A comon question asked is whether or not ColdFusion components should contain HTML, with the conventional wisdom being a firm "NO". Well, hold on, because I'm going to tell you why they should, and why your objects should do the same.
I'm a bit "old-school" when it comes to objects. As defined in the Smalltalk era, objects should know how to manipulate themselves and their data, should be able to serialize themselves (perhaps through an ORM)... and be able to render themselves.
In the traditional example, a drawing program's graphics objects would each draw themselves when asked, drawing a triangle if they were triangle-objects, drawing a square if they were box-objects, and drawing a circle if... well, you get the idea.
Translated into ColdFusion terminology, a "member" object (CFC) contains its registration form, used throughout the site. A call to the object's "registered" method generates another request that gets the HTML needed for the registration email, which it sends, and so on.
An "order" object knows how to render its invoice, again used in many places: the order confirmation page, the confirmation email, by the administration system when it prints orders, and on the user's "what you've ordered page".
An "article" view may know how to properly render an article displayed in many places, correctly handling titles, subtitles, abstracts, bylines, datelines, sources, and so on.
Business Objects
So, to that end, my business object's interface provides access to the forms and views commonly associated with that object.
In practice, and to keep the business object from suffering from bloat, that equates to a set of view and form cfcs that live in their parent object's directory.
And in doing so we have what I consider to be a good separation of church and state: the business-object itself doesn't contain any HTML, only the sub-components do, and those components are "purpose-built" to deliver generated HTML to the page.
From the outside, however, the net effect is that my object "knows" what to do with itself and its data, and does so when asked.
And it maximizes the reuse of those components.
This approach fits my "building-block" approach to software development, in that I'll combine small pieces to make larger ones, and use those to make even larger blocks.
Examples
Let's say I have MVC ordering system and I now, as mentioned earlier, need to display the "Thank you" page. The order controller loads the correct order object and passes it to a controller view. That view, in turn, asks the object to display its invoice, which it then wraps with the standard "Thank you for ordering from..." and "If you have problems..." boilerplate.
Note that I have several kinds of "views" being used here. The "make-a-page" view used by the MVC system, and the "make-a-block" invoice view used by the order object, which are combined and given to the page template to create the final result.
In reality, the invoice view might have been even more fine grained, with it in turn asking the order's address and order item objects to properly render themselves as well.
Small blocks, big blocks, bigger blocks.
Alternatives
I could have included the invoice view in the order application folder, but I'd need it elsewhere in the site, and on "standard" pages that don't have or use controllers. And it seems to be VERY bad form (to me anyway) to have others pages digging around in another application's views. Never can tell what dependencies and side effects may be hidden, present, or be added later.
I could create a common "views" folder, but in a big site there would be a lot a views, and I'd probably need to organize them into, say, "order" views, "member" views, and... essentially duplicate my entire "business-object" folder tree.
And since a member view isn't going to work when passed an order object, why not associate the views with the proper dependent objects in the first place? And why not provide easy methods to access them?
Convential wisdom says that the "front-end" is responsible for rendering data. But where does the front-end stop and the back-end start? In a MVC system is the controller front-end or back-end? It's responsible for what's displayed, and in what order, but the view displays it.
If a controller calls my order's "purchased" method I want my object, among other things, to send the confirmation email... which needs to display an invoice. How does it find it? What if I have multiple ordering systems? A standard cart and a single page order and a "one-click" system (sorry Amazon). Am I supposed to duplicated the business logic into each one of those systems?
Where's the line?
And moreover, is engaging in line-drawing beneficial? Especially when it hampers reuse and application clarity?
Be Smart
Once again, it comes down to being smart about your application development. Will a view or form need to be reused across your site? Is that view or form dependent upon a specific object's data?
If the answers to those two questions are yes and yes, then you now know what to do. And if that flies in the face of "conventional" wisdom, then that's just too bad.
Let the purists cry if they want to. Me, I'll just be over here, playing with my blocks...
Comments