By Peter Bell

Reconsidering Controllers - Part 2.5 - Types

Just a real quickie as part of this continuing series. I just want to go from having a type attribute to different elements for each type. Here's why that is often a good idea . . .

In the last posting I talked about having a "type" attribute for actions so I could have a type="list" that knows how to handle my filter, paging and ordering conventions without me having to re-specify them as attributes for every list that implements filtering, ordering and/or paging. It also allows a type="save" which will get a new bean and based on configuration will automagically load just the right fields into the bean for validating. This idea of "types" of elements comes up all over the place when you start developing DSLs. However, rather than adding an attribute called "type" it is often better to create an element for each type. Here is why.

While the following works:

action: type="list" name="MyEventList" object="Event" method="getByFilter"
param: name="Filter" value="EventUserID = '%SiteUser.ID%'"
param: name="PropertyNameList" value="StartDate,EndDate,Title"
param: name="Order" value="StartDate DESC"
/action

action: type="detail" name="CategoryView" object="Category" method="getByID"
param: name="IDList" value="%Input.CatID%"
param: name="PropertyNameList" value="Title,Description,MainImage,SubCategories,Products"
/action

action: type="save" name="ProductProcessAdd" object="Product" method="add"
param: name="PropertyNameList" value="Title,Price,Description,MainImage"
switch expression="%Product.Valid%"
case="true" action="ProductList"
defaultcase view="ProductForm"
/switch

the problem is that there is no way to make this self validating or documenting. Because we just have an attribute called "type", there is no easy way to document the fact that (say) lists must have a DefaultRecordsPerPage parameter and save must have a PropertyNameList.

If instead we replace the action element with elements called List, Detail and Save (all within an actions collection element), we can make the required and optional properties different for each element. Of course, we also need to have a Custom element to allow for custom elements with 0..n optional attributes/parameters and to make it easier to add new element types experimentally without having to refactor the XSD every time we want to try out a new element type, but in general by having distinct elements for each type we can make the language better documented and validated (providing we create a well documented, explicit XSD).

What might this look like? I don't have it just right yet, but two options would be:

save: name="ProductProcessAdd" object="Product" method="add"
PropertyNameList value="Title,Price,Description,MainImage"
switch expression="%Product.Valid%"
case="true" action="ProductList"
defaultcase view="ProductForm"
/switch
/save

and

save: name="ProductProcessAdd" object="Product" method="add" PropertyNameList="Title,Price,Description,MainImage"
switch expression="%Product.Valid%"
case="true" action="ProductList"
defaultcase view="ProductForm"
/switch
/save

Note that in the first case the param element containing the PropertyNameList has been replaced by PropertyNameList as an element and in the second case PropertyNameList has been made an attribute of the Save element. Both are valid approaches, but I'd probably make PropertyNameList an attribute unless I thought it was going to get sub elements or attributes of its own. So in this case I'd probably just make it an attribute.

Just thought it was worth mentioning this before I went any further with developing the DSL.

Thoughts?

Comments
Well, the 2nd one is certainly easier to read...

But what about

propertyName: Title
propertyName: Price
propertyName: Description

and so on?

I see it is much more clutter... anything else?

Also, I'm loving how simply dropping the angled brackets is truly easier on the eyes. I didn't think it should make that much difference, but it really does. I thought the same thing about semicolons, as well, but now I would easily prefer not to use them.

I guess the small things really do matter.
# Posted By Sammy Larbi | 6/25/07 4:23 PM
Hi Sam,

Agree 100% about the brackets - silly but true!

Re: n propertyName statements instead of the list, I just can't be bothered honestly. I treat a list as one of my primitives and do lots of list style operations and I can't see any reason to break the list into a collection of tags unless I have a credible belief that they will gain additional attributes. In cases like this where it is a reference to a name of another entity, I don't see that being likely, so I'd rather just have the list.

May be an idiosyncratic choice - not sure - but I haven't yet come across a downside (if you can think of one . . .)>
# Posted By Peter Bell | 6/25/07 7:51 PM
I can't think of one other than the one you mentioned (having another attribute)... And having them separated is an ugly mess.

But, what about default value as that attribute?
# Posted By Sammy Larbi | 6/25/07 8:04 PM
Hi Sam,

Good question, but I only use lists to refer to either strings that have no deeper meaning or as pointers to other concepts. In the case of the propertynamelist, there is a separate section in the object DSL with a properties collection with the custom data type, sql data type, title, validations, transformations, default values and all of the additional information about each property name. The list just references which elements within that collection this action should work with.

Seems to be working out so far, but I really appreciate the questions - always worth trying to figure out what I'm missing :->
# Posted By Peter Bell | 6/25/07 8:20 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.005.