Distinguishing between UI command & domain commands
- by SonOfPirate
I am building a WPF client application using the MVVM pattern that provides an interface on top of an existing set of business logic residing in a library which is shared with other applications. The business library followed a domain-driven architecture using CQRS to separate the read and write models (no event sourcing). The combination of technologies and patterns has brought up an interesting conundrum:
The MVVM pattern uses the command pattern for handling
user-interaction with the view models. .NET provides an ICommand
interface which is implemented by most MVVM frameworks, like MVVM
Light's RelayCommand and Prism's DelegateCommand. For example, the view model would expose a number of command objects as properties that are bound to the UI and respond when the user performs actions like clicking buttons.
Many implementations of the CQRS use the command pattern to isolate
and encapsulate individual behaviors. In my business library, we have implemented the write model as command / command-handler pairs. As such, when we want to do some work, such as create a new order, we 'issue' a command (CreateOrderCommand) which is routed to the command-handler responsible for executing the command.
This is great, clearly explained in many sources and I am good with it. However, take this scenario:
I have a ToolbarViewModel which exposes a CreateNewOrderCommand
property. This ICommand object is bound to a button in the UI. When
clicked, the UI command creates and issues a new CreateOrderCommand
object to the domain which is handled by the CreateOrderCommandHandler.
This is difficult to explain to other developers and I am finding myself getting tongue-tied because everything is a command.
I'm sure I'm not the first developer to have patterns overlap like this where the naming/terminology also overlap. How have you approached distinguishing your commands used in the UI from those used in the domain?
(Edit: I should mention that the business library is UI-agnostic, i.e. no UI technology-specific code exists, or will exists, in this library.)