CRUDs - Filters, DAOs, and single purpose functions?

5 views
Skip to first unread message

Collectonian

unread,
Nov 3, 2009, 2:36:34 PM11/3/09
to Mach-II for CFML
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)

Matthew Woodward

unread,
Nov 3, 2009, 4:05:03 PM11/3/09
to mach-ii-for...@googlegroups.com

On Tue, 3 Nov 2009 11:36:34 -0800 (PST), Collectonian
<collec...@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
ma...@mattwoodward.com
http://mpwoodward.posterous.com
identi.ca/Twitter: @mpwoodward

Please do not send me proprietary file formats such as Word, PowerPoint,
etc. as attachments.
http://www.gnu.org/philosophy/no-word-attachments.html

Collectonian

unread,
Nov 4, 2009, 9:20:31 AM11/4/09
to Mach-II for CFML
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

Matt Williams

unread,
Nov 4, 2009, 10:01:35 AM11/4/09
to Mach-II for CFML
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

Matthew Woodward

unread,
Nov 4, 2009, 10:05:53 AM11/4/09
to mach-ii-for...@googlegroups.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.

Matthew Woodward

unread,
Nov 4, 2009, 10:11:09 AM11/4/09
to mach-ii-for...@googlegroups.com

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.

Summer Wilson

unread,
Nov 4, 2009, 10:17:04 AM11/4/09
to mach-ii-for...@googlegroups.com
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....

--
~~ Summer

Matthew Woodward

unread,
Nov 4, 2009, 10:26:45 AM11/4/09
to mach-ii-for...@googlegroups.com

On Wed, 4 Nov 2009 09:17:04 -0600, Summer Wilson <collec...@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/

Reply all
Reply to author
Forward
0 new messages