3 ms·
Except I find the concept of state "doing something with" other state unhelpful. Why is bar working with baz and not baz working with bar? I struggle with thi
by SebastianKra 4y ago
Except I find the concept of state "doing something with" other state unhelpful.
Why is bar working with baz and not baz working with bar?
I struggle with this in Unity:
Player.collect(PickUp) // this?
PickUp.boost(Player) // ...or this?
Instead, the code should describe the interaction between the two units of state:
onCollide(Player, Pickup)
If we structure our code like in the last example, it makes sense to weaken the `a.b` vs `b(a)` distinction, and instead use the dot as a kind of pipe-operator.
- tsimionescu 4y agoIt shouldn't be that confusing. Ideally, a method should be defined on an object only if it needs to access the encapsulated state of that object. Otherwise, it should probably be a free function. So, in your case, depending on other modeling decisions, I could argue either for onCollide(Player, Pickup) - if Player and Pickup are both plain data, and don't need to guarantee any invariants Player.collect(Pickup) - if Player actually has to ensure some invariants such as health<100) I don't see any good arguments for pickup.boost(Player), in typical games. Of course, if both the Pickup and the Player have some invariants that need to be maintained on a collision, then arguably the design has to be changed at a deeper level.
- Y_Y 4y agoBut this isn't a discussion about pickups specifically. Attacking an example is pointless if the thing you take issue with is incidental and not fundamental to the argument. I bet you could think of a case where you pick something else and OP's example meets your standards.
- tsimionescu 4y agoMy point was that there is a meaningful, and I believe relatively simple, distinction to be made between free functions and methods bound to an object - a distinction which UFCS doesn't really help with. For any given example, I believe there is a reason to prefer one over the other, and I showed what reasoning I would use for the particular example raised by OP.
- SebastianKra 4y agoI got that and it's a good point. Although I rarely see Objects used this way. Often, methods are used to implement all related functionality. Unity even strongly encourages this. (...at the moment. They are working on Entity Component Systems which will work more similar to my third example) I concede that languages shouldn't use the dot as a syntactic tool, be it through Extensions[1] or UFCS, but rather offer a pipe-operator. If they don't, I'd still prefer UFCS rather than no way of chaining at all. [1] Extensions for interface/protocol conformance are fine of course.
- zmgsabst 4y agoI think which of the three is best depends on the context: What is the code driving it? - looping over players to update them? - looping over objects to update them? - some other event loop? I actually like the third least: The first two tell me what is happening, but the third doesn’t — I could be colliding to block motion or I could be picking up.