IoC concepts: Service

As part of preparing for release of Windsor 3.1 I decided to revisit parts of Windsor’s documentation and try to make it more approachable to some completely new to IoC. This and few following posts are excerpts from that new documentation. As such I would appreciate any feedback, especially around how clearly the concepts in question are explained for someone who had no prior exposure to them.

As every technology, Windsor has certain basic concepts that you need to understand in order to be able to properly use it. Fear not – they may have scary and complicated names and abstract definitions but they are quite simple to grasp.

Service

First concept that you’ll see over and over in the documentation and in Windsor’s API is service. Actual definition goes somewhat like this: “service is an abstract contract describing some cohesive unit of functionality”.

Service in Windsor and WCF service
The term service is extremely overloaded and has become even more so in recent years. Services as used in this documentation are a broader term than for example WCF services.

Now in plain language, let’s imagine you enter a coffee shop you’ve never been to. You talk to the barista, order your coffee, pay, wait and enjoy your cup of perfect Cappuccino. Now, let’s look at the interactions you went through:

  • specify the coffee you want
  • pay
  • get the coffee

They are the same for pretty much every coffee shop on the planet. They are the coffee shop service. Does it start making a bit more sense now? The coffee shop has clearly defined, cohesive functionality it exposes – it makes coffee. The contract is pretty abstract and high level. It doesn’t concern itself with “implementation details”; what sort of coffee-machine and beans does the coffee shop have, how big it is, and what’s the name of the barista, and color of her shirt. You, as a user don’t care about those things, you only care about getting your cappuccino, so all the things that don’t directly impact you getting your coffee do not belong as part of the service.

Hopefully you’re getting a better picture of what it’s all about, and what makes a good service. Now back in .NET land we might define a coffee shop as an interface (since interfaces are by definition abstract and have no implementation details you’ll often find that your services will be defined as interfaces).

public interface ICoffeeShop
{
   Coffee GetCoffee(CoffeeRequest request);
}

The actual details obviously can vary, but it has all the important aspects. The service defined by our ICoffeeShop is high level. It defines all the aspects required to successfully order a coffee, and yet it doesn’t leak any details on who, how or where prepares the coffee.

If coffee is not your thing, you can find examples of good contracts in many areas of your codebase. IController in ASP.NET MVC, which defines all the details required by ASP.NET MVC framework to successfully plug your controller into its processing pipeline, yet gives you all the flexibility you need to implement the controller, whether you’re building a social networking site, or e-commerce application.

If that’s all clear and simple now, let’s move to the next important concept (in the next post).

Must I release everything when using Windsor?

This is a follow up to my previous post. If you haven’t yet – go and read that one first. I’ll wait.

So where were we? Aha…

In the last post I said, that Windsor (any container in general) creates objects for you, hence it owns them, ergo its responsibility is to properly end their lifetime when they’re no longer needed.

Since as I mentioned in my previous post, Windsor will track your component, it’s a common misconception held by users that in order to properly release all components they must call Release method on the container.

container.Release(myComponent);

How will Windsor know I no longer need an object?

That’s the most important part of this post really, so pay attention.

In Windsor (every container in general) every component has a lifestyle associated with it. In short lifestyle defines the context in which an instance should be reused. If you want to have just single instance of a component in the context of the container, you give the object a singleton lifestyle (which is the default in Windsor). If you want to reuse your object in the context of a web request, you give it a lifestyle of a per-web-request and so on. Now the word context (though overloaded) is important here.

When the context ends?

While some contexts, like web request have a well defined ends that Windsor can detect, that’s not the case for every of them. This brings us to the Release method.

