Ok.. I think it would help if I create a scenario that demonstrates my
ideas. Let's consider the use case of adding a comment... here's the
sequence of events as I see it:
Mach-II bundles up the comment form info into a CommentTO
ArticleManager.addComment( articleID, commentTO ) invoked
ArticleManager calls ArticleDAO.getArticle(articleID)
ArticleDAO creates Article object from database info, and loads up the
Article object's Comment collection (if any comments already exist)...
returns new Article object
Manager calls Article.addComment( commentTO )
Article.addComment() invokes createObject("component",
"Comment").init( this, commentTO)... note that the Comment constructor
needs an Article argument, since a Comment cannot exist without an
Article
Comment constructor validates and assigns its instance data according
to the commentTO data... if something's wrong, it throws an exception
Comment constructor then coordinates collaboration between itself and
the Article (the Comment object knows best what it needs to exist in a
valid state)... it checks any of its own business rules to make sure
it can be associated with that Article... it then asks the Article
(Article.testAddComment( this )) if the Article is ok with it (e.g.,
the Article may loop through it's current Comment collection and make
sure that Comment is not a duplicate). If all is good and no
exceptions are thrown, the Comment instructs the Article to add itself
to the Article's Comment collection (Article.doAddComment( this )),
and the Comment may also keep a reference to the Article instance.
Note how business rules associated with a single comment live in the
Comment class... business rules associated with a comment in the
context of an Article and all its comments live in the Article class.
The Article, having successfully added a Comment, returns the new
Comment instance from its addComment method
The ArticleManager, having captured this new Comment instance, calls
ArticleDAO.createComment( newCommentInstance )
>From the ArticleManager's point of view, this is all that happens:
var article = ArticleDAO.getArticle( articleID );
var comment = article.addComment( commentTO );
ArticleDAO.createComment( comment );
Also, in this scenario, I did not use a CommentDAO. I figure since
Comments are wholly dependent on Articles (ie, a comment cannot exist
without an article), I'll have the ArticleDAO handle Comments... or,
looking at it another way, if Articles and Comments had their own
DAOs, a CommentDAO would not be able to do anything without an
ArticleDAO doing something first.
Does that make any sense at all? It's a pretty radical departure from
classic, procedural CF development.
On Wed, 12 Jan 2005 10:42:32 -0500, Brian Kotek <[EMAIL PROTECTED]> wrote:
> Just goes to show how we all have different takes on these ideas. My
> thoughts inline...
>
> > -----Original Message-----
> > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On
> Behalf
> > Of Doug Keen
> > Sent: Wednesday, January 12, 2005 10:04 AM
> > To: [email protected]
> > Subject: Re: [CFCDev] When to Use Composition (Was: Newbie
> approach...)
> >
> > Patrick... I wholeheartedly agree.
> >
> > I don't think it's a manager object's responsibility to coordinate
> > collaborations between business objects. The article object should
> > hold the knowledge of all its comments, not the manager. That way, if
> > you want to add another comment to the Article, you can call something
> > like Article.addComment( commentTO ), and then the Article business
> > object can manage the creation of the Comment object and all the rules
> > associated with it (e.g., the Article, since it has knowledge of all
> > its Comments, can make sure this new Comment isn't a duplicate of one
> > of it's existing comments).
>
> I think that an object should either create other objects or use other
> objects, but not both. Having the Article object creating and
> manipulating comment objects seems to reduce the cohesion of the
> Article. Unless you are going all the way to say that they are really
> part of the same "thing" and in that case just combine them into a
> single object, maybe "BlogContent".
>
> But let's play out the original idea out a bit. OK, you have an
> ArticleBO. In the interest of separating creation from usage, let's say
> you're passing in an object to let the ArticleBO deal with Comments.
> What do you pass into the ArticleBO? A CommentGateway, so the ArticleBO
> and retrieve all comments associated with it? A prebuilt array of
> associated CommentBO objects? If you pass in a Gateway you're already
> crossing the layer between the business objects and the persistence
> layer. If you pass in an array, and you want to create a comment, now
> the ArticleBO has to create a new CommentBO and place it into the array.
> And how does that new CommentBO get persisted? Right now it's just
> sitting in the array. Somewhere a CommentDAO is going to have to store
> that new CommentBO. This would also be crossing layers.
>
> In other words, I don't see any way for an ArticleBO to get or store new
> Comments without dealing with a CommentGateway and a CommentDAO, and if
> that's true then I think cohesion has been sacrificed because Articles
> are responsible for Articles AND Comments. Not only that but the
> business object is now coupled to a DAO/Gateway...certainly not a good
> thing?
>
> > Pushing that kind of logic up into the
> > service layer (i.e., manager objects) seems to contradict cohesion.
> > Let your business objects take care of all the business logic... the
> > manager objects can simply coordinate action between the different
> > layers (persistence/DAO, business objects, caching, etc.).
>
> I think from the example I gave above, this situation *is* a situation
> where one layer (BO) is dealing with another layer (DAO/Gateway). I
> would indeed push this relationship into a higher layer.
>
> > I tend to think of this kind of "manager does everything" approach as
> > an *anti-pattern*... I'd like to call it the "Micromanager
> > Anti-pattern". Just like a micromanager doesn't trust subordinates to
> > do their job and tends to direct every single task to such minute
> > detail that the workers are simply reduced to an extra set of hands,
> > "Micromanager" objects take on too many minute details of business
> > processes and reduce business objects to dumb sacks of data that might
> > do a few type-checking operations on its instance data and little
> > more. It's almost as if the manager object methods become procedural
> > subroutines and the business objects act as simple data structures...
> > it strikes me as a very non-OO approach.
>
> I can see how that would be bad...I'm not advocating handling all
> relationships with Managers. But I am agreeing with you that a Manager
> type of object should be coordinating interactions between separate
> layers like DAOs, Gateways, and BOs.
>
> > I guess I'm still not clear on what the appeal of segregating Articles
> > and Comments is.
>
> This might really be the crux of the issue. Do Articles and Comments
> really need to be modeled as separate "things"?
>
> I find all this very interesting! Hey Sean, can we get your take?
>
> ----------------------------------------------------------
> You are subscribed to cfcdev. To unsubscribe, send an email
> to [EMAIL PROTECTED] with the words 'unsubscribe cfcdev'
> in the message of the email.
>
> CFCDev is run by CFCZone (www.cfczone.org) and supported
> by Mindtool, Corporation (www.mindtool.com).
>
> An archive of the CFCDev list is available at
> www.mail-archive.com/[email protected]
>
----------------------------------------------------------
You are subscribed to cfcdev. To unsubscribe, send an email
to [EMAIL PROTECTED] with the words 'unsubscribe cfcdev'
in the message of the email.
CFCDev is run by CFCZone (www.cfczone.org) and supported
by Mindtool, Corporation (www.mindtool.com).
An archive of the CFCDev list is available at
www.mail-archive.com/[email protected]