I\'m trying to understand object orientation. I understand it a little bit of course, but sometimes I\'m not 100% clear. How do you decide what should be turned into an object (
As long as the object has only one purpose/responsibility is should not be divided anymore (unless it is too large which should not be the case).
Make objects as long as you can divide and conquer them after that. If you make to many small objects you will not be able to handle well all. On the other other side to few big objects cannot be reused easily.
My advice: practice! While practicing you will get a sense of what granularity you need - there is no general rule for this.
I answered this already in another question
Code objects are not related to tangible real-life objects; they are just constructs that hold related information together.
Don't believe what the Java books/schools teach about objects; they're lying.
Just write something that gets the job done, even if it's ugly, then refactor continuously:
But:
If you don't end up with massive (and useless) class hierarchy, then you have done a good job, producing elegant and clean code.
Remember: OOP is a means, not an end.
As always, the answer is unfortunatly: it depends...
At the beginning, you have some sort of environment and you want to create a model for it. But you would not model every thing, you'll concentrate on the important things. That's why I started with: it depends. It depends on what details you need to accomplish the task.
Take the car and it's wheels - if you model a city and want some traffic, you may create a 'Car' class with the attribute 'numberOfWheels'. But if you design cars, then you most likely want to create a class 'Wheel' aswell and add four of those to the 'Car' class.
Rule of a thumb:
Edit
Because you emphasized the 'multiple usage' aspect: I don't think that this is an aspect for a decision whether to use a class or not. Think of a simple counter, an integer value in a for loop. You'll use this concept hundreds of times but I bet you'll never think of wrapping this poor little int
into a 'Counter' class - just because you use the 'concept of a counter' multiple times.
This depends a bit on the usage. To go with your example, if the doorknob is an important part and could (potentially) be used on another door (or a different knob be used for 'this' one) then it should probably be an object.
If on the other hand it is only there to allow you to open and close the door, it should simply be a part of the door object.
Everything can be made into an object.
IMO, the answer to your question is the question - Is the behaviour of the key-hole necessary for my model of the door to be an accurate representation?
When the answer to the above is in the affirmative, go ahead and incorporate it. When the answer to the same question is in the negative, then I'd choose not to.
There is theory and then there is practice... and then there is you as a software engineer trying to balance them both.
In theory you should make objects pretty much everything until you fall down to the smallest possible elements, the primitive types (boolean, string, integer etc). Well.. it is rather simplistic but with this one rarely goes wrong...
that is...
until you actually get to create (that is code the classes) the thing.
On the practical end of the spectrum you can define all in one big class and be done with it... that is... until you have to define subtle change in behavior (outside door, garage door, dog door etc).
My approach is to usually start with the one big class (ugly but it's fast to code and I can get a working prototype faster). Then if I ever need to define ajustments or new behaviour or reuse some part of the whole then I create the smalle element and refactor the big one to use the smaller one instead of defining it's own attributes.
For example. I code the door class, and from there I can create (instantiate) as many door as I want but they are all the same and behave the same. Now I realize that I need to also define windows that swivel around hinges... wait a minute... the door`s got hinges also. This is where I create a hinge class that can be used by both Door and Window and remove whatever way I had before to define a hinge in the door class. Then continue working until I encounter a situation where I can reuse some parts across multiple objects (the handle, the frame, etc).
With this rule of thumb I can get the code fast and usually it converges to a level of granularity that is sufficient for the needs at hand.
Then with experience you get to have a fair idea of on deep you want your objects granularity without having to constantly re-factoring your objects which is time consuming. However I found that the re-factoring is time consuming but never as much as designing the thing all the way down right from start. Re-factoring is almost inevitable, as such better to start re-factoring early and often.
anyways... my two cent, I hope it helps.