TicketDesk 3 Dev Diary – MEF, IoC, and Architectural Design

TicketDesk 2 and TicketDesk 3 have some key architectural differences. Both enforce a strict separation of concern between businesses and presentation layers, but there are major architectural differences within each layer. In this installment, I’d like to talk about how the back-end architecture will evolve and change.

TicketDesk 2 – Decoupled design:

The most significant technology that shaped TicketDesk 2’s class library design was the use of the Managed Extensibility Framework (MEF). The use of MEF in TicketDesk 2 was not about modularity, at least not in a way that is relevant to business requirements. TicketDesk 2 was never intended to support plug-ins or dynamic external module loading. I used MEF for two reasons; I was giving test driven development (TDD) another shot, and I had planned to write a Silverlight client for TicketDesk 2.

MEF was originally built by the Silverlight team. It had a lot of potential for other environments, but didn’t play well with MVC back then. It took some dark magic and hacking to just make it work there. MEF is an extensibility framework first, but an IoC container only by accident. While MEF can do the job of an IoC container, it wasn’t particularly good in that role.

As an extensibility framework, MEF actually has more in common with require.js than traditional server-side IoC frameworks. As a Silverlight technology, the primary purpose was to enable clients to download executable modules from the server on demand when needed. This is exactly what require.js does for JavaScript in HTML applications. The truly interesting thing is that TicketDesk 2 did not use MEF in this way at all. Asp.Net MVC is a server-side environment following a request-response-done type execution flow. Deferred module loading isn’t relevant in that kind of environment. TicketDesk used MEF only for its secondary IoC features — runtime composition and dependency injection.

Considering the difficulty in getting MEF working, and the fact that there are better IoC frameworks for MVC, I should have scrapped MEF in favor of Ninject –which has made me very happy in dozens of other projects. I stuck with MEF partly because it would pay off when I got to the Silverlight client, and partly because I liked the challenge that MEF presented.

Sadly, I was only three weeks into development on TicketDesk Silver, the Silverlight client, when Microsoft released Silverlight’s obituary. I had two other projects under development with Silverlight at the time, so that was a very bad summer for me.

The modular design of TicketDesk’s business layer is mostly about testability. EF 4 was quite hostile to unit testing, so I did what everyone else was doing… I wrapped the business logic in unit-of-work and repository patterns, and made sure the dependencies targeted abstract classes and interfaces. If you want to get all gang-of-four about it, the service classes in TD2 are more transaction script than unit-of-work, but it gets the same job done either way. This gave me the level of testability I needed to follow a (mostly) TDD workflow.

One thing I have never liked about heavy unit testing, and TDD in particular, is having to implement complex architectures purely for the sake of making the code testable. I’ll make some design concessions for testability, but I have a very low tolerance for design acrobatics that have nothing to do with an application’s real business requirements.

TicketDesk 2 walks all over that line. I dislike that there are a dozen or more interfaces that would only ever have one (real) concrete implementation. Why have an interface that only gets inherited by one thing? I also dislike having attributes scattered all over the code just to describe things to an IoC container. Neither of those things make TicketDesk work better. It just makes it more complex, harder to understand, and harder to maintain.

On the flip-side, I was able to achieve decent testability without going too far towards an extreme architecture. The unit tests did add value, especially early in the development process –They caught a few bugs, helped validate the design, and gave me some extra confidence.

If you noticed that the current source lacks unit tests, bonus points to you! My TDD experiment was never added to the public repository. I was pretty new to TDD, and my tests were amateurish (to be polite). They worked pretty well, and let me experience real TDD, but I didn’t feel that the tests themselves made a good public example of TDD in action.

TicketDesk 3 – Modularity where it matters:

A lot has changed for the better since I worked on TicketDesk 2.

