Reputation: 495
I've read in a lot of places that SRP is a good principle to apply, and I wanted to apply it in my projects.
Actually, it's a game, and my objects have basically two functions update
and draw
, so they have two responabilities (defined as a "reason to change"). It could look like this:
class Object {
public:
void update() {
// implementation...
}
void draw() {
// implementation...
}
};
Let's say I choose to use the Component design pattern to split update
and draw
into an UpdateComponent
and a DisplayComponent
, the object which uses these component will still have the pair update
/draw
, but not their implementations anymore. So it could look like this now:
class Object {
public:
void update() {
m_updateComponent.update(*this);
}
void draw() {
m_displayComponent.draw(*this);
}
private:
UpdateComponent m_updateComponent;
DisplayComponent m_displayComponent;
};
In this implementation, are update
and draw
considered as responsabilities of the components and of the object, or only the components so the object agrees with the SRP?
Upvotes: 0
Views: 267
Reputation: 54781
You have considered the "reason to change" and moved it. Now if either the drawing or updating needs to change, you do not need to change the Object
class. That is all inline with SRP.
However, you have some unnecessary coupling. You can tell because of the two way dependancy between DisplayComponent
and Object
. Why does the Object
need to know about (depend upon) its DisplayComponent
or even it's UpdateComponent
?
You have:
DisplayComponent <--> Object
(the lines represent a dependency, i.e. you can't compile one without the other it is pointing at)
You only need:
DisplayComponent ---> Object
But then how would you get to the DisplayComponent
to call draw
, if you can't do that from the object?
ObjectContainer --\
--> UpdateComponent ---> Object
--> DisplayComponent --/
So I have introduced a new ObjectContainer
class that knows about (depends upon) UpdateComponent
, DisplayComponent
and Object
.
Your outer game loop only has access to ObjectContainer
s and can only change game state via m_updateComponent
and draw via m_displayComponent
. Object
's only responsibility now is to persist the state of the object:
class Object {
public:
//getters/setters maybe
private:
int x;
int y;
float speed;
float health;
//etc
};
class ObjectContainer {
public:
void update() {
m_updateComponent.update(object);
}
void draw() {
m_displayComponent.draw(object);
}
private:
Object object;
UpdateComponent m_updateComponent;
DisplayComponent m_displayComponent;
};
The above ObjectContainer
is very similar to your Object
, but there is no two-way dependency.
Upvotes: 1