I remembered that I read once in a book that teaches
try to use composition as far as you could. I forgot the reasons now, anyone could give the hint?
I had been confused same as you until I found this explanation:
Inheritance is Bad: Code Reuse Great example where author explain inheritance based on example typically used to show why inheritance is "great".
Favor 'object composition' over 'class inheritance'. (Gang of Four 1995:20)
Read the book
Related
Considering the Law of Demeter, Single Responsibility Principle and Tell, Don't Ask principle; What is the correct relationship between the Article and Comment class?
A: The Comment is a concern of Article class. It can Read, Create, Update and Delete comments. The Comment class itself is just a read-only representation of the Comment concept.
B: The Comment is a concern of HandleComments class. It can Create new comments and assign them to the respective articles. It can also Read, Update and Delete comments. The Comment class itself is just a read-only representation of the Comment concept.
C: The Comment is not a concern of neither Article or HandleComments classes. It has all the CRUD functionality by itself. It can Assign itself to an article as well.
D: The Comment could be a concern of either Article or HandleComments classes; However they can only Read, Create and Delete comments. The Update functionality is a concern of Comment class itself.
Update #1
Here is how I think about it, however can't really find answers because all of my reading ends up to a non-practical or very simple proof-of-concept examples:
Do I have to have readComment, createCommnet, updateComment and deleteComment classes? According to Bertrand Meyer classes with Verbal or PerformSomething names are signs of danger as they could be methods not classes. So it is okay to have only Article and Comment classes with all of their respective functionality inside themselves?
The Article and Comment doesn't have a is-a relationship, so obviously no inheritance here, but they have a has-a relationship. I'd go for Composition then, but who's responsible for what? If I am a Comment then this is my concern to Update myself, right? But is that the Article's concern to Delete me? Hence I'm attached to it.
Is it the concern of Article to load its Comments? Or there should be a man-in-the-middle class to handle the relationship between the Article and Comment? If the Comment has loaded by the Article then is it a concern of Article to be 100% responsible for all of the Comment actions?
Update #2
More thinking about it, what I really want is Loosely-Coupled classes as much as possible. In any case the Article class should have a list of Comments to iterate between them. In order to assign a Comment to an Article, I should either pass the Article reference to the Comment constructor -- the bottom-top way, or I should pass the Comment reference to the AddComment method of Article class -- the top-bottom way.
I prefer the Bottom-Top-Way, even tho it looks awkward in the first sight, because then I can have all the other Comment actions also within the Comment class itself, so the Article class will be totally unaware of Comments class. The only thing the Article class should have is an internal array to hold the Comments instances. No need to have AddComment, RemoveComment methods to the Article class.
Is it something that makes sense?
Without knowing a lot more about the system it's difficult to answer your question (bar the specifics in update 2). It's possible, for example, to think of comments referencing articles, or articles referencing comments. With more details, especially use cases, it's likely that one design would likely come out in front.
Nevetheless, in the absence of further information, it's your second bullet point, composition, which strikes me as most natural. To wit, articles have a list of comments, as well as a title, a body, etc. You might or might not have a CommentsList intermediate class. In any case, you can create, delete, and get references to comment objects. Comments have text, links, formatting, etc.
Re update 2, I agree that loose coupling is desirable. However I disagree that passing a reference to an Article to the Comment constructor makes sense, all other things being equal. This introduces a cyclic dependency -- because the Article has a list of Comments -- and also therefore a higher degree of coupling than would be the case if you took the alternative "top-bottom" approach of passing the Comment to the AddComment method of the Article class.
With this "top-bottom" approach, the Article could either have a NewComment method, in which case the Article itself creates the Comment object, or it could have an AddComment method as you suggest. Which is preferable depends on the details of the requirements: for example a requirement to have different kinds of comments (or even to share comments between articles) would suggest the AddComment approach.
Thanks to Bart comments, I decided to go for the Repository Design Pattern, which seems to be one of the battle-tested patterns for handling this kind of cases.
The general idea is to have a Repository which is responsible for taking care of Comments. So in a broader view a Blog should have at least a postRepository and commentRepository to take care of blog Posts and Comments functionality.
It is also recommended to handle all of the List like data with repository pattern, when there is a need for a kind of central-functionality. In the Blog example, it make sense to have repositories for Categories, Tags, Users, etc. as well.
What is a good gauge for knowing when a class is poorly designed or even necessary. In other words when to write a class and when no to.
SOLID might help if a class is poorly designed, but it won't help answer a question like "Is object-oriented programming the best approach for this problem?"
People have done a lot of very good work in programming for mathematics and science before object-oriented programming came into vogue. If your problem falls into those categories, perhaps object-oriented programming isn't for you.
Objects are state and behavior together; they tend to map onto problem domain objects one-to-one. If that's not true for your problem, perhaps object-oriented programming isn't for you.
If you don't know an object-oriented language well, perhaps object-oriented programming isn't for you.
If your organization doesn't know and can't support object-oriented solutions, perhaps object-oriented programming isn't for you.
A lot of people will say the "SOLID Principles" are a good guideline for class design.
There are a lot of articles/podcasts concerning the SOLID Principles, just do a quick search. Here's a good start:
http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
rather than list a bunch of don't-do-this rules for recognizing a poorly-designed class, it is easier - and more efficient - to list the few rules governing a good class design:
a class is a collection of related state and behavior
the behavior should use only the state and method parameters
if you think about the state as a relation (i.e. as the columns in a relational database table), the object ID (pointer) is the primary (synthetic) key and the state comprises the non-key attributes. Is the object in third normal form? If not, split it into two or more objects.
is the lifecycle of the object complete? In other words, do you have enough methods to take the object from creation through use and finally to destruction/disposal? If not, what methods (or states/transitions) are missing?
is all of the state used by at least one method? If not, does it provide descriptive information useful to a user of the object? If the answer to both of these is no, then get rid of the extraneous state.
if the problem you're trying to solve requires no state, you don't need an object.
On top of the SOLID principles, have a look at Code Smells. They were mentioned first (IIRC) in Martin Fowler's "Refactoring" book, which is an excellent read.
Code smells generally apply to OO and also procedural development to some degree, including things like "Shotgun Surgery" where edits are required all over the codebase to change one small thing, or "Switch Case Smell" where giant switch cases control the flow of your app.
The best thing about Refactoring (book) is that it recommends ways to fix code smells and takes a pragmatic view about them - they are just like real smells - you can live with some of them, but not with others.
I know there are LOTS of reasons why you would compose a certain object inside another one. Some schools of thought have made explicit the reasons for architecting a program a certain way e.g. 'data-driven design' or 'domain-driven design'. I'm still a beginner to OOP, and it's often hard for me to understand why one object should be contained by another. Sometimes, I find myself with an object that seems awesome, and then I get to the point where I realize, "Okay, now I have to put this somewhere?" Is the reasoning behind this similar to where I'd decide put a file on my hard disk?
I have a couple guiding principles for this:
If it models a relationship in the physical world.
If the composer has data needed to construct the object.
If the composed object will be listening to the composer.
What do you look for when you make this decision?
Well, one very simple concept that helped me with this is simply the concept of "has a" versus "is a". Ask yourself, is the contained object something the containing object has, or is it something the containing object is? If it's something the containing object has, then containment is appropriate. Otherwise maybe you should be looking at inheritance.
A dog IS an animal, and has a nose, so it's:
class Animal
{
}
class Dog : Animal
{
Nose n;
}
Now this works fine. One "problem" with this approach is that you tightly couple noses and dogs, so sometimes you'll see things like containing an interface pointer rather than an object, or you might Google "Dependency Injection". But as the saying goes, "has a" and "is a" is often close enough for government work.
Early on, just try lots of examples and over time it will become natural. If you end up with spaghetti, throw some meatballs at it and try again! :)
What alternatives are you considering? Are you talking about Containment versus Inheritance, John Lockwood's comments about hasA and isA help with that issue.
Or are your perhaps talking about, Containment versus Association? There are various flavours of hasA. For example a Person may haveA Spouse, but clearly does not containA Spouse. There's a difference between changing a Spouse and changing a Nose.
The kinds of relationship that you consider:
Lifetime: Does it make sense to create a Person without a Nose? Can Noses exist without a Person? Can a Person exist without a Spouse? The answers to these questions drive the kind of operation you choose to have on Person. Probably don't need a setNose() method, though maybe we do need a wipeNose() method, and we probably do need a marry(Person) method.
Cardinality: How many Noses for a Person? How many Wheels and Seats does a Vehicle have? Answers to this determine the kinds of data structures? Just a reference? A list? An hash table?
I found it helpful to read about UML modeling, especially class diagrams. This reflects much experience of how to usefully capture various kinds of relationships.
Sometimes, I find myself with an
object that seems awesome, and then I
get to the point where I realize,
"Okay, now I have to put this
somewhere?"
From the above sentence, it sounds like you're trying to design from the bottom up. One of the thing's I've learned over the years is that top down design is the way to go. You should only write the class after you know where it needs to be used. Otherwise you just end up writing classes that "seem awesome" and contain code that might not be useful at all.
I've read all the books about why to create a class and things like "look for the nouns in your requirements" but it doesn't seem to be enough. My classes seem to me to be messy. I would like to know if there are some sort of metrics or something that I can compare my classes to and see if there well designed. If not, who is the most respected OO guru where I can get the proper class design tips?
Creating classes that start clean and then get messy is a core part of OO, that's when you refactor. Many devs try to jump to the perfect class design from the get go, in my experience that's just not possible, instead you stumble around, solving the problem and then refactor. You can harvest, base classes and interfaces as the design emerges.
if you're familiar with database design, specifically the concept of normalization, then the answer is easy: a data-centric class should represent an entity in third normal form
if that is not helpful, try this instead:
a class is a collection of data elements and the methods that operate on them
a class should have a singular responsibility, i.e. it should represent one thing in your model; if it represents more than one thing then it should be more than one class.
all of the data elements in a class should be logically associated/related to each other; if they aren't, split it into two or more classes
all of the methods in a class should operate only on their input parameters and the class's data elements - see the Law of Demeter
that's about as far as i can go with general abstract advice (without writing a long essay); you might post one of your classes for critique if you need specific advice
Try to focus on behaviour instead of structure. Objects are 'living' entities with behaviour and responsibilities. You tell them to do things. Have a look at the CRC-card approach to help you model this way.
i think Object design is as much art as it is science. It takes time and practice to understand how to design clean & elegant classes. Perhaps if you can give an example of a simple class you've designed that you aren't happy with SO users can critique and give pointers. I'm not sure there are any general answers outside of what you've already read in the texts.
The most respected OO guru i personally know is StackOverflow. Put your classnames here and i reckon you'll get a goodly number of reviews.
Classes are typically used to model concepts of the problem domain. Once you have a well-defined problem (aka the set of use cases), you will be able to identify all participants. A subset of the participants will be intrinsic to the system you are designing. Start with one big black box as your system. Keep breaking it down, as and when you have more information. When you have a level where they can no longer be broken down (into concepts in your problem domain), you start getting your classes.
But then, this is a subjective view of a non-guru. I'd suggest a pinch of salt to the menu.
Metrics? Not so's that you'd trust them.
Are your classes doing the job of getting the program working and keeping it maintainable through multiple revisions?
If yes, you're doing ok.
If no, ask yourself why not, and then change what isn't working.
Is there a name meaning "not a singleton"?
Castle Windsor uses the term "transient" to describe all non-Singleton objects.
I personally prefer the term "non-Singleton" though.
Yes, there is a Multiton pattern, but it means something very specific. It's not simply everything that's not a Singleton.
Prototype.
It is used as a scope in Spring framework to identify dependency which will always be new instance when injected.
When someone asks me if a class is a Singleton (and it isn't), I just say no, it's a regular class.
Multi-Instance ?
http://elegantcode.com/2008/04/17/the-opposite-of-a-singleton/
Actually, there is a variant on the Singleton called Multiton or Multiplton or something like that. Rather than having one instance, you have n instances where n is a specific value. I'm not sure if the Gang of Four describe this application in their book, but I learned about it in my Software Engineering 361 class.
But if you have an unconstrained number of instances, I don't think there is a name for it.
Simply, a 'Single Instance of a Class.'
This is an old post, but if someone still comes across then a better word is "multiplex" over "transient". IMHO
Definition:
noun:
a system or signal involving simultaneous transmission of several messages along a single channel of communication.
There is a related thread about this over at English Language & Usage. Looking through the various suggestions posted there, I think the best one is
replicant
I've adopted this term in the naming of methods and the wording of comments in a little PHP Reflection factory I've built.
How about the word "Instanced"