Some developers still write their biz code in a custom unit-of-work and repository layer that abstracts away all the entity framework stuff; which is fine. But when EF code-first introduced the DbContext, it became much friendlier towards unit testing. The DbContext itself follows a unit-of work pattern, while its DbSets are a generic repository pattern. You don’t necessarily need to wrap an additional layer of custom repository and unit-of-work on top of EF just to do unit testing anymore.

I plan to move most of the business logic directly into the code-first (POCO) model classes. Extension methods allow me to add functionality to any DbSet<T> without having to write a custom implementation of the IDbSet interface for each one. And the unit-of-work nature of the DbContext allows me to put cross cutting business logic in the context itself. Basically, TD 3 will use something close to a true domain model pattern.

As for dependency injection, the need to target only interfaces and abstract types has been reduced. An instance of a real DbContext type can be stubbed, shimmed, or otherwise mocked most of the time. In theory, I should be able to target stubbed/shimmed instances of my concrete types. If I find the need to target abstracts, I can still refactor the DbSets and/or DbContext to inherit custom interfaces. There still isn’t a compelling need to wrap the business logic in higher layers of abstraction.

In TicketDesk 3, I will not be using a TDD workflow. I love unit testing, but am traditionally very selective about what code I choose to test. I write tests for code that will significantly benefit from them –complex and tricky code. I don’t try to test everything. Using TDD as a design tool is a neat thought process, but I find that design-by-test runs counter to my personal style of design. I can easily see how TDD helps people improve their designs, but I personally tend to achieve better designs when I’m coding first and testing later.

When I do get to the need for dependency injection, I plan to run an experimental branch in TicketDesk 3 to explore MEF 2 a bit further. I think they have fixed the major issues that made MEF 1 hard to use in web environments, but it is almost impossible to find good information online about MEF 2. The documentation, when you can find it, is outdated, contradictory, and just plan confusing. What I have found suggests that MEF 2 does work with MVC 4, but still requires some custom infrastructure. What I don’t know is how well it works.

With the need for dependency injection reduced, few compelling extensibility requirements on the back-end, and no plans to do heavy unit testing, I am more inclined to go with Ninject. They care enough to write top-notch documentation, and it was designed explicitly for the purpose of acting as an IoC container… which is the feature set TicketDesk actually needs.

Asp.net 4.5 mvc or webforms – model binding dropdownlist to an enum with description attributes

One of the more common problems people encounter when working with any .Net user application is the need to put a UI on top of some enumeration. Normally you need to present a friendly list of all the possible items in the enumerator list, then allow the user to pick one of them. This UI typically takes the form of a drop down list, combo box, list box, or similar.

Enums are wonderful in C#, but unlike some other languages, they are also a very thin type. Enums define a collection of named constants. By default, each enumerator in the list equates to an underlying integer value.

Here is an example Enum, and for clarity I’ve specified the value for each enumerator:

public enum CarMake
{
    Ford,     //0
    Chevy,    //1
    Toaster   //2
}

Enums are lightweight, highly efficient, and often very convenient –until you start trying to map them to a UI anyway.

Each of the items, enumerators, within the enum have a name, but the name cannot contain white space, special characters, or punctuation. For this reason, they are rarely user-friendly when converted to a string and slapped into your dropdown lists.

Enter the DescriptionAttribute (from the System.ComponentModel namespace). This attribute allows you to tag your enumerators with a nice descriptive text label, which will fit the UI pretty well if only you can dig the value up. Unfortunately, reading attributes is a cumbersome job involving reflection.

Here is the same enum decorated with descriptions:

public enum CarMake
{
	[Description("Ford Motor Company")]
	Ford,     //0

	[Description("Chevrolet")]
	Chevy,    //1

	[Description("Kia")]
	Toaster   //2
}

To bind up an enum to a drop down list, many developers tend to just manually hard-code the list with user-friendly text values and corresponding integer values, then map the selected integer to right enumerator on the back-end. This works fine until someone comes along later and changes the enum, after which your UI is horribly busted.

To get around this mess, I’ve put together a set of extensions that solves this problem for the common enum to drop down list cases.

