I've been reading a lot of material lately about DDD (business entity objects) and other common patterns in n-tiered(layered) architecture. One thing I have issue with is, most articles, blogs, examples, etc. seem to talk to only one aspect of a system. Some may talk about creating a BLL for containing business logic. Some talk about only saving data via a DAL (ignoring reading). Some talk about only DTOs. I've not yet found anything that at a basic level talks about putting all of this together. When I attempt to put a lot of that material out together myself, it seems the information is at times is mutually exclusive.
Here is where (to me) things tend to be mutually exclusive:
- Business logic is contained in the DDD business entity objects, which your UI doesn't create directly (it gets DTOs).
- Data is passed to the UI via DTOs, which should not contain business logic. The DTO should only contain getters and setters.
Which leads to my Question:
How does your UI configure itself when business logic is required to analyze the data of those DTOs to make UI decisions?
For example, you are developing the UI and you have this requirement. You need to determine in code whether or not the Delete Button should be enabled:
System Requirement: An Order can only be deleted when there are no products on the Order and the Order's status is 'Open'.
Sure, you can do a check in your UI with the following:
Dim _order As OrderDTO = SomeServiceCall.ReadOrder(123)
If _order.Products.Count = 0 And _order.Status = "Open" Then
DeleteButton.Enabled = True
End If
But isn't this now putting business logic into the UI code? What if there are new or changed business rules to determine when an Order can be deleted? While you could add a function .CanDelete()
to the OrderDTO, it's the wrong place based on everything I've been reading, because business logic belongs in the Order entity object. So how do you tell the UI to Enable or Disable that darned Delete button???
One option may be to always enable the Delete button and throw an exception when the Delete action fails validation in the Order entity object (side note: just found FluentValidation and it seems amazing!). But that's sloppy UI. What are the "good architecture" alternatives to get the UI what it needs?
The same could apply to many other UI situations, where based on different combinations of the data (i.e. business logic) contained in a DTO, you may lock out some input fields, or hide them, etc.
A lot of times it seems the write-ups about DDD, DAL, BLL, DTO ignore the practical UI requirements.