IoC patterns – partitioning registration

I’ve blogged a bit in the past, more or less explicitly, about patterns and antipatterns of Inversion of Control usage. This is yet another post that will (possibly) spawn a series. We’ll see about that. Note that this post is not talking about any particular IoC container and what I’m talking about is generic and universally applicable to all of them.

Historically we started to register and configure our components in XML (example is in pseudo syntax, not specific to any particular framework).

<components>
   <register name="foo" type="Acme.Crm.Foo, Acme.Crm" as="Acme.Crm.IFoo, Acme.Crm" />
   <register name="bar" type="Acme.Crm.Bar, Acme.Crm" as="Acme.Crm.IBar, Acme.Crm">
      <parameter name="bla" value="42" />
   </register>
   <!--... many, many more components like this...-->
</components>

Later we learned that it’s massive pain in the neck to write and manage, and we moved to code:

container.Register<Foo>().As<IFoo>().WithName("foo");
container.Register<Bar>().As<IBar>().WithName("bar")
   .WithParameter("bla", 42);
/* ...many, many more components like this... */

This had the advantage over  XML of being strongly typed, refactoring friendly, but still shared the biggest drawback of the previous approach. For each and every new component you added to your application you would have to go back and explicitly register it.

To alleviate that, many containers support conventions – where naming the type in the “right” way or putting it in the “right” place would be enough to make that type available as a component.

container.RegisterAllTypesInNamespace("Acme.Crm")
   .AsInterfaceTheyImplement()
   .NamedAsLowercaseTypeName()
   .WithParameterFor<Bar>("bla", 42);

You would still need to do some finetuning with some of the components, but for bulk of it, it would just work.

So where’s the problem?

While the last approach is evolutionally the most advanced it too comes with its own set of drawbacks, that can bite you if you don’t pay attention to them.

If you partition your application abstracting implementation detains with interfaces and registering classes via conventions you will end up with highly decoupled application. So decoupled in fact, that you will have no explicit reference to your classes anywhere outside your tests. This can complicate things when a new person comes to the project and tries to figure out how stuff works. Simply following ReSharper’s “Go to definition”/”Go to usage” won’t cut it. Often you can infer from the interface or usage which class is used under which interface, but if you have generic abstraction (like ICommandHandler) and multiple implementations that get wired in a non-trivial way it may quickly become much more complicated to find out how the stuff gets wired and why it works the way it does.

Partition your registration

 Installers

To minimize problems like this its crucial that you partition your registration correctly. What do I mean by that?

First of all make it granular. Most containers have some means of dividing your registration code into pieces. Windsor has installers, Autofac and Ninject have modules, StructureMap has registries… Take advantage of them. Don’t just create one and put all your registration in one. You will regret it when later on you try to change something and you find yourself scrolling through this monstrous class. Make it granular. Partition is applying Single Responsibility Principle. Even if your installer (I will stick to Windsor lingo – replace with module/registry if you’re using any other container) ends up registering just a single type – that’s fine.

Remember to name them correctly so that it’s very quick and obvious having a type, to find which installer is responsible for its registration/configuration.

To do that – also pay attention to the name you give your installers. If the next developer has to stop and think, or search several to find the right one for a particular service you’ve failed.

Last but not least – keep them all in one visible place. I generally create folder/namespace dedicated to holding my installers, so that I can find them quickly and scan the entire list at once. It’s really very frustrating having to chase down installers all across the solution.


Posted 08-10-2010 11:44 AM by Krzysztof Koźmic
Filed under: ,

[Advertisement]

Comments

Chris Canal wrote re: IoC patterns – partitioning registration
on 08-10-2010 12:39 PM

We've been doing this with installers for a while now, the new stuff in 2.5 for easily pulling out installers is a blessing :D

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)