Frequently, when we adapt new technologies or techniques, the new fix ends up introducing new "yucky" stuff or simply pushes the previous yucky stuff to another area. Since "yucky" just might be a bit subjective here, I consider yucky stuff to include any bit of code that has no clear home or which is overly complicated for the sake of separtion of concerns. If you encounter code such as this, it doesn't necessarily mean that you have a weak understanding of the domain or task at hand, but it may be a sign that you have a grey area between application layers which needs to be better defined.
These grey areas are frequently found between where the presentation layer ends and the controller and/or business logic begins. For example, when we moved from Active Server Pages to ASP.NET, we liberated our views of business logic only to find our newly embraced code-behinds to be a bear to maintain as they intertwined abstracted presentation concerns with logic. Adding a pattern such as M V P certainly made it all testable but then moved much of the "yucky" stuff to either the presenter class or added new yucky stuff in the form of complicated event communications and/or fudgy controller logic between the code-behind and presenter classes. (If you've used MVP in a major project, you'll likely know what I'm talking about.) So now with the dawn of ASP.NET MVC with a DDD approach (nicely encapsulated within S#arp Architecture, of course), our concerns are over, right? Well, not exactly...we now have a new yucky bit to deal with: the grey area between the controllers and application services (not to be confused with domain services) . This is exactly the grey area that I've struggled with since adopting ASP.NET MVC with an eye for DDD. Where exactly do we draw the line between what goes into controllers and what goes into application services?
Joe Wilson recently posted a review on S#arp Architecture and had a useful critique of the framework which IMO provides a very clear explanation of where the line should be drawn between the MVC controller and DDD application service layers:
I've borrowed a metaphor from the SQL Server installer that talk about "surface area". I think of the MyProject.ApplicationServices layer as a wrapper around all the app logic. The methods in this layer are the surface area of my application, and they encapsulates all the implementation code my domain is dealing with. Calls into this layer can kick off multi-step processes, handle workflow, and usually have long, explicit method names. But this is the only part of my domain's surface area that is exposed externally.
To put it another way, if you're putting any logic into your controller class that you would have to copy and paste, almost verbatim, into, e.g., a WCF service class to replicate the same sort of behavior, but for a different client interface (e.g., WCF vs. MVC), then it's likely a sign that your controller is doing too much and that the code may instead belong in an application service. In a different light, if you're putting anything into the application service layer which would preclude a different client type (e.g., WCF vs. MVC) to leverage it, then you may be introducing controller concerns into the application services. Following these rules of thumb, your controllers remain more appropriately paired with the web tier of your application while your application services provide the true gateway to the rest of the application. Keeping a close watch on the application service layer's "surface area" (or more appropriately stated, bounded context), and making sure it doesn't leak into the controller layer or vice versa, is a good approach for drawing a firm line between these two layers and keeping the yucky stuff at bay.
09-16-2009 11:29 AM