By Peter Bell

Removing Argument Definitions from Delegates

Just something I'm playing with right now as part of implementing loadByProperty() and loadByFilter() within my IBO. These are both basically two line methods. The first line takes the argument collection and passes it to the DAO method that returns a recordset. The second line calls loadQuery() to load that recordset . . .

At first I cut and pasted the argument definitions from the DAO methods, but whenever I cut and paste chunks of code I always stop myself and ask if it was a good idea. Now if my getByProperty() arguments change, I'm going to have to change those both in my DAO and in my IBO.

So, I just deleted all of the cfargument statements in the two IBO methods. They are identical to the arguments of the underlying object so it is no big deal to look at the DAO as the authoritative source of the API for these methods and it means my code is DRYer.

Honestly I'm not sure I'd defend this choice - especially in a bigger team or less "dynamic" environment. It'll break any auto-documentation features, it makes the code less self documenting and it means that error messages will be a little more cryptic (as it'll throw an argument missing error on the DAO, not the IBO), but I'm happy with the trade off for my use case in keeping my code base tighter and DRYer.

<cffunction name="loadbyProperty" returntype="void" access="public" output="false" hint="I load the IBO with data for each of the property values provided in the property value list - in the order of the values in the list.">
   <cfscript>
      var Recordset = variables[ObjectName & "DAO"].getByProperty(ArgumentCollection=Arguments);
      loadQuery(Recordset);
   </cfscript>
</cffunction>

Any opinions?!

[UPDATE] Grrr - didn't work. Unless you pass in named arguments, all you get is a struct with numbered arguments. Oh well, it was worth a try :-<

Comments
You could name a single argument called 'args' which accepts the argument collection and passes it onward. Since the arguments are not specifically named, you would not have to change the code in several places as you refactor.

Thoughts?

dw
# Posted By Dan Wilson | 5/13/07 4:30 PM
@Dan, Thanks for the input. After thinking about this have decided to use named arguments and it actually works without the args struct, so the code above works. Thanks!
# Posted By Peter Bell | 5/13/07 4:49 PM
Normally, if the args are the same I'll just say in the hints to the 2nd function something like "alias for theOtherMethod" or "see otherMethod for argument details" But I'm with you, I dont even like to duplicate arguments, though its not as if I haven't done it (and probably fairly recently)
# Posted By Sam | 5/14/07 7:28 AM
Peter,

I've encountered the same problem with delegates. I hated having to manually keep the arguments in sync AND I didn't want to have to specify the NAME of an argument when calling a function so I could pass an arguments collection to the end method. I think passing NAMED arguments when calling CFC methods should be avoided because if you want/need to change an argument name later on you can't without breaking the referencing code. To facilitate this I wrote the following utility. I call it a "Dynamic Proxy Generator." I'm sure there are other incarnations of this, but it generates delegates for you automatically PRESERVING ARGUMENT ORDER (and other argument attributes too). I use it in my service classes to create delegates to my daos and gateways when I don't need to do anything special ON TOP OF the dao and gateway methods.

Basically you call the "createProxies" within your "Service" and give it the name of the property (assumes a GETTER is available) to your dao or gateway, and you tell it which functions to create delegates for. You can even ALIAS the delegate function name in your service layer if you wish. This can DEFINITELY be further expaneded on (such as creating delegates for ALL methods of another object, et...) but has enough functionality right now to reduce my work nicely. I would only suggest doing this with singletons unless you came up with a cacheing scheme to apply this to transients.

Hopefully this will be of some help to you,

- Kurt Bonnet

http://home.comcast.net/~kurt.bonnet/dynaProxyGenerator.zip
# Posted By Kurt Bonnet | 5/14/07 3:05 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.005.