Sunday, July 25, 2004 - Posts
I have been using dependency injection as a mechanism to help shape the design of my code for a while now. I find it to be extremely useful in helping me write highly-decoupled, easily testable, well composed software. Dependency injection allows me to cleanly separate the creation of an object from the way it is used. In fact, I often end up in a situation where I have as many occurrences of the new keyword as I have classes in the system.
Injecting a dependency raises some interesting questions for object disposal. Does an object take responsibility for disposing of its dependencies? In the pre-depedency injection world, the answer would be yes as the object both instantiates and destroys its dependencies. However, as the depedency has a life outside of the object that uses it, it would be wrong for the object to try and dispose of it.
It is worthwhile to consider that the origins of depedency injection are in the world of container management. There, the container is responsible for not only creating, but also for managing the lifecycle, of its components (this is the crucial difference that distinguishes containers from factories). Hence it should be the responsibility of the container to ensure not only that the dependency is properly injected, but also that it is appropriately destroyed. This has the advantage of centralising the disposal of your components in the same way that a factory encapsulates their creation. It also means that you can centrally manage the sequence of their destruction (generally such a big issue in non-memory managed languages).
So, what are the implications for C#? If a component implements IDisposable, call Dispose in your container. One nice thing about this approach is that, as the container knows which specific instance it is instantiating, you can keep the Dispose method out of your component interface. Implementing IDisposable is the product of the way a component is implemented . As such, it should not be part of the component interface. So check if you have any interfaces that implement IDisposable, and, if so, think about moving this into a container instead.
The problem with proxy customers (business analysts assigned to work with a distributed team) is that they serve as a layer of abstraction between the developers and the customer. While this seems like a statement on the obvious, the implications are not necessarily so. The primary concern with the use of customer proxies is that they may misinterpret the customer's requirements so that the development team ends up building the wrong thing. However, with highly iterative Agile development, this is unlikely to happen because the real customer has the opportunity (and responsibility) to regularly review what's been developed thus far. If the development team is off track, they tend to find out pretty quickly.
The main concerns that I have with customer proxies is that they tend to be too good at shielding the development team from direct interaction with the customer. As I see it, this creates two main challenges:
- developers are less likely to learn the language of the domain. As proxy customers are generally more technically-inclined than real customers, it is easier for the devs and the proxies to communicate using the language of the system rather than the language of the domain. This eliminates part of the compulsion to build a common understanding of the domain (the Ubiquitous Language that Eric Evans describes in Domain Driven Design) and, when developers actually have to try to explain the system to real customers and users during presentations or training, it becomes very hard for developers to get their ideas across.
- developers lose visibility in the eyes of the customer. This is especially dangerous as it can become easy to dehumanise the developers and be less tolerant of any mistakes they might make (especially in an offshore engagement where there is an implicit backdrop racial prejudice).
That said, customer proxies are essential to distributed projects. If developers need business questions answered and the real client is time zones away, the immediate feedback that a customer proxy can give is invaluable. However, what is important is to establish a process that ensures that the developers have the opportunity to regularly engage with the customer directly.
I have just finished Margaret Macmillan's Paris 1919, a fascinating account of the Paris peace process that followed World War I, culminating in the Treaty of Versailles and the founding of League of Nations. The Allied negotiators found themselves taking on the herculean task of trying to "fix the world", resolving the boundaries of all those nations that were drawn into the conflict. The decisions that they made have shaped much of the world today, and contingently contributed to many of its recent global conflicts: from the four Balkan wars of the 90s, to the civil war in Lebanon and the ongoing Palestinian conflict. Most pertinently, the peace process had the dubious distinction of drawing the borders of modern Iraq (at time, the British protectorate of Mesopotamia). Macmillan ominously described this decision:
In 1919 there was no Iraqi people; history, religion, geography pulled the people apart, not together. Basra looked south, toward India and the Gulf; Baghdad had strong links with Persia; and Mosul had closer ties with Turkey and Syria. Putting together the three Ottoman provinces and expecting to create a nation was, in European terms, like hoping to have Bosnian Muslims, Croats, and Serbs make one country.
With this as the basis for constructing a nation, it hardly bodes well for the future of a new "independent" Iraq.