2008/02/28

The Component Burden Concept

Important Note: Mort that I am, I have mistaken ReleasePolicy for Component Burden and blogged about the former... As soon as I know what I am writing about, I will update that post.

There is a discussion on the Castle mailing list recently about the Component Burden problem. This is one of the oldest Castle issues (and the oldest that is not resolved by now). Now, the issue got a little bit of momentum by Ayende's post and Hammett's blog entry about it.

In short, the problem is this: If there are non-singleton components created by the IoC-Container that implement IDisposable, someone sometime needs to call Dispose(). However, both someone and sometime pose a problem:

  • Someone could be the using code or the container. It has been proposed that a component should dispose it's dependencies itself, but if you think about it, this is problematic because the component cannot know it's dependencies' lifestyles. Just imagine a service configured to run as a singleton being disposed after the very first request it served, because an using component doesn't need it anymore. Additionally there is a simple principle about resource allocation: The code that allocates a resource is responsible for deallocation too. Period. Back when C/C++ was used, every developer adhered to that principle because there was no GC...
  • Sometime is dependent on the components lifestyle. A singleton must not be disposed before the container shuts down itself while a transient component must be disposed as soon as possible to free allocated resources.

Now it is clear that the container is fully responsible for both construction and destruction of dependency objects. But how will it know, when the component is not used anymore?

Well, at least one component must be resolved from the container. This component must be released after you are finished using it:

MyComponent c = container.Resolve<MyComponent>(); // Some work container.Release(c);

Do you need to do this even if you're component is not disposable? Yes, because it can have direct or indirect dependencies that are disposable. If you don't release it, the container cannot know that it is now safe to dispose these dependencies, when they are otherwise unused.

Now there is one thing missing: The container must keep track of the dependencies. Assume that your component uses a custom per-web-request-logger that uses a FileStream.

Every time you resolve a component that uses the logger in one web request, the dependency will be fulfilled with the same logger. If you release a component, the container must remember that it used the logger, then check whether the logger is still used by other instances and if not, dispose the logger.

This bookkeeping of dependencies and disposal is called the component burden in the Castle project.

Although I don't know Microkernel's source code for this, I have an idea how to implement such a concept. But this is a topic for another post.