Continuing in my exploration of the Effectus code base, which originated from my Building a Desktop To-Do Application with NHibernate article on MSDN Magazine, I wanted to talk today about how to build an application infrastructure.
First, to be clear, I am not talking about infrastructure pieces such as caching, data access, etc. Those are generic concerns and you should be able to just get them from an off the shelve library. When I am talking about an application infrastructure, I am talking about the infrastructure code that you are going to need to write for a particular application. You are always going to have to do that, even if it is something as simple as just wiring the container together, or registering session handling, etc.
From my point of view, the point of the application infrastructure is to make writing the actual application features as simple as possible. Ideally, you want to make the infrastructure pieces handle everything that isn’t purely related to the feature you are implementing. The reason that an application infrastructure can do this while a generic infrastructure cannot is that an application infrastructure can make a lot of assumptions about the way the application is built.
Let us take the Main screen feature in Effectus, shall we, it will let us look at how this is implemented:
public Observable<int> CurrentPage { get; set; }
public Fact CanMovePrev
{
get { return new Fact(CurrentPage, () => CurrentPage > 0); }
}
public Fact CanMoveNext
{
get { return new Fact(CurrentPage, () => CurrentPage + 1 < NumberOfPages); }
}
public void OnCreateNew()
{
Presenters.Show("CreateNew");
}
public void OnActionsChoosen(ToDoAction action)
{
Presenters.Show("Edit", action.Id);
}
public void OnLoaded()
{
LoadPage(0);
}
public void OnMoveNext()
{
LoadPage(CurrentPage + 1);
}
public void OnMovePrev()
{
LoadPage(CurrentPage - 1);
}
Looking the code, we can see that there are actually a lot of infrastructure playing a part here.
- Automatic binding of On[Button Name]() methods to the button command.
- Within this, enabling / disabling automatically using Can[Button Name] properties
- Automatic binding of On[List name]Choosen(Item) to the selected item changed behavior on the list.
- Automatic updates of property states using Fact.
- Automatic updates of property values, using Observable.
There isn’t much to say about the automatic binding between UI actions and presenter methods, except that I think it is clear how this behavior reduce the level of infrastructure level code that you would have to write, test and maintain. But both Fact and Observable deserve a bit more explanation.
In the LoadPage() method, not shown here, we are updating the CurrentPage property, this will trigger invalidation of the all the facts bound to the value (CanMoveNext, CanMovePrev), which will force their re-evaluation. Since the infrastructure knows how to wire this up to the appropriate commands on the UI, this means that this will enable/disable the given controls automatically. What is more, look at the code. It is clear, concise and pretty easy to reason about and use.
I’ll leave the actual exploration of the implementation to you, it is fairly simple, but the idea is important. The Effectus application actually have more infrastructure code than it have code to implement its features. But that is a very small application. Just to give you an idea, the # of lines of code devoted to infrastructure in Effectus is about 600 LOC! In most applications, you probably wouldn’t even notice the amount of code that the infrastructure takes, but the effects are quite clear.