I'm working on a networked game. I have tried to design the various components (client, server, engine) to only about things within their domain. For example, the server should only be concerned with handling packets and connections, not about entities within the game engine, or handling hardware events on the client-side. I haven't been able to find a nice way to stitch these domains together cleanly, because ultimately, an entity moving in the game world does eventually need to be represented to the user in some way. That's a related question, but perhaps not the core of this one.
With this in mind, I've been looking at some of my classes, and have wondered if they were designed in a clean way.
One example I have is a Party
class, that represents a group of Pokemon (pets to battle with). My initial design looked something like
// Max number of Pokemon is 6.
public interface Party {
Set<Pokemon> getPokemon();
void add(Pokemon pokemon);
void remove(Pokemon pokemon);
boolean contains(Pokemon pokemon);
boolean contains(Species species);
int getNumberOfPokemon();
}
Most of the methods within the interface expose the Party
's state. The client code was expected to check if the number of Pokemon within the party is less than 6, and if so, it was allowed to add
to the party; as well as checking that there were at least 2 in the party before remove
was called. I simplified it a little bit in an effort to expose less of the object's state, and was left with
public interface Party {
boolean hasRoom();
void add(Pokemon pokemon);
void remove(Pokemon pokemon);
}
A Party
is used in many places across the domains of the code. For example, there's a view on the client side that shows the user what is in their Party
. It's also stored in a repository.
Should the Party
class know how to send itself to the client, and repository?
public interface Party {
// ...
void saveTo(PartyRepository repo);
void showUITo(Client client);
}
Sure, doing it that way keeps the state of the party locked within the object, but then you run the risk of having lots of almost-god objects, who know everything about how they're used.
One alternative I had thought of was to split the Party
into two separate types, one specifically designed to represent the state, and one to represent behavior. But seeing as a Party
is just a collection of Pokemon, it would really just be something like
public interface PartyDTO {
Set<Pokemon> getMembers();
}
public interface PartyBehavior {
void add(Pokemon pokemon);
}
That still doesn't feel right though because then which one is the Party
? I'd still be manipulating the state of the PartyDTO
class through the PartyBehavior
class, so I don't feel like I'm really gaining anything.
Is this something that should be done? What alternatives are there?