Jean-Paul Boodhoo (is that a great name or what?) wrote a post recently title Screen Bound DTO’s. I thought it was interesting from the standpoint that where I work we do something very similar, and it’s always neat to read about other people who congregate toward similar designs.

I suspect, judging from Jean-Paul’s post, that what we’re doing is similar (but in fact it may not be).

The first difference I can see is that we don’t call our objects DTO’s; they’re just DataTables. To me, a DTO represents some sort of data that will be transferred over the wire. Our screen bound objects do not travel the wire, they just get created for UI purposes only.

Our domain objects come in only a couple of flavors: single entity objects (like Employee), custom collections (EmployeeCollection) and managers (which roughly translate to UnitOfWork objects which manage an aggregation of objects for a use case). Many times we need to display data to the user in a customized way, because that is what customers do: they ask for the same set of data to be displayed a myriad of ways. Instead of writing several different versions of the same objects or collections, or writing different DTO’s to send over the wire for specific requests, we prefer to keep to one business object for a give set of data. This makes our service layer a little simpler since there is only one type of Employee object in the domain, for instance. If you want to know what the HireDate is for an Employee, there’s not five different ways to get at that data, just one.

So how to display that data (almost always collections) in unique ways? We opt for DataTables and then write mappers that perform the translation at the UI level. The mappers are GUI classes; the domain model doesn’t know about them or care. Services have no idea they exist. Only the GUI layer knows about them.

A typical scenario for us is to query for a collection of business objects and then display that collection in a specific way. The Presenter class in an MVP triad will then pass that collection off to a mapper, which will map it to a DataTable. The DataTable then gets sent to the view, which binds it to a grid for display.

When the user wants to delete an item from the grid, the View delegates that call to the Presenter which then removes the item from the actual business object collection. The DataTable then gets updated via the mapper which has an Update() method. The Update method allows us to only create the DataTable one time and bind it one time. This has a neat feature; it allows us to detect changes to a set of data visually, so we can do things like bold or italicize changed fields in the DataTable via change events.

If the user wants to add a new item, they do so via a Dialog or Wizard (depending on the complexity of the business object) and then the object gets added to the business collection. Again, the DataTable is updated via the Update() method and the UI gets updated as well. In this way the DataGridView is never used to perform adds or deletes; just the domain objects are used (and thus any validation or other business logic can be performed as required).

As Jean-Paul says, this sort of design really helps when you’re doing development from the top down (or as he puts it, Top Down Development, but do we really need another xDD acronym?). From our perspective, we really like doing development this way. It makes sense to our users because they interact with the UI and don’t often understand business objects, despite the data they work with on a daily basis. We find it easier to conceptualize a problem if we can capture it from the user’s perspective in terms of a view or multiple views. As the problems get solved the domain objects fall out of the UI solutions, and as customization of the data is required the mappers get created on an as-needed basis. All of this lends itself very well to a test driven approach as you can unit test the presenters and mappers very easily. There’s a really great feeling that comes when you finally fire up the application for the first time in several hours of coding and the whole thing works and the data gets displayed correctly, yet you haven’t looked at the UI outside of the IDE.

The neat part is that the domain objects remain unaffected by any of this. They’re evolution can vary independent of the mappers. Other views can use the same domain objects and map them differently if they need.