Archive for July, 2009

Greg Young on a solution to CRUD

Thursday, July 30th, 2009

Greg Young gave a talk at QCon last year entitled Unshackle Your Domain. In it, he offers a solution to CRAPpy -- sorry I mean CRUDdy -- services.

CRUD services expose a set of objects. A client gets an object (Read), makes changes to it, and puts it back (Update, or Alter). One big problem with CRUD is that it is not auditable. There is no record of the change. Sure, you can keep a parallel audit history, but if your system does not rely upon that history, how can you trust it?

Greg points out that accountants don't make changes to objects. They keep histories. They never Update (Alter) records, and they never Delete (Purge). Their work is completely auditable. Their legers have a running total, but that current state is always based on history. Changes, not objects, are the foundation of their domain.

Record changes, not state
Greg proposes that a service can be modeled as a series of changes, rather than a collection of objects. In many domains, the set of changes is just as important as the set of objects. This is the only way to truly trust your audit log.

State transitions are an important part of our problem space and should be modeled within our domain.
- Greg Young

In addition to making a system auditable, this solves a whole host of validation and consistency problems. For example, in a CRUD service, we would model a customer as:

class Customer
{
  identity CustomerId;
  string FirstName;
  string LastName;
  string City;
  string State;
}

As a domain object, it would have validation. For example, the City must be within the State. But what if the customer moves from Dallas, Texas to Tulsa, Oklahoma? There is no method to get us there in one step. We either have to transition through Tulsa, Texas or Dallas, Oklahoma. We have to allow our object to be in an invalid state.

More subtle is the FirstName/LastName pair. There is no validation here, but it is just as incorrect to change one without the other.

Now consider the CRUD operations:

CreateCustomer(Customer c);
UpdateCustomer(Customer c);
DeleteCustomer(Customer c);
List<Customer> GetCustomersByCity(string city, string state);

Suppose one client gets a customer and changes their name. At the same time, another client gets the same customer and changes their address. How does the server reconcile these two changes? There should be no conflict: the two clients performed two independent operations. But because we funnel all of the changes through UpdateCustomer, we cannot easily separate them.

A change-oriented service model
Greg proposes that the service should model the changes as first-class citizens. For example:

change AddCustomer
{
  identity CustomerId;
  string FirstName;
  string LastName;
  string City;
  string State;
}

change RenameCustomer
{
  identity CustomerId;
  string FirstName;
  string LastName;
}

change MoveCustomer
{
  identity CustomerId;
  string City;
  string State;
}

change RemoveCustomer
{
  identity CustomerId;
}

Each of these changes is a command object that is routed through the system. They are stored in a sequential log on the server. The current state of a customer is driven exclusively from this set of command objects. Since there is no other way to change a customer, the audit log can be trusted.

Command/query separation
A command changes the state of the system, and a query examines it.

Queries tend to be synchronous, since the server returns results. Some patterns such as AJAX perform queries asynchronously by providing a callback method to capture the results. Even so, the client is in a waiting state until the results are delivered, so the query is synchronous in essence if not in actual fact.

Commands tend to be asynchronous, since the server returns no results. The client only needs a guarantee that the server has received the command. Message queues are often used for commands.

A query can be retried with no ill effects. But this is not always true with a command. if a command is not idempotent, then we must ensure that it is executed once and only once.

Queries and commands are two very different things. Because they have different requirements, they should be handled with separate mechanisms. RPC-based systems, unfortunately, provide onlyl one mechanism for all messaging. There is no enforcement that queries have no side effects, or that commands return no results. As a consequence, queries and commands tend to be intermingled within a single RPC.

Greg proposes a different architecture. When commands are treated as first-class citizens, the separation between commands and queries is easy. Commands are sent to an audit log, and queries are processed out of a reporting database. Don't let the term reporting database confuse you; to Greg any query is a report.

command_query

Eventual consistency
The client workstation, the audit log, and the reporting database are three separate bounded contexts. Each has its own storage schema, its own transaction boundary, and its own interface. The three environments are isolated from one another. The only way for them to reach an agreement is for them to communicate.

Communication takes time. We must allow our distributed systems to be out-of-sync for that time. We cannot guarantee consistency across these bounded contexts at all times. The best we can do is to guarantee that they will become consistent eventually.

Most bounded contexts can interact with relaxed consistency.
- Greg Young

