Home / .NET / Agile UI Development in .NET: Tools

Agile UI Development in .NET: Tools

In the last post, I showed you the big picture of my UI design pattern. Before I can start showing you sample code for the different parts, I need to introduce some tools, which are used to glue all the tiny parts together:

  • Dependency Injection
  • Design By Contract
  • Synchronous and Asynchronous Communication
  • Test Driven Development

Dependency Injection – Ninject

We use dependency injection to decouple build-up from execution time. First, all is built-up, then the code is executed.

This helps a lot regarding the Open-Close and Dependency Injection principles of SOLID.

In ProCollEE, I use Ninject as Dependency Injection Container. Ninject works basically in the following manner:

First, instantiate a kernel:

StandardKernel kernel = new StandardKernel();

Then, you can define mappings (e.g. from interfaces to classes):

kernel.Bind<IMainViewModel>().To<MainViewModel>().InSingletonScope();

This results in the behaviour that every time a IMainView is required, the same instance (singleton) of the MainView class is returned.

Finally, you can use the mapping in code (e.g. constructor injection):

public MainView(IMainViewModel viewModel)
{ ... }

When a MainView is requested from the kernel then an instance is created that gets a view-model injected.

As you can see, the MainView class does not have to know anything about the MainViewModel class. It simply states that it needs an IMainViewModel instance. Which instance is used, is defined by the mapping code that is decoupled from the MainView and MainViewModel.

Ninject supports three kinds of injection:

  • Constructor injection
  • Method injection
  • Property injection

To use property or method injection, the Inject attribute has to be placed on the property or method. You’ll see samples later in the series.

There is much more to dependency injection, but for now this is sufficient.

Design By Contract – Code Contracts

Design by Contract uses pre-, post-conditions and invariants to verify the correct behaviour of the code. This helps finding defects in code early during development a lot, especially because my UI design pattern consists of several parts. If one part does not work as expected by another part using it then the contract is violated and an exception is thrown.

I use Microsoft’s Code Contracts to check design contracts. Let’s look at a sample:

public class Rational
{
    private int numerator;
    private int denominator;

    public Rational(int numerator, int denominator)
    {
        Contract.Requires(denominator != 0);

        this.numerator = numerator;
        this.denominator = denominator;
    }

    public int Denominator
    {
        get
        {
            Contract.Ensures(Contract.Result<int>() != 0);
            return this.denominator;
        }
    }

    [ContractInvariantMethod]
    protected void Invariant()
    {
        Contract.Invariant(this.denominator != 0);
    }
}

The code contract requires that the denominator passed in the constructor is not equal to zero. The same applies to the return value of the property and the invariant.

I hope you get the idea from this short sample. Again, this is not very important but helps to understand the sample code later.

Synchronous and Asynchronous Communication

I’m sure you don’t like it when the application you are using does not react to your input because it is doing some work. Me, too! Therefore we should not block the user interface thread but do the work asynchronously in a worker thread. When the worker thread is finished then the UI has to be updated.

In WPF, Microsoft introduced the Dispatcher that can be used to synchronize from a worker thread back onto the user interface thread in order to update some visualized data. However, this mechanism is rather low-level and not handy to use throughout the UI layer.

In ProCollEE – and all my other applications – I use the event broker of bbv.Common.

The event broker allows to send and receive events synchronously and asynchronously between publishers and subscribers of an event topic:

EventBroker

Let’s look at a small sample:

class Publisher
{
    [EventPublication("topic://SimpleEvent")]
    public event EventHandler SimpleEvent;
}

public class Subscriber
{
    [EventSubscription("topic://SimpleEvent", typeof(Handlers.UserInterface))]
    public void SimpleEvent(object sender, EventArgs e)
    { }
}

After both the Publisher and Subscriber were registered on an event broker, the subscriber receives the events fired by the publisher.

The subscriber in the above sample defines that the handler should be called on the user interface thread: typeof(Handlers.UserInterface). The event broker takes care to switch threads and there is no need to use a dispatcher directly.

Please see this tutorial for further details.

Test Driven Development

We use test driven development (TDD) as a tool for several reasons:

  • less defects
  • simpler code
  • better development parallelism
  • faster development

It is simply a fact that code, which is developed in a test driven way, has less defects.

Our code gets simpler because TDD forces you to use a testable design. Testable designs are also designs that don’t get too complicated.

When using TDD then you don’t need a complete environment to run the code you are just writing. All you need are clear interfaces to the dependencies of your code so that you can use mocks to simulate the environment. This boost the possibility for parallelism – work being done concurrently by several developers at the same time. You can get things done faster.

Additionally, you can test your code within a few seconds in your unit tests and don’t have to start the whole application and navigate to the UI that calls your code, which could take up to several minutes or even hours.