Monday, January 08, 2007

Castle project - MicroKernel

In the "Team Work” post I have been talking about an architecture based on contract, in other words – an interface. The presenter for example was using the ILocalDataAccessService and the IOnlineService services.
What happens if the current presenter needs another service? We should change the presenter constructor, and all initialization. We could have the same problem as the one I talked about in the previous post, with the Object Mother – we could have to change the code in a lot of places and maybe hundreds of tests. This is one of the many problems which could appear because of a tight coupled architecture. The dependency using constructor injection isn’t enough sometimes, for example a presenter can use a service only in a specific moment, or it can use a service which isn’t available all the time, so the service shouldn’t necessarily be given as a constructor parameter.
The ideal way is to have an infrastructure, a framework which solves all these problems automatically for us, so we shouldn’t worry about a complex service dependency, or service creation.

The first idea is to have a collection of services, which can be retrieved at any time using their names, and/or interface they implement. These would solve our problem with the service we don’t use all the time, or they could be unavailable at a specific time.

IService service = (IService) Kernel[“My service”];

The second idea is to automate the construction of services, if a service A needs to be constructed and it depends on another service - B, the framework should automatically retrieve the service B from the collection and construct the service A. So the services should be instantiated automatically without having to call explicitly the constructors.
Kernel.AddService(“Service A”, typeof(AService));
Kernel.AddService(“Service B”, typeof(BService));

If the BService class has a constructor with a AService parameter, the framework should automatically call the constructor with the service “A” added in the first step.

Another problem would be the service “style”: is the service a singleton? Or should a different instance be created for every call of Kernel[“My Service”] ? Or maybe create a service for each thread? These details should also be handled by the framework.

So, we shouldn’t be worried when changing the constructor of a service. The infrastructure should have to worry now. We could also use this framework for a plugin architecture: until now, I have worked at a few applications which used plug-ins, and most of the time, a plugin defined in fact a service. I had to do every time my own manager for these plugins. Some plugins were singletons, some would had to be instantiated for every call, but I had to think how to do all this by myself. I didn’t use a framework which could do all the work for me.

Some days ago I have searched for such a framework and I found exactly what I was looking for. It is called the Castle Project – MicroKernel. I started using this framework, and – until now, I am very pleased with the results.

No comments: