Maybe I am totally wrong but here is what is in my mind. Most of the books that describe object oriented programming, architecture or whatever are making examples using “objects” like person, cat, mammal and then big hierarchy of classes. Of course, more advance books are explaining why huge hierarchy of classes can be wrong and why it is good to use composition. I will not even try to explain that in this post.
And then having these classes you can read about different aspects of OOP. Some of the examples can be:
dog.bark()
person.walk()
person.openDoor()
engine.start()
And I agree that these are almost great examples (except person.openDoor() where I will come back later on).
So let me try to explain where are I am aiming with me question (in the caption of the post).
For learning OOP these may be good examples but from my experience so far these are cases that I don’t meet so often in practice.
Let try one example. Imagine class Can (not verb but noun). Coming from the examples above one could model method: Can.open(). Uhmmm, is it really possible that Can is able to open itself? I wouldn’t say this is reality.
So what is solution here? Quite straight forward. Model a class CanOpener. Then model method CanOpener.open(Can can). This is now much closer to reality.
But what is Can and what is CanOpener from the programming point of view? Well I would say:
Can - is data
CanOpener - is service
And in most of the projects this is what I meet. Most often you are working with data and then perform something on that data. If you try to model your solution as explained at the beginning of the post you will finish with domain classes that have hundred of methods and probably thousands of lines. But very often domain classes are just data while services are actually performing real work. But be careful not to fall into trap of procedural programming.
So come back to example from the beginning: person.openDoor(). As I mentioned this is not good example. And again I would model this quite differently:
Door
DoorOpener (interface)
Person (implements DoorOpener)
It is clear that doors can be opened by person, but they can be opened by engine or wind. So “item” that is able to open door is again service while door is just class keeping data (entity). And yes, you need to add code to open door into Person but again this can be great situation to use composition.
I hope I successfully explained how I try to model solutions for programming problems.
And just short note at the end. Please do not add Service, Manager or similar words at the end of class name. It can easy trap you into procedural programming as you will place too much responsibility into those “managers”.
And then having these classes you can read about different aspects of OOP. Some of the examples can be:
dog.bark()
person.walk()
person.openDoor()
engine.start()
And I agree that these are almost great examples (except person.openDoor() where I will come back later on).
So let me try to explain where are I am aiming with me question (in the caption of the post).
For learning OOP these may be good examples but from my experience so far these are cases that I don’t meet so often in practice.
Let try one example. Imagine class Can (not verb but noun). Coming from the examples above one could model method: Can.open(). Uhmmm, is it really possible that Can is able to open itself? I wouldn’t say this is reality.
So what is solution here? Quite straight forward. Model a class CanOpener. Then model method CanOpener.open(Can can). This is now much closer to reality.
But what is Can and what is CanOpener from the programming point of view? Well I would say:
Can - is data
CanOpener - is service
And in most of the projects this is what I meet. Most often you are working with data and then perform something on that data. If you try to model your solution as explained at the beginning of the post you will finish with domain classes that have hundred of methods and probably thousands of lines. But very often domain classes are just data while services are actually performing real work. But be careful not to fall into trap of procedural programming.
So come back to example from the beginning: person.openDoor(). As I mentioned this is not good example. And again I would model this quite differently:
Door
DoorOpener (interface)
Person (implements DoorOpener)
It is clear that doors can be opened by person, but they can be opened by engine or wind. So “item” that is able to open door is again service while door is just class keeping data (entity). And yes, you need to add code to open door into Person but again this can be great situation to use composition.
I hope I successfully explained how I try to model solutions for programming problems.
And just short note at the end. Please do not add Service, Manager or similar words at the end of class name. It can easy trap you into procedural programming as you will place too much responsibility into those “managers”.