Julian Birch recently posted a reaction to my reaction to Uncle Bob’s IOC lunacy post. Julian mistakenly thinks that i have a problem with using factories. I definitely don’t have a problem with using factories. I just have a problem with using them in the manner that Uncle Bob suggested in his post. Jeffrey Palermo also recently posted an example of where he thinks using a factory is better than injecting dependencies. I wanted to react to both those posts with a real-world example of where i prefer to use a factory and how i use an IOC container to do so.
As you probably know by now, i’m a big proponent of using IOC containers. I’ve never stated that they should be used in every single application, but using one certainly pays off in most applications, especially as complexity increases gradually. When you use an IOC container, you’ll have much less need for factories. There are however two situations where i certainly prefer to use a factory. And that is when:
- a certain dependency might not always be used by a class and that dependency is expensive to create
- i might need multiple instances of a dependency during the lifetime of a class
A good example of both those situations is when using Agatha’s AsyncRequestDispatcher class from a Silverlight user control. Creating an AsyncRequestDispatcher is expensive because it in turn requires an instance of the AsyncRequestProcessorProxy class. The AsyncRequestProcessorProxy class inherits from WCF’s ClientBase class, and those types are relatively expensive to create. And due to the asynchronous nature of those service calls, you can never deterministically dispose of a AsyncRequestDispatcher instance with absolute certainty that it won’t be disposed before the response of the service call is returned from the service. Because of that, the AsyncRequestDispatcher class was designed to dispose of itself automatically once the response is returned. This effectively means that you’ll need a new instance of AsyncRequestDispatcher whenever you need to make an asynchronous call to an Agatha service.
For most user controls, it obviously doesn’t make sense to inject one instance of the AsyncRequestDispatcher into the user control because you often need to make multiple service calls depending on user interactions or other events. A good way to deal with this is obviously to ask a factory to create the AsyncRequestDispatcher whenever you need one. Which is why Agatha offers the AsyncRequestDispatcherFactory class, which looks like this:
public interface IAsyncRequestDispatcherFactory
{
IAsyncRequestDispatcher CreateAsyncRequestDispatcher();
}
public class AsyncRequestDispatcherFactory : IAsyncRequestDispatcherFactory
{
public IAsyncRequestDispatcher CreateAsyncRequestDispatcher()
{
return IoC.Container.Resolve<IAsyncRequestDispatcher>();
}
}
Now, some of you are probably thinking: what is the difference between this and Uncle Bob’s example? Well, unlike Uncle Bob’s example this factory is not responsible for registering the required components to create an AsyncRequestDispatcher with the container. It merely resolves an instance and returns it. And yes, it uses the container to do so. I could actually just new up an AsyncRequestDispatcher myself but then the factory would also have to know about its dependencies and make sure it’d be able to create them. If those dependencies have dependencies of their own, i’m back to dealing with dependencies manually which is exactly what i’m trying to avoid throughout my codebase.
I can’t come up with a single reason why this would be wrong, but some of you probably will so feel free to point out those reasons ![]()
The benefit of this factory is that it enables me to delay the instantiation of an expensive dependency, and it also enables me to get more than one instance if i need to during the lifetime of a single object. At the same time, it doesn’t have any of the downsides of Uncle Bob’s approach. Also, this approach is something that you won’t need to resort to throughout your codebase, it’s more for edge-cases.
Now, how do we use this factory? Instead of new’ing the factory manually like Jeffrey does in his example, the factory is registered with the IOC container and i simply inject the factory into the class that needs to use it. This still enables me to change implementations of both the factory as well as the instances the factory needs to create. And it also makes it easy to stub or mock the factory during tests. I get all of the benefits from using Dependency Injection and an IOC container, and i have yet to notice any downsides to this approach. But again, i only use this approach in the 2 situations i mentioned in the beginning of this post. In most cases, you really don’t need factories anymore. And when you do, just leverage your IOC container to make the factory as simple and dumb as possible.
Pingback: The Morning Brew - Chris Alcock » The Morning Brew #524