Note: I’m using the SelectList class, which comes from Asp.net MVC, as an intermediary container. I then bind the SelectList to the appropriate UI control. You can use SelectList in Asp.net webforms, and most other UI frameworks as well, but you’ll need to implement the code for SelectList. The easiest way to do this is to include the source files for SelectList into your own projects.

The code for SelectList can be found on the AspNetWebStack project page over at CodePlex. Here are the three files needed for SelectList :

The first step in solving the problem is to have an extension method that takes care of reading the description from the enumerators in your enum.

public static string GetDescription(this Enum enumeration)
{
	Type type = enumeration.GetType();
	MemberInfo[] memberInfo = type.GetMember(enumeration.ToString());

	if (memberInfo != null && memberInfo.Length > 0)
	{
		var attributes = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

		if (attributes.Length > 0)
		{
			return ((DescriptionAttribute)attributes.First()).Description;
		}
	}
	return enumeration.ToString(); ;
}

To get an enumerator’s description using this extension method:

string text = CarMake.Ford.GetDescription();

The next challenge is to build a select list for the enum.

public static SelectList ToSelectList(this Enum enumeration, object selectedValue = null, bool includeDefaultItem = true)
{
	var list = (from Enum e in Enum.GetValues(enumeration.GetType())
				select new SelectListQueryItem<object> { 
				   ID = Enum.Parse(enumeration.GetType(), Enum.GetName(enumeration.GetType(), e)), 
				   Name = e.GetDescription() }).ToList();

	if (includeDefaultItem)
	{
		list.Insert(0, new SelectListQueryItem<object> { ID = null, Name = "-- select --"});
	}
	return new SelectList(list, "ID", "Name", selectedValue);
}
internal class SelectListQueryItem<T>
{
    public string Name { get; set; }
    public T ID { get; set; }
}

To get the select list using this extension, you just new-up the enum and call the method:

var carSelectList = new CarMake().ToSelectList();

This extension has an optional parameter to set which item in the list should be selected, and another optional parameter that will include a default item in the SelectList (you may want to adjust this extension to match your own convention for default items).

Here is an example that sets a selected value and includes a default item:

var carSelectList = new CarMake().ToSelectList(CarMake.Ford, true)

I’ve been working in C# for over ten years, and until just this week I had no idea that you could instantiate an enum with the new keyword. Of course I cannot think of reason why you’d normally want to new-up an enum either, but the capability is handy for this extension.

You can also use this extension by calling it on one of the specific enumerator items too. This example does exactly the same as the previous example:

var carSelectList = CarMake.Ford.ToSelectList(CarMake.Ford, true);

I personally prefer the new-up pattern in this case, since it isn’t intuitive that calling ToSelectList on a specifc item would return the list of ALL items from the containing enum.

Now that we have the SelectList, all we have to do is bind it up to a DropDownList.

In Asp.net WebForms 4.5, using model binding, this looks like this:

<asp:DropDownList ID="CarMakeDropDown" runat="server" 
	SelectMethod="GetCarMakeDropDownItems"
	ItemType="MyApp.SomeNameSpace.SelectListItem" 
	DataTextField="Text" 
	DataValueField="Value"
	SelectedValue="<%# BindItem.CarMakeValue %>" 
/>
protected SelectList GetCarMakeDropDownItems()
{   
	return new CarMake().ToSelectList();
}

For more in-depth examples of various techniques for binding SelectList to DropDownList in webforms, see my previous article titled “Asp.net 4.5 webforms – model binding selected value for dropdownlist and listbox“.

In Asp.net MVC model binding to a SelectList is a very common and routine pattern, so I’m not going to provide a detailed example here. Generally though, you make sure your model includes a property or method for getting the enum’s SelectList, then you use the Html.DropDownList or Html.DropDownListFor helper methods. This would look something like this:

@Html.DropDownListFor(model => model.CarMakeValue, Model.CarMakesSelectList)