Sunday 23 November 2014

Type registration in Unity - Code or Configuration

Dependency Injection is one of the important design aspects that makes system just better. It lets you have Dependency Inversion built into your system and lets you managed it with ease. Dependency Inversion is the "D" of the SOLID design principals.

There are plenty of tools available that let you implement Dependency Injection in the applications. I have used Unity Application Block for Dependency Injection functionality for a long time. It is just as good as any other tool available in the market both in terms of features, extensibility and performance.

There are two ways to manage the DI container registrations. Usually i would use a separate file (generally named IOC.config) and mention all the desired registrations in that file. Making the registrations driven by configuration file makes you inject Mock implementation in test projects by just changing it in the file. This usually worked fine for me till now.

Recently though I moved to a team where the software will be built and evolved over multiple iterations (in many months) and it seemed OK to register dependencies through configuration file. It didn't work out all that great :). The main difference was that this solution is just too big and has many moving parts that needed to be deployed at different intervals - that forced us to have multiple IOC configuration and therefore leaving gaps in configuration every time something changed (e.g. namespace change, assembly refactoring, internal interfaces etc.) because configuration files do not force strong typing. Almost every deployment started to reflect one issue or other in IOC configuration file. So the team decided to give up the benefits configuration for ensuring strong type checking by getting rid of IOC configuration files and using Application Startup methods to register dependencies in code.

Learning: If there are multiple deployment units in your solution, it might be better to have type registration in code instead of driving it through configuration file. What we realized was that we almost never ever change configuration file in deployed system anyways :).

Option 2: In case registration becomes error prone, code base can be improved to use convention based approach and have a default implementation registered by default and developers have to register a type only if they do not want to use default implementations. E.g. 

public interface ICustomerGateway{}
public class DefaultCustomerGateway: ICustomerGateway {}

Registration code change be changed to reflect the assembly and references, find public interfaces and register types that have "Default" word appended to their implementations.