It will take time for data to flow through the system. Sometimes that time is not important. But sometimes decisions must be made with the most up-to-date data possible. Only a domain expert can tell us the difference.

When we acknowledge the fact that communication takes time, we open up a whole new set of discussions with the domain experts. Now we can ask how long is too long. We can start defining service level agreements at the command level. And we can start measuring those times to see when the SLA is violated.

Don't take consistency as a given. Don't automatically define a CRUD service. Take the time to model the changes in your domain. Make those changes part of your discussion with the domain experts. Make them part of your solution.

Alter and Purge

Tuesday, July 28th, 2009

You are aware of the CRUD operations:

  • Create
  • Read
  • Update
  • Delete

Two of these operations are perfectly safe. The other two are destructive.

When you update state, you destroy what used to be there. The old information is lost, overwritten with the new. An audit cannot see beyond the update into the past.

When you delete state, you destroy it outright. I'm referring to a hard delete. A soft delete does not destroy information. But a soft delete is not really a delete.

Make things more explicit
I propose new names for these last two operations, in order to emphasize their destructive nature. Instead of Update, let's call it Alter. An update sounds like your adding fresh data. What you are really doing is altering what was there.

Instead of Delete, let's call it Purge. When you purge something, it no longer exists. It's as if it never was. While you might confuse Delete with a soft delete, you cannot mistake the meaning of Purge.

Auditability
Armed with our new language, let's think about how to audit our systems. Can explain to your legal department how you are Altering records? Can you convince your IT staff that it's OK to Purge data? Don't use terms that sugar-coat the facts. Tell it like it is.

Synchronization
Discrete machines in a distributed system need to exchange information in order to keep each other up to date. If they have each Altered the same data, how do they know which is the correct version? How do they even know that there has been a conflict. The prior version upon which they both agreed is lost.

If one Purges data, should the other Purge it as well? Or should the first Create it again? How can they tell the difference?

Post an article in an RSS feed, then change it. See what happens to the feed aggregators. Create a contact in Outlook and then delete it from your iPhone. See if it goes away.

The data destroyed by Altering and Purging records is precisely the data required to synchronize discrete systems. Retain it.

  • Create
  • Read
  • Alter
  • Purge

I think that's more explicit.

Update Controls for Silverlight 3

Sunday, July 26th, 2009

Now that Silverlight 3 has been released, I have taken the Beta designation off of Update Controls Light.

Update Controls is data binding without INotifyPropertyChanged. You never have to implement it. And you never have to consume it. And now it works with Silverlight 3.

Just like with the Winforms and WPF versions, Update Controls Light requires you to identify independent properties. An independent property is one that can be changed. It's value does not depend upon anything else. For example, a Customer's name is independent, as well as their list of invoices. You indicate that these properties are independent by creating an Independent sentry and calling OnGet() and OnSet() whenever they are accessed or changed.

public class Customer
{
    private string _name;
    private List<Invoice> _invoices = new List<Invoice>();

    private Independent _indName = new Independent();
    private Independent _indInvoices = new Independent();

    public string Name
    {
        get { _indName.OnGet(); return _name; }
        set { _indName.OnSet(); _name = value; }
    }

    public IEnumerable<Invoice> Invoices
    {
        get { _indInvoices.OnGet(); return _invoices; }
    }

    public Invoice NewInvoice(string number)
    {
        _indInvoices.OnSet();
        Invoice invoice = new Invoice(number);
        _invoices.Add(invoice);
        return invoice;
    }
}

Properties that use those independent properties are dependent upon them. Update Controls recognizes those dependencies and fires PropertyChanged events for you.

Think about that. It isn't just firing PropertyChanged for the properties that you indicate as Independent. It's firing PropertyChanged for all the properties that use those properties.

Two lists
Here's an example. This control has two lists: paid invoices and unpaid invoices.

Get Microsoft Silverlight

In a typical program, you would handle the "Paid" and "Unpaid" buttons by removing selected invoices from one list and adding them to the other. But with Update Controls Light, you just change the data model. The two lists are dependent.

public IEnumerable<Invoice> PaidInvoices
{
    get { return _payment.PaidInvoices; }
}

public IEnumerable<Invoice> UnpaidInvoices
{
    get { return _payment.Customer.Invoices.Except(_payment.PaidInvoices); }
}

The body of the UnpaidInvoices property tells the whole story. When you add an invoice to the payment, it no longer appears in UnpaidInvoices. Update Controls Light can see this and fire the right notification events.

Dependent properties never have backing storage. They just reference independent properties in their getters and -- if two-way binding is required -- setters.

Update Controls and INotifyPropertyChanged: never the two shall meet (but if they have to, here’s how)

Thursday, July 9th, 2009

I recently corresponded with a new Update Controls user. He brought up some excellent points about INotifyPropertyChanged and Update Controls. The short answer is: don't mix them. Unfortunately, reality is not so cut and dried.

We started with some easy questions:

Should my view model implement INotifyPropertyChanged [when I'm using Update Controls]?

No, your view model should not implement INotifyPropertyChanged. When you call ForView.Wrap(), Update Controls implements it for you.

So ForView.Wrap() completely replaces the "{u:Update}" syntax?

Absolutely, it does. It is more Blend friendly.

But do I still need to define my Independent's using Ctrl+D, G?

Yes, the underlying dependency tracking is still exactly the same. It still requires Independent sentries, which Ctrl+D, G generates for you.

And then the hard questions began:

If I exposed properties of an object that implements INotifyPropertyChanged (for example, CslaDataProvider.IsBusy) via my ViewModel, do I need to do anything special? Or would it be so simple as:

public bool IsBusy
{
    get { return _dp.IsBusy; }
}

Unfortunately, ForView.Wrap() hides the INotifyPropertyChanged implementation of the root object or any of its properties. So simply passing through the property access would not be sufficient. Neither does the dependency tracking mechanism recognize INotifyPropertyChanged. So when the event is fired, Update Controls does not know to forward that along to the view.

If your class already implements INotifyPropertyChanged and you want to add Independent sentries too, that's fine.

public class Customer : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _name;
    private Independent _indName = new Independent();

    public string Name
    {
        get { _indName.OnGet(); return _name; }
        set { _indName.OnSet(); _name = value; FirePropertyChanged("Name"); }
    }

    private void FirePropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

The INotifyPropertyChanged implementation will be completely ignored by Update Controls, and the Independent will be completely ignored by legacy code.

Or, if you have a legacy object and you completely control the access to its properties, you can wrap it.

public class CustomerWrapper
{
    private Customer _customer;
    private Independent _indCustomerName = new Independent();

    public CustomerWrapper(Customer customer)
    {
        _customer = customer;
    }

    public string Name
    {
        get { _indCustomerName.OnGet(); return _customer.Name; }
        set { _indCustomerName.OnSet(); _customer.Name = value; }
    }
}

But if someone else could change the controlled property without going through your code, you have to handle INotifyPropertyChanged yourself.

public class CustomerWrapper
{
    private Customer _customer;
    private Independent _indCustomerName = new Independent();

    public CustomerWrapper(Customer customer)
    {
        _customer = customer;
        _customer.PropertyChanged += (sender, e) =>
        {
            if (e.PropertyName == "Name")
                _indCustomerName.OnSet();
        };
    }

    public string Name
    {
        get { _indCustomerName.OnGet(); return _customer.Name; }
        set { /*_indCustomerName.OnSet(); Not needed anymore. */ _customer.Name = value; }
    }
}

When the event fires, you record that the property has been set. I'd love to generate a wrapper for you (something like ForViewModel.Wrap()), but I can't think of a way of doing that without hiding the underlying object properties. Maybe with some Ayende mojo I could pull it off, but I'm hoping that I never have to.

Data bound menus

Friday, July 3rd, 2009

I had a twitter conversation recently with Edward Tanguay about his StackOverflow question on binding menus to an Observable Collection. Naturally, I locked on to the ObservableCollection part and didn't get the true gist of his question. I took a step back, reread his question and the provided answers, and finally caught on to the problem. I wish I could upvote Kent Boogaart's answer more than once, because it set me on a trail of discovery.

This example uses Update Controls. Download the example source code: databoundmenus.zip.

There is not just one way to make a WPF menu work. There are several techniques that you have to combine. Much of an application's menu is static. Some of it is context sensitive, and only appears in certain conditions. And in a few places, the menu items are dynamic, like recently opened files or currently open windows. Update Controls can help with all of these things.

Declarative menu structure
For the static menus, you want to declare the structure entirely in XAML. This gives you the greatest design/code separation, and the best tool support. Use Command Binding for all menu items.

<Menu DockPanel.Dock="Top">
    <MenuItem Header="_File">
        <MenuItem Header="_New" Command="{Binding FileNewCommand}"/>
        <MenuItem Header="_Open" Command="{Binding FileOpenCommand}"/>
        <MenuItem Header="_Save" Command="{Binding FileSaveCommand}"/>
        <MenuItem Header="_Close" Command="{Binding FileCloseCommand}"/>
    </MenuItem>
</Menu>

Use Update Controls MakeCommand to create all of the bindable ICommand properties. The When clause will enable and disable the menu item.

public ICommand FileSaveCommand
{
    get
    {
        // We can only save a file when one is open.
        return MakeCommand
            .When(() => _dataModel.OpenFileName != null)
            .Do(() => _dataModel.LastAction = "Save");
    }
}

Some of the menu items are not application actions, but window actions. These can be handled in code-behind.

<Separator/>
<MenuItem Header="E_xit" Click="Exit_Click"/>
private void Exit_Click(object sender, RoutedEventArgs e)
{
    Close();
}

Context sensitive menus
You want context sensitive menus to appear under certain conditions. WPF has a mechanism for that: the DataTrigger. A DataTrigger sets a control property when a data property is equal to a specific value. In this case, we want to set a MenuItem's Visibility property to Hidden when the data property IsFileOpen is False.

<Window.Resources>
    <Style x:Key="VisibleWhenFileIsOpen" TargetType="MenuItem">
        <Style.Triggers>
            <DataTrigger Binding="{Binding IsFileOpen}" Value="False">
                <Setter Property="Visibility" Value="Hidden"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

We apply this style to any menu that is sensitive to this context.

<MenuItem Header="_Edit" Style="{StaticResource VisibleWhenFileIsOpen}">
    <MenuItem Header="Cu_t"/>
    <MenuItem Header="_Copy"/>
    <MenuItem Header="_Paste"/>
</MenuItem>

DataTriggers automatically reset. When the IsFileOpen data property is no longer False, the Visibility control property will go back to the default Visible. There is no need to create another trigger for that rule.

Dynamic menus
For recently opened files or currently open windows, you want each menu item to represent a data object. You want to bind the menu to a list.

If you bind to the raw data objects, you will have a hard time getting exactly the behavior that you want in the view. XAML is declarative, and is easiest to use when the data is already in the right format. That's where the View Model comes in.

public class RecentFileViewModel
{
    private int _index;
    private string _fileName;
    private IFileHandler _fileHandler;

    public RecentFileViewModel(int index, string fileName, IFileHandler fileHandler)
    {
        _index = index;
        _fileName = fileName;
        _fileHandler = fileHandler;
    }

    public string FileName
    {
        get { return string.Format("_{0} - {1}", _index + 1, _fileName); }
    }

    public ICommand Open
    {
        get
        {
            return MakeCommand
                .Do(() => _fileHandler.Open(_fileName));
        }
    }
}

The recent file view model presents the file name in a format suitable for the menu item. It even adds the underscore to turn the 1-based index into a hot key.

The view model also provides the command to open the file. It doesn't actually perform the operation; it delegates to a file handler and provides the context.

We provide a list of these view models based on the list of recently opened files.

public IEnumerable<RecentFileViewModel> RecentFiles
{
    get
    {
        // Create a RecentFileViewModel for each recent file.
        // The view model serves the menu item.
        return _dataModel.RecentFiles
            .Select((fileName, index) =>
                new RecentFileViewModel(index, fileName, this));
    }
}

Please note that this pattern does not work with ObservableCollection. Once you call .Select() on an ObservableCollection, it is no longer observable. This pattern only works with Update Controls.

Now we need to bind MenuItems to this collection. My first instinct was to set the ItemTemplate of the parent MenuItem to a DataTemplate containing a child MenuItem. The problem with that is that a DataTemplate controls the content of the child item, not the child item itself. So instead of setting ItemTemplate, you need to set the ItemContainerStyle.

<MenuItem Header="_Recent Files" ItemsSource="{Binding RecentFiles}">
    <MenuItem.ItemContainerStyle>
        <Style>
            <Setter Property="MenuItem.Header" Value="{Binding FileName}"/>
            <Setter Property="MenuItem.Command" Value="{Binding Open}"/>
        </Style>
    </MenuItem.ItemContainerStyle>
</MenuItem>

A WPF menu should not be defined using just one technique. If you choose something to simple, you won't be able to handle the more interactive requirements. If you choose something too complex, you loose tool support and put too much of your design in code. With this combination of techniques, you can create interactive menus with ease.