Windsor has a Release method that you use to explicitly tell it “hey, I’m not gonna use this this object anymore.” Although the method is named very imperatively, which would suggest it takes immediate action, it’s not often the case. Quite a lot of time may pass between you call the method and Windsor will get the object destroyed. When the object gets really destroyed is up to its lifestyle manager, and they act differently.

  • Singleton will ignore your call to Release because the instance is global in the scope of the container that created it, and the fact that you don’t need the object in one place does not mean you won’t need it moments later somewhere else. The scope of the singleton lifestyle has a well defined end. Windsor will destroy the singletons when the container itself is being disposed. This also means that you don’t have to Release your singletons – disposing of the container will take care of that.
  • Per-web-request will ignore your call to Release for similar reasons – the object is global in the scope of a web-request. Web request also has a well defined end, so it will wait with destroying the object till the end of the web request and then do all the work necessary. This also means that you don’t have to release your per-web-request components – Windsor can detect end of a web request and release the per-web-request components without and intervention from your side.
  • Per-thread is like singleton in the scope of a thread. Releasing Per-thread components does nothing, they will be released when the container is disposed. This means that in this case as well you don’t have to do anything explicitly about them (except for remembering to dispose the container obviously) ..
  • Pooled components are different. They don’t really have a well defined “end” so you need to return a component to the pool explicitly (that is pass them to container’s Release method), and Windsor (depending on the component and configuration of the pool) may either return the object to the pool, recycle it, or destroy and let it go. Thing is – it matters, and it usually makes sense to return the object to the pool, as soon as possible (think connection pooling in ADO.NET).
  • Transient components are similar to pooled, because there’s no well known end to transient component’s lifetime, and Windsor will not know if you still want to use a component or not, unless you explicitly tell it (by calling Release). Since transient components are by definition non-shared Windsor will immediately destroy the component when you Release it.

And then it gets interesting

If you’re now scratching your head thinking “Does Windsor really puts all the burden of releasing stuff on me?” don’t despair. The reality is – you never have to call Release explicitly in your application code. Here’s why.

You never have to call Release…

Releasing a component releases entire graph. As outlined in previous section, Windsor can detect end of scope for components with most lifetimes. In that case, if you have a per-web-request ShoppingCard component that depends on transient PaymentCalculationService and singleton AuditWriter, when the request ends Windsor will release the shopping card along with both of its dependencies. Since auditwriter is a singleton releasing it will not have any effect (which is what we want) but the transient payment calculator will be releases without you having to do anything explicitly.

You obviously need to structure your application properly for this to work. If you’re abusing the container as service locator than you’re cutting a branch you’re sitting on.

Explicitly…

This also works with typed factories – when a factory is released, all the components that you pulled via the factory will be released as well. However you need to be cautious here – if you’re expecting to be pulling many components during factory’s lifetime (especially if the factory is a singleton) you may end up needlessly holding on to the components for much too long, causing a memory leak.

Imagine you’re writing a web browser, and you have a TabFactory, that creates tabs to display in your browser. The factory would be a singleton in your application, but the tabs it produces would be transient – user can open many tabs, then close them, then open some more, and close them as well. Being a web savvy person you probably know firsthand how quickly memory consumption in a web browser can go up so you certainly don’t want to wait until you dispose of your container to release the factory and release all the tabs it ever created, even the ones that were closed days ago.

More likely you’d want to tell Windsor to release your transient tabs as soon as the user closes it. Easy – just make sure your TabFactory has a releasing method that you call when the tab is closed. The important piece here is that you’d be calling a method on a factory interface that is part of your application code, not method on the container (well – ultimately that will be the result, but you don’t do this explicitly).

UPDATE:

As Mark pointed out in the comment there are certain low level components that act as factories for the root object in our application (IControllerFactory in MVC, IInstanceProvider in WCF etc). If you’re not using typed factories to provide these service and implement them manually pulling stuff from the container, than the other rule (discussed below) applies – release anything you explicitly resolve

In your application code

There are places where you do need to call Release explicitly – in code that extends or modifies the container. For example if you’re using a factory method to create a component by resolving another component first, you should release the other component.

container.Register(
   Component.For<ITaxCalculator>()
      .UsingFactoryMethod(k =>
      {
         var country = k.Resolve<ICountry>(user.CountryCode);
         var taxCalculator = country.GetTaxCalculator();
         k.ReleaseComponent(country);
         return taxCalculator;
      })
   );

This is a code you could place in one of your installers. It is completely artificial but that’s not the point. Point is, we’re using a factory method to provide instances of a component (tax calculator) and for this we’re using another component (country). Remember the rule – You have to release anything you explicitly resolve. We did resolve the country, so unless we are sure that the country is and always will be a singleton or have one of the other self-releasing lifestyles, we should release it before returning the tax calculator.

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.