Reconsidering Controllers - Part 2.5 - Types
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?


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.
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 . . .)>
But, what about default value as that attribute?
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 :->