In the comments of a recent post, some people pointed out some questionable practices:
- Modifying the data access when I should be modifying the business model
- Using a NoSQL data store when a relational one would be more appropriate for slicing and dicing data
- Changing the business model to accommodate the UI
Will ignore the second point for now. I’ve covered part of the concern already anyway.
For the other two, it’s worth explaining the architecture that I think Google Web Toolkit encourages.
Both points mention “business model” and I’ve probably called it that on occasion as well. I’ve never liked using the term because I don’t think I’ve worked on a project that’s done any form of DDD except use repositories. My domain is usually anemic because there isn’t a lot of business logic in a CRUD app. Unless you count the many forms of GetFullName I’ve written on a customer object.
But now I’m in an app that has real business logic. “Find next available appointment”, for example. Or better yet, “find optimal appointment time” for the ominous “smart scheduling” feature. Seems like a good candidate for a rich domain model. Except that our “domain” is still all DTOs.
I’m fine with this because it works for our architecture. In a more traditional .NET web app, I would probably define a proper domain model with behaviours and such. On the front end, I’d diligently translate between it and screen-specific DTOs or JSON objects or what-have-you.
We’re using GWT. It’s *all* JSON. And it’s not even JSON we control. (We could control it but we choose not to and use the built-in GWT RPC translation.) Every single action is an AJAX call launched from a button, or a link, or a drag and drop. Nothing is screen-specific because presenting a single screen is too big a concept. Instead, we replace individual pieces of it as necessary and make individual requests for the corresponding data for those pieces.
So we’ve adopted an architecture based around what I have been calling (possibly erroneously, so you may want to look it up) the command pattern. This sounds like a grand architectural decision from a big software mucky-much but really, this architecture is nigh impossible to avoid with GWT applications. The implementation is courtesy of gwt-platform, which also handles our MVP structure as well.
Here is a 998-word picture of the process:
Notice there are no domain objects anywhere. That’s because it’s my diagram and I’ve specifically doctored it so that there are no domain objects.
I jest, slightly. There are no domain objects because they aren’t interesting. All the real magic happens in the “Process command” step. This is where we examine the data we’ve been given, do some stuff like save to a data store or calculate a person’s likelihood of arrest before the age of 18 or some other piece of logic befitting our “domain”.
The “data we’ve been given” is the command, which is a fancy word for a specialized DTO. For example, if we want to search for a suitable liquor store, we create a FindClient command and populate the SearchText proper—…whoops, this is Java. I mean we call the setSearchText method. The server matches, through dependency injection, the FindLiquorStore command with the FindLiquorStoreHandler and executes it.
After doing whatever magic needs to be done, we create a result, which is another specialized DTO. It has a getResults method which returns a list of LiquorStore “domain” objects.
With this architecture, the domain objects are little more than property bags. All the real work is done in handlers. To summarize the objects used in our “find liquor store” example:
|FindLiquorStore||Command object. Class name helps determine which handler to run. Property accessors store relevant data needed to execute the command|
|FindLiquorStoreHandler||Handler that examines the data within the command and does whatever needs to be done with it. Also creates a result object and returns it.|
|FindLiquorStoreResult||Contains any data that the caller might be interested in after processing the command; in this case, a list of LiquorStore objects|
|LiquorStore||An “domain” object in the sense that it is called something that a business person might recognize|
Seems a lot of infrastructure but it’s not so far removed from MVC applications where a controller action takes parameters from a query string (or form), process it, then sends a model back to the view. The difference is we don’t do it at the page level with a model that contains a bunch of lookup data as well as the one piece of info we care about (notwithstanding some interesting work in this area).
This is more in line with the types of apps I’m building more often even using MVC. That is, the page loads with very little actual information on it and each section takes care of its own data. One section might load the client data, another the alcohol consumption stats for the staff, and another the customer satisfaction charts. Each of these would entail a separate AJAX call to a controller action that would likely return a JsonResult (or even more likely, a custom Json result so that I can avoid the serialization issues inherent with the native MVC JsonResult object).
This probably doesn’t necessarily obviate the need for a full-fledged domain model complete with all the behaviours and other keywords that I have no business pretending I know anything about. You can translate between DTOs and domain objects very easily these days. But given that the sole access to the application is through commands, I’m more inclined to leave everything as DTOs and have the handlers contain all our business logic.
Kyle the Commandeered