Agile UI Development in .NET: Model Commands

In my series on agile UI development in .NET, we have seen quite a lot so far (table of contents). But up to now, we never made a call to the model (business logic, services and so on). This is the topic of this post: Model Commands.

A Model Command encapsulates a single action hat is execute against the model. This can be a query to request data, an action that modifies data, communication with a completely different part of the system or anything else your application has to do on the model.

Let’s get back at my sample of sending a message in ProCollEE. The following code show the Model Command that sends a message:

/// <summary>
/// Command for sending messages.
/// </summary>
public class SendMessageModelCommand : ISendMessageModelCommand
{
    /// <summary>
    /// The message service used to send messages.
    /// </summary>
    private readonly IMessageService messageService;

    /// <summary>
    /// Initializes a new instance of the <see cref="SendMessageModelCommand"/> class.
    /// </summary>
    /// <param name="messageService">The message service.</param>
    public SendMessageModelCommand(IMessageService messageService)
    {
        Contract.Requires<ArgumentNullException>(messageService != null, "messageService");
        Contract.Ensures(this.messageService != null);

        this.messageService = messageService;
    }

    /// <summary>
    /// Gets or sets the message to send.
    /// </summary>
    /// <value>The message to send.</value>
    public string Message
    {
        get; set;
    }

    /// <summary>
    /// Gets or sets the channel on which the message has to be sent.
    /// </summary>
    /// <value>The channel.</value>
    public IEnumerable<string> Channels
    {
        get; set;
    }

    /// <summary>
    /// Gets the time when the server received the message.
    /// </summary>
    /// <value>The time when the server received the message.</value>
    public DateTime? SentAt
    {
        get; private set;
    }

    /// <summary>
    /// Sends the message.
    /// </summary>
    public void Execute()
    {
        Contract.Ensures(this.SentAt != null);

        this.SentAt = this.messageService.SendMessage(this.Message, this.Channels);
    }
}

The SendMessageModelCommand takes a IMessageService as dependency in the constructor. This service is used to send the message to the server.

The message and the channels to send the message on are set with properties. When the command is executed then it simply calls the service and passes on the information to send. Finally, the time when the server accepted the message is passed back in the property SentAt.

Note: go to UI Commands to have a look how the command is used.

Why Dedicated Command?

You may ask yourself, why I split this simple code into a dedicated command. There are several reasons:

Single Responsiblity Principle

Sending a message is for itself a responsibility. However, you may argue that its too simple and leads to unnecessary complexity. While this may be true for this simple example, model commands can be quite complex in real world scenarios.

Reusablity

Another advantage of a dedicated command is that you can reuse it in other parts of your application.

Let me make an example: in an application that manages customers there may be several places where you have to store addresses; edit a customer, edit order address, … Now you can reuse the command to save an address in these scenarios.

Batch Processing

Commands can be batched, too. Several commands can be added to a batch and executed at once. Thus simplifying mass operations.

Decouple Model From UI Layer

Model commands separate the UI layer (presenter, UI commands, …) from the domain model and act as a natural layer border that prevents change chains (a change in one place in the code results in changes through all “layers” in the application – e.g. from database up to the UI.

Command Processor

Each command is execute by the command processor and not directly by the client code. This allows tracking of all commands in a single place, e.g. log them.

Additionally, the command processor can be extended to support undo commands that can be used to undo the modifications of a command.

Conclusions

Model commands add a lot of advantages to the UI design pattern I’m advertising in this series on agile UI development and force decoupling and reusability in a project.

About the author

Urs Enzler

7 comments

  • Hi Urs,
    you said that the Model Command should be a clean cut between your domain model and the UI which is quite reasonable but very hard to achieve.
    We have following basic situation:
    On the UI we show a form where a lot of properties of a business entity (from the domain model) are shown and the user can change some of these properties. Closing the form is done via an OK button. Now the ok-button executes the bound UICommand which has access to all properties from the viewModel and therefore also to all changes made on the form. So far so good. The problem arises when we want to update the changes back into the domain model (with an underlying database). We use a repository to abstract from the actual database.
    My question is now, how to design such a model command (lets call it UpdateEntityModelCommand). Should it accept a reference to the changed domain entity and the UiCommand copies the changes from the view-model back into the domain entity? If so, the UiCommand also needs to deal with transactions since the UpdateEntityModelCommand might throw an exception and so the UiCommand has to roll back the changes made to the entity.

    Maybe you have a good answer to this.

  • Hello,
    I’m not Urs but nonetheless I share my two cents. The easiest way would be to directly save view models to the database and not map between view models and domain entities (see CQRS for example from Udi Dahan). Your view models have property changed notification, editable mode (BeginEdit, EndEdit, CancelEdit) and maybe data error infos. So you would basically retrieve view models from the database, bind them to the UI. The command only calls EndEdit when everything the storing of the view models was successful and in case of transaction rollback the command can just cancel the view model which then sets the view model to its previous state. If you already have the domain entities and view models separated we need to talk again 😉

    Daniel

  • Hi Christoph

    The answer depends on your overall architecture. If it’s something like CQRS then see Daniel’s answer. If not then maybe this is an idea for you:

    The transaction handling should be done completely in the model command (not the UI command). When there is an exception, the model command rolls back the transaction. Then you have two choices: either the model command reacts with an exception that has to be handled by the UI command or the model command notifies the presenter (event).

    The first case is the more coupled one: the UI command catches the exception and reflects the error condition on the view model and therefore on the view.

    In the second case, the presenter reacts to the error event and reflects that too on the view model. In this case (when using for example my event broker from bbv.Common) the presenter can listen too all different error cases with the same mechanism.

    Okay for short: transaction handling inside model command. Propagate error information back to UI (view model) either via UI command or presenter.

    Did that help?
    Urs

  • @Urs Enzler
    Hi Urs,
    yes that goes in the same direction as I was expecting. We are currently using the first approach (dealing with exceptions in the UiCommand) which allows us to show errors as validation errors in WPF.
    However, when moving transactions into the ModelCommand it follows that:
    – almost all UiCommand can only call a single ModelCommand (since one click leads most of the time to a single transaction)
    – a huge set of ModelCommands is required (because of the point above)

    These two points make me think…. Of course, I can have ModelCommands which do nothing else than calling an array of other more fine grained ModelCommands wrapping them with a single transaction but it still leaves me with the problem having a lot of model commands.

    Appart from that, thanks for all your thoughts!
    Cheers,
    Christoph

  • @Christoph

    Maybe, you can decouple the transaction handling from the commands:

    You need some kind of transaction context – an object holding information about whether there is a current transaction and which allows transactions within transaction (for example a simple nesting counter).

    The UI command can then create such a transaction context and pass it to all model commands that it calls. Furthermore, a model command, can start a transaction for itself, when needed – regardless whether some object up in the call stack started a transaction or not.

    With this, you can reduce the number of model command to the number of operations possible on your DOM and not to the number of different transaction scopes needed.

    I hope this explanation is clear enough 😎

    Cheers,
    Urs

By Urs Enzler

Recent Posts