I’m reading a book that explain that it is a good thing that classes have a single responsibility, that is, that they do a single thing.
I can understand how to implement this in some cases I personally faced:
– I needed an array of 6 countries returned to the model, so it can use it in the views… So I designed a class to do just that and only that. The class contained a few functions, each with a single task.
But what if I need in a game, a class “monster” that is responsible for the “monster” entity in the game. The monster can “attack”, “hide” and “sleep”.
That’s 3 responsibilities, isn’t it ? Then in this case, how to organize that monster class while still respecting the single responsibility principle ? I don’t get it.
4
Single Responsibility Principle means a class should only have a single “responsibility.” This does not mean one “action” or one “attribute” however.
If I were to write down a list of what a monster in a game might need to do, I may come up with a list such as this one:
- Monsters have attributes such as health and attack power. These attributes may change as the monster takes damage, or perhaps it can pick up a different weapon.
- Monsters have an AI that governs its actions and differentiate dumb little monsters with tougher, smarter monsters.
- Monsters need to be displayed on the screen somehow.
There are multiple responsibilities here. Clearly, “having health” and “having attack power” are not different responsibilities: they are both attributes that define what a monster is and how tough it is compared to other monsters.
The AI might be different responsibility. Perhaps a game has 200 types of monsters, and 10 different AIs. Different types of monsters might be grouped and act similarly: the AI does not need to be recoded each time, it can be shared. How the monster acts might be a responsibility of the AI, not the monster itself! For example, in the Diablo series of games, the Fallen (cowardly little imps) all act pretty much the same despite having slightly different appearances and different toughness.
Displaying a monster on the screen is a great application for an adapter object that has its own single responsibility: figuring out, for a given monster; where it is located, what state it is in (swinging its weapon, running, standing), and generally how it should look on screen.
In this example we might have a core monster object describing the current state of the monster, a pluggable AI that governs its actions, and an adapter object that knows the current visual state of the monster and can produce its graphical state to the graphics subsystem for display on screen.
Note that this analysis does not dig down to the level of individual functions or methods. I analyzed this at a higher level than that: getting bogged down in the nuts and bolts of the implementation is a bad idea when defining object responsibilities. Once those responsibilities are defined and you move on to the low level implementation details, of course you need to write the attributes and functions to support those responsibilities.
3
You need to consider how we use the word responsibility. If you are responsible for a child, that is a single responsibility. We all know there are many tasks you’ll have to perform to maintain that responsibility.
So for your example of a Monster Class. You would only have functionality and data that pertains to the Monster. A monster has health and once the monster dies, the health value is gone from the individual monster, but could be recorded in some history. If you put the history in the monster class, you would lose it. If the monster was carrying a club, that would be a separate object that was possessed by the Monster, but upon the monster’s death, the club would now be without an owner in some place another object could obtain possession. There’s no law that says you have to do this, but if that was something you wanted to happen in your game, you’d have to figure out a way to maintain objects possessed by people but can still be available when the possession is lost. The monster can’t take it with him.
So try to think in the perspective of what behaviors you want. If you find you’re making changes to the monster because you want to change the club, you are getting out of the responsibility of the Monster class managing a monster character.