Coldbox, ColdSpring, Transfer, Refactoring And Me (part 3)

I was trying to come up with a nice way to introduce working with Transfer in Coldbox. At first I wanted to have a service layer to control interactions with my objects. With Transfer, however, the relations became a little fuzzy. Take, for example, an event trying to register a new user. When thinking about submitting a registration form, I normally see at least two steps: validation and saving. Trying to imagine the flow of something like this in an application that's trying to be as close to OOP as possible isn't as easy as I thought, though. Here's what I got so far.

Generally speaking, I normally see the Coldbox controllers as having as little to do as possible. Their job is a little like a traffic operator who doesn't move, but rather tells people where to go.

Some Coldbox Controller

<cffunction name="doRegistration" access="public" returntype="void">
    <cfargument name="event" type="any" required="true" />
    
    <!---
        Let's suppose we have a userService object in the request collection
        (not likely, but that's a problem for another post)
    --->

    <cfset event.getValue( "userService" ).saveAndValidate( event ) />
    
</cffunction>

You see that we're basically just passing the event argument (akin to the request scope) over to the service layer for treatment. The way I see it, the userService object is basically another controller, but for the user object rather than for the event requested.

The userService's validateAndSave() method

<cffunction name="validateAndSave" access="public" returntype="void">
    <cfargument name="event" type="any" required="true" />

    <!--- do some validation stuff --->

    <!--- tell the object to save itself --->
    <cfset variables.instance.user.save( event ) />

</cffunction>

I didn't want to go into too much detail for this post, but we can see that the validateAndSave method takes care of validating the data submitted and then asks the user object to save itself (passing it the event variable so it knows what values to assign itself). The user object then calls Transfer's method to update and save itself.

The user object's save() method

<cffunction name="save" access="public" returntype="void">
    <cfargument name="event" type="any" required="true" />

    <cfset var locals = { } />

    <!--- get the transfer bean --->
    <cfset locals.transfer = event.getValue( "transfer" ) />

    <!--- create a new user --->
    <cfset locals.user = locals.tranfer.new( "myPackage.User" ) />

    <!--- set some columns --->
    <cfset locals.user.setMyColumn( event.getValue( "myValue" ) ) />
    <!--- etc. --->

    <!--- save the user back to the database --->
    <cfset locals.transfer.save( locals.user ) />

</cffunction>

Using Transfer's new method, we get a reference to a blank user record. We then use the generated setX methods (one for each column) to update the record, and save, well, saves the record back to the database. Simple enough, right? The question is, however, is it good enough?

Hesitations

I've been avidly following Ben's series on OOP, especially his posts (day 1 and day 2 are up, hopefully more to come) following his courses with Hal Helms. His last post talks about objects having behaviours, and being able to do what is requested from them. He also warns against « massive, procedural "Service" objects and data-driven "Business Objects" that have no true behavior ». After reading through the post a couple of times I can't help but question my structure.

  • What good is the user service object for? Shouldn't the user object be able to validate and save itself? Should it be called directly from the Coldbox Controller?
  • I seem to be passing the event object around alot... I don't feel confortable doing this and feel I'm repeating myself.

I've got some serious thought to put into this, but I'm glad I put it out there. Any insight is, as always, very much appreciated.

Comments
Justin's Gravatar I've been following them as well. As a ColdBox user, I have to say that my next ColdBox project is going to be procedural. I don't have the time or resources to make proper OO, so why over-complicate things just to be like everyone else. I haven't found maintenance to be that much easier with this procedural OOP after all.

Yes, maintenance is easier than with sloppy procedural code written by a beginner, but not pretty procedural code written in a quality framework which forces a separation of concerns to allow for application expansion.

This is for me and my projects personally. I'm sure the Sean Corfields are on massive enterprise projects where OOP and OOP specific design patterns are mandatory.
# Posted By Justin | 10/22/08 10:51 AM
Francois Levesque's Gravatar OMG, there are more than one Sean Corfields?

I understand where you're coming from. Honestly, I have to agree that this is a major step and that it requires a lot of resources. At work I tend to lack the time to pursue a true OO approach.

However, I'm exploring on some experimental projects on my own time, so it isn't so much an issue. I guess I'm looking for a solution that's easier to scale and manage (and debug by my coworkers!).

Obviously I wouldn't bother with all of this with a comment form, but you still have to ask:

"What is considered small?" ;)
# Posted By Francois Levesque | 10/22/08 11:03 AM
Justin's Gravatar "Sean Corfields of the world" I suppose would be better.

I don't know what small is; it's a good question.
# Posted By Justin | 10/22/08 2:56 PM
Raul Riera's Gravatar Again, give Wheels (http://www.cfwheels.com) a try, you will find it sooo easy to fit into your way of life. Its convention over configuration witch is a good thing on its own (no BIG A** XML files)

I have been reading the ColdBox docs and its a pretty tough cookie to eat, yet with Wheels you are coding just the same way you did before but better. I dont know why a ColdFusion developer would want to do things harder.
# Posted By Raul Riera | 10/22/08 6:48 PM
Francois Levesque's Gravatar @Raul,

I don't think Coldbox is difficult to learn, or use. It's also conventions-based, using XML only for it's settings file. What got me interested, at first, was the huge amount of documentation available for this framework. This made it much easier to learn than others I had tried. I do admit, however, that I had not seen or heard of cfwheels before. I might save some time after this project to give it a try, if only to compare ;).

The difficulties I'm facing here, though, is integrating all of these frameworks together and trying to create an application that is as OO as possible. It's an experiment, so it's supposed to create challenges.
# Posted By Francois Levesque | 10/22/08 7:33 PM
Raul Riera's Gravatar I see whata you are saying but Wheels is also very OO and everything is baked in, of course Model Glue and ColdBox with Transfer are more feature rich, but this is a rather new framework.

Now if Model-Glue or ColdBox could work with Transfer to make it so everyone works on a single framework would be the best idea for the community. Its like people forget they chose ColdFusion for its simplicity in the first place, a single all in one framework is very needed, and wheels is heading tht way.

Maybe I am naive but I believe we need an united front and not lots of semi useful thing scatter around, there are some greate examples out there with Django, Rails and Symfony where eveyrthing is baked in and everyone is working out the tweaks everyday.
# Posted By Raul Riera | 10/23/08 9:51 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.3.000. Contact Blog Owner