If I`m programming a game in which there is a worker that cuts wood (from trees), where would I put the "cutWood" method, in the worker class, or the tree class?
EDIT: The first example I read on OOD was about a circle (a class called circle) which has in it a method called "calculate area". Now, sure enough a circle doesn't calculate its own area. The only way to think of it is that calculating area is an operation that is relevant to the circle (an operation done on the circle)
So, cutWood method is relevant to both, the worker, and the tree.
-
A circle doesn't calculate its own area? Hmmm. I think you may have misread the example: doing something that no other object is needed for, and for which the class has the most knowledge (i.e. the radius), is EXACTLY what should go in a class. Where it gets debatable is things like circle.draw( ScreenObject ) -- should a self-contained class know about the details of a particular graphics system?Rodney Gitzel– Rodney Gitzel2010年09月30日 22:51:59 +00:00Commented Sep 30, 2010 at 22:51
-
You might be mixing up OOP and DDD. OOP is procedural programming with the additional aspects of inheritance, composition, and polymorphism (all very powerful, and with a litany of techniques for best-usage). However! It's DDD which insists that you model your entities and their interactions around real-world things and actionsSTW– STW2010年09月30日 22:52:15 +00:00Commented Sep 30, 2010 at 22:52
-
It's stupid stuff like this that makes object-oriented programming ridiculous. No wonder functional programming is making a comeback.duffymo– duffymo2010年09月30日 23:09:04 +00:00Commented Sep 30, 2010 at 23:09
-
1@Rodney Gitzel It's a circular argument without more knowledge of the actual problem. Does a graphics engine do element.Draw() or drawer.draw(element) or both?codelark– codelark2010年09月30日 23:09:31 +00:00Commented Sep 30, 2010 at 23:09
-
I'd recommend you study the SOLID OOP principles. Here's a great course offered on Udemy that I think can help you advance your design skills: udemy.com/mastering-object-oriented-design-in-java/…Horse Voice– Horse Voice2015年01月13日 20:23:35 +00:00Commented Jan 13, 2015 at 20:23
12 Answers 12
I don't see any cohesion to have a wood cutting method in the worker. The cutting is done on the tree, and should therefore be part of the tree class. Presumably, cutting the wood will also involve changing some internal state of the wood class too.
A worker should call the cut method on whatever tree he wants, rather than the tree telling the worker that he should cut it. If you want to abstract this like Hans has hinted at, you could make an ICuttable interface for the Cut method, and have your tree implement it.
Consider something you're familiar with, a String. When you want to cut a string (split), you don't define a splitString method in every object which is going to do this. Whatever object decides to split the string, the same thing takes place - and will usually need to know the internals of the target object (the string) in order to do it. Many other objects simply call the split method of the string. The string object has high cohesion - because it's methods contribute to a common task - manipulating strings.
I don't see how cutting wood contributes much to the worker object itself.
Comments
Ask yourself: Do workers cut wood, or do trees cut wood?
3 Comments
You basically answered it in your question: "a worker that cuts wood". You should put it to the worker class.
5 Comments
doWork(), which takes an IWorkable object, which exposes a single work() method, which then calls the internals required to do that work? I mean, if we're going to be concerned with that level of extensibility, we should take it to its logical conclusion.Create a
cut(Material m)
method for the worker for extra object-orientedness.
do you have to modify the tree as it is being cut?
do you have to modify the worker as it cuts a tree?
i would imagine you'd end up with a WoodCutting service which handles the event possibly modifications to both, or in turn calling worker.cutWood() AND tree.woodCut()
ahah what a question ;)
Comments
Sounds like a candidate for the Strategy pattern to me. You may need a WorkerAction abstract class with a performAction method. Then subclasses of the WorkerAction class will implement the details such as cutting a tree, digging for gold and other worker actions. So the sub class knows about the details of the tree and can call the necessary methods on the tree to affect the tree as it is being cut.
The worker class then only need a reference to an instance of a concrete WorkerAction on which it calls performAction(). The worker does not know the details of the Tree or the Gold etc. This way the worker can perform the action but you are not limiting the worker to only one action. In fact you no longer need to modify the worker class if you want your worker to do more actions in the future.
2 Comments
You could have a cutWood method in the worker class, and a cutted method in the tree class. Obviously, worker.cutWood calls tree.cutted, which might return the amount of wood harvested.
tree.cutted would do all the stuff that is necessary to let the tree die.
If you consider method calls as "messages sent from one object to another", it makes a lot more sense to say "the player sends a 'cut wood' message to the worker who in turn sends a 'cut' message to the tree".
Comments
Object design is all about assigning responsibilities to your classes. That means there really is no good answer to this question. As it all depends how you model the responsibilities in your design. (see: Larman)
Thus you need to decide what object/class is responsible for what. This will lead you to correct answers on question about were to place what kind of methods.
Thus ask you’re selves questions like: does the worker decide on his own to cut wood? If he does, he probably does not need to be ordered so, thus he will not have a need for a method cut(tree). But if the user can order him to do that, he will need a cut(tree) method. An other example: does the tree have to know he is cut? Well, if a cut tree just leads to his removal from the forrest, he might not have a need for such a tree.cut() method. But if you assign to the tree the responsibility to (re)draw himself during cutting, you might have a need for a tree.cut() method. The tree could even be modeled as having a width and that he can calculate how many cuts are needed before he collapses.
Comments
Since a single worker might cut more than one tree, it sounds more likely that you'd want to put cutWood() in the worker class.
Comments
Doesn't the cut() method go on the Saw object?
More seriously, I think of the target of the method call as the "subject", the method itself as a "verb", and its parameters (if the verb is transitive) as "direct objects." So, in this example, it would be worker.cut(tree).
Comments
This question can only really be answered if you explain what cutWood does.
If cutWood only affects the state of a Tree then it belongs in Tree e.g.,
public void cutWood() {
this.height = 0;
}
In the case of calculateArea you only need the radius of a circle (assume pi is constant) to do this calculation - nothing else. That's why it belongs in Circle.
Stop trying to model the real world too closely and look at what your method actually needs to do.
Comments
This is an intresting topic. I thought about a likewise scenario myself sometimes. I think a good way to go, is to put the method into the class with the highest cohesion. Therefore the Tree class would be the first choice. On the otherhand if you try to match a real world model i would say the Worker class has to be able to perform some kind of actions which includes cutting a Tree. I often find myself in these kind of situations and wonder where is the right place to put this method. Another approach would be a class which knows about worker and tree's, and therefore handles the cutting tree meachnism. This way both classes (tree,worker) would not know anything about it.