Pointers to an instance's owner

Started by
7 comments, last by Bruno Sofiato 11 years, 4 months ago
I have a question about the following design

class Unit {
Manager *my_manager;
...
};

class Manager {
vector<Unit> unit_list;
...
};

In the interest of encapsulation the Unit handles it's own actions (e.g. movement), the pointer to the manager is then required so that the unit can interact with other units (e.g. colliding). It feels like it's a hack, I've added in the pointer in the absence of a better design strategy. Is this an intelligent way to structure my code, or should I be looking for a different design pattern?

I'm from a Maths/Science background and so while I have done quite a bit of programming (FEM, graph theory, simulations) I haven't formally learned application programming. If there is a good book on how to design/structure a program that is more than just datain->process->dataout I would love to hear your recommendations.
Advertisement
Bi-directional dependencies (Unit uses Manager but Manager also uses Unit) are a kind of "code smell": not necessarily a problem, but may indicate there's something wrong with the design.

One small step that you can try to take is to remove that member variable, and instead pass the manager as an argument when using the Unit. This is still a bidirectional dependency, but a little weaker.
class Unit {
void DoStuff( Manager* );
};


If Units need to access each other for collisions, perhaps you can move the collision logic out of the Unit and into the Manager?

Alternatively, you can pass in the parts of the manager that the unit needs, instead of the whole manager:
class Unit {
void MoveWithCollisions( const vector<Unit>& others );
};
Thanks. I did think it smelled a bit fishy. I believe I have some thinking to do...
In my experience, this tends to go beyond even a code smell. It's an outlet for the instance to get at more things than even the manager. And there will be times when you want the object (even temporarily) not to be owned by anything. And keeping the collection and pointer synchronized is a little tricky once you start dealing with concurrency, serialization, and network operations.

In the interest of encapsulation the Unit handles it's own actions (e.g. movement), the pointer to the manager is then required so that the unit can interact with other units (e.g. colliding)


This right here is your problem from a design perspective. You say that the unit handles it's own movement "in the interest of encapsulation", but then immediately after state that the manager is required.

By definition, the units movement cannot be fully encapsulated as it requires external information to function correctly. The unit cannot move independently (it has to handle collisions etc). As Hodgman said, it might be better to move the unit movement logic out of the unit and into the manager.
if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight

By definition, the units movement cannot be fully encapsulated as it requires external information to function correctly. The unit cannot move independently (it has to handle collisions etc). As Hodgman said, it might be better to move the unit movement logic out of the unit and into the manager.

+1, for instance the unit could expose its movement capabilities (range, etc...) to the manager, which will then use that information to move it correctly within the world, which allows you to abstract away unit types more comfortably.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

My take

I'd scrap the manager, at least for know, and create an Unit class hierarchy. It's a responsability of Units knowing what they are capable of doing, perhaps by returning a set of Actions. But the catch, to know which Actions they're are capable of doing, they must be supplied a context, or a World, the World responsability is to provide methods to query the spatial state of the Things (which can be Units) within itself.

Its a crude design, but I would start it like that.

I'd scrap the manager, at least for know, and create an Unit class hierarchy.


How does creating a Unit hierarchy help here?
if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight
Seems to me that the propose of the manager class as presented was to manage all the possible movements and iterations from every kind of units. (I'm assuming there're many kind of units), by doing so it would be coupled to every type of unit given. By moving the the movement logic to an Unit class hierarchy, this coupling is eliminated.

But you're right, external information must be given to an unit so it can know which movements they´re capable of doing within a context that is given in a World class object (which is similar to the manager concept, but with diferent responsabilities).

P.S. On this rationale, I was think on a board gaming, something like chess or checkers, maybe to other kind of games, those concepts would not cut ...

This topic is closed to new replies.

Advertisement