Reading through the seventh part of the primary (http://
greatbiztoolsllc.trac.cvsdude.com/mach-ii/wiki/MachIIPrimerPart7) it
seems like its considered a good practice to have individual functions
in your DAO for the create/update/delete stuff, the individual
functions in your Listener to call those functions, and to have the
filter in your configure fire off the individual events to access
those Listener methods depending on if you are creating/updating/
deleting.
My co-worker and I found ourselves wondering, though, why you would do
this over having a single function in the DAO for create/update/
delete, with then the single function in the Listener and the single
event, with the DAO flipping between the appropriate query(s) to
perform the right action depending on which is needed? This would seem
like a good way to reduce code redundancy and increase its
maintainability, but are we missing something?
Summer S. Wilson
Collectonian on Yahoo! Messenger ~ Facebook (http://www.facebook.com/ Collectonian)
An Eclectic World (http://eclectic-world.com) ~ LiveJournal (http://
collectonian.livejournal.com)
On Tue, 3 Nov 2009 11:36:34 -0800 (PST), Collectonian
<collecton...@gmail.com> wrote: > My co-worker and I found ourselves wondering, though, why you would do > this over having a single function in the DAO for create/update/ > delete, with then the single function in the Listener and the single > event, with the DAO flipping between the appropriate query(s) to > perform the right action depending on which is needed?
Just to make sure this is clear, your listener should be talking to a service, not directly to your DAO.
Beyond that, some of this is really a personal preference issue, but when I find myself with a method called doABunchOfStuff() that has a bunch of conditionals in it, that smells bad to me. More methods that do discrete things is always preferable to a single method that does a bunch of different things. Makes it far easier to debug, maintain, and extend.
> This would seem > like a good way to reduce code redundancy and increase its > maintainability, but are we missing something?
The redundancy point is debatable I suppose, but when you think about your backend as a service layer to the rest of your app, the fact that you have a method in your listener that merely calls a method in your service seems less redundant. We also do have the call-method command that you can use to bypass listeners altogether if all the listener method is doing is pulling data from a service.
I disagree with the maintainability point. I do tend to have a single save() method that does a create or update based on whether or not an ID is set on the object in question, but I can't imagine including the read and delete actions as well. What would you even call a function that does all four of those things? And to distinguish between a read, update, and delete you'd have to pass an action in anyway ... at that point you have a real mess IMO.
In my opinion you should always opt for code that is explicit, easy to read, easy to debug, and easy to maintain. Discrete, single-purpose methods help achieve this. -- Matthew Woodward m...@mattwoodward.com http://mpwoodward.posterous.com identi.ca/Twitter: @mpwoodward
On Nov 3, 3:05 pm, Matthew Woodward <m...@mattwoodward.com> wrote:
> Just to make sure this is clear, your listener should be talking to a
> service, not directly to your DAO.
Wait, I thought the listener should be passing things to the Gateway
for multi-result queries, and the DAO for single result things (like
CRUD stuff)? That is how the tutorial has it and all the examples I've
seen show it? ~confused again~
> I disagree with the maintainability point. I do tend to have a single
> save() method that does a create or update based on whether or not an ID is
> set on the object in question, but I can't imagine including the read and
> delete actions as well. What would you even call a function that does all
> four of those things? And to distinguish between a read, update, and delete
> you'd have to pass an action in anyway ... at that point you have a real
> mess IMO.
I didn't mean the read would be included, that's a totally separate
function. Delete though is just a matter of checking the action
between update/delete of a form (basically is normally done in a non-
MachII app with a create/update/delete component with a switch
statement). Generally would just call it updateObjectTable or the like
Summer S. Wilson
Collectonian on Yahoo! Messenger ~ Facebook (http://www.facebook.com/ Collectonian)
An Eclectic World (http://eclectic-world.com) ~ LiveJournal (http://
collectonian.livejournal.com)
Matt,
She's right. The Primer she linked to has code samples going from
listener to gateways and DAOs. We may want someone to revisit those,
but they are out there nonetheless.
Summer,
Ideally you would have a service layer between your listeners and
database components (Gateways and DAOs). For more info about service
components, google "coldfusion service layer".
In Matt's example of create and update, your listener and service
components could have a function named "Save". The listener function
would pull data out of the event object and pass it to the service
component. The service's save function would decide, possibly based
upon an existing primary key, if the bean passed to it is to be a new
record inserted in the database or an existing record to be updated.
The service component would then call either the "Create" or "Update"
function in the DAO based on that decision.
And to add a +1 to what Matt said, it is a good idea to keep
components and functions as simple as possible. It is a bad idea to
have one CFC that does everything. The same goes for any given
function. One function for Create, one for Read, one for Update and
one for Delete keeps things easier to troubleshoot. At least this is
my opinion. The way you discussed is not necessarily wrong, and if it
is what you prefer, then go for it. But in the Object Oriented world
you will hear the term encapsulation quite often. It is the idea of
having functions and components perform small, simple tasks. They
become more reusable that way. Much more so than a do everything
function or an uber.cfc.
-Matt (not Woodward) Williams
On Nov 4, 9:20 am, Collectonian <collecton...@gmail.com> wrote:
> On Nov 3, 3:05 pm, Matthew Woodward <m...@mattwoodward.com> wrote:
> > Just to make sure this is clear, your listener should be talking to a
> > service, not directly to your DAO.
> Wait, I thought the listener should be passing things to the Gateway
> for multi-result queries, and the DAO for single result things (like
> CRUD stuff)? That is how the tutorial has it and all the examples I've
> seen show it? ~confused again~
> > I disagree with the maintainability point. I do tend to have a single
> > save() method that does a create or update based on whether or not an ID is
> > set on the object in question, but I can't imagine including the read and
> > delete actions as well. What would you even call a function that does all
> > four of those things? And to distinguish between a read, update, and delete
> > you'd have to pass an action in anyway ... at that point you have a real
> > mess IMO.
> I didn't mean the read would be included, that's a totally separate
> function. Delete though is just a matter of checking the action
> between update/delete of a form (basically is normally done in a non-
> MachII app with a create/update/delete component with a switch
> statement). Generally would just call it updateObjectTable or the like
> Summer S. Wilson
> Collectonian on Yahoo! Messenger ~ Facebook (http://www.facebook.com/ > Collectonian)
> An Eclectic World (http://eclectic-world.com) ~ LiveJournal (http://
> collectonian.livejournal.com)
On Wed, 2009-11-04 at 06:20 -0800, Collectonian wrote: > Wait, I thought the listener should be passing things to the Gateway > for multi-result queries, and the DAO for single result things (like > CRUD stuff)? That is how the tutorial has it and all the examples I've > seen show it? ~confused again~
Some of the tutorials are likely outdated but if they aren't showing the use of a service layer they should be. I've also personally moved to a single DAO object instead of splitting between DAO for CRUD and gateway for aggregate data.
> I didn't mean the read would be included, that's a totally separate > function. Delete though is just a matter of checking the action > between update/delete of a form (basically is normally done in a non- > MachII app with a create/update/delete component with a switch > statement). Generally would just call it updateObjectTable or the like
Again, personal preference, but that really doesn't make sense to me. To me having save(myBean) and delete(myBean) is much more straight-forward than updateMyTable(myBean, "delete") and the requisite conditionals in your listener method. I just don't see what you're gaining by doing things that way.
On Wed, 4 Nov 2009 07:01:35 -0800 (PST), Matt Williams <mgw...@gmail.com> wrote:
> Matt, > She's right. The Primer she linked to has code samples going from > listener to gateways and DAOs. We may want someone to revisit those, > but they are out there nonetheless.
Yep, would be nice if someone would revisit those. ;-) We're always looking for volunteers so if someone has the time, that's a great way to get involved with the project.
Alrighty, I understand on the encapsulation :-) The service layer thing though...*sigh* And this app was almost done too...for now, I think I'll stay with the older way...we've had a hard enough time selling some of our other developers on going to a framework without increasing the complexity and time to developer. :-P Baby steps....
On Wed, 4 Nov 2009 09:17:04 -0600, Summer Wilson <collecton...@gmail.com> wrote:
> Baby steps....
Absolutely!
Here's a link to a presentation I gave to the Maryland CFUG a while back--talks about architecting applications for multiple UI technologies but I think it's a great illustration of the service layer concept. http://adobechats.adobe.acrobat.com/p52512658/