After my recent review of Continuous Integration in .Net, I wanted to review another book as i enjoyed it a lot. Therefore I was offered the opportunity, by Manning Books, to review Dependency Injection in .Net by Mark Seemann. For me this seemed to be a great book to review as I really wanted to get into DI. I really wasn’t disappointed.
The book is structured as follows:
- Part I : Introduction to DI (chapters 1 – 3)
- Part II: DI Catalogue (chapters 4 – 6)
- Part III: DIY DI (chapters 7 – 9)
- Part IV: DI Containers
For me the book was well structured, as it stems from putting the basics of what DI is in place, then stemming through how to implement DI and then on to actual implementations of DI with specific containers.
Chapter 1: Tour de DI
What problems does tightly coupled code cause? What is n-tier architecture or modular applications? How does DI solve this?
This chapter is a basic introduction of what DI has been designed to do and what is actually involved in the principal of DI.
Chapter 2: DI Fundamentals
As developers, we may think we know the best practices and best ways of doing things but we may not know why we do these things in this way. Ask yourself this question:
Has there ever been a time when you implemented what you thought was great only to realise it wasn’t scalable or extensible?
I reckon the answer would be yes as we never produce 100% perfect code as we are always learning. The author then goes on to speak about N-tier architectures and seams. This is where my previous understanding of DI failed. There are 2 types of dependencies:
- Volatile (e.g. database, network, file system etc.)
- Stable dependencies (references to BCL)
DI is the technique to control these dependencies but with implementing DI we may loose control of where, when and how dependencies are created and destroyed. Great chapter to set the scene of what DI actually is.
Chapter 3: DI Containers
What are DI containers? What do them do? This chapter discusses the answers to these questions. There is a great analogy to making ice-cream here that demonstrates that DI containers are facilitators, basically the “thing” that provides functionality but that can take care or other work as well.
DI Containers, or IoC containers, take care of all the features talked about in chapter 2. They will require configuration for this to happen and this can happen in different ways:
- Configuration files
- Directly in Code
The author uses Castle Windsor to extend the sample application to show its use. There is also talk about how we have got to where we are with the number of DI containers and how the concept was formed. The Castle Windsor was introduced a bit early in my opinion, but I can see why it was done. Stick with the chapter as it is a required read.
Chapter 4: DI Patterns
This is the proverbial meta of a DI container sandwich. This explains “How Do I Inject My Dependencies?”. The author seems to suggest there are 4 main patterns:
- Method Injection
- Property Injection
- Ambient Content
- Constructor Injection
The author explains each pattern in detail and then relates this back to the sample application.It seems that constructor injection is the default and is actually what I believed what DI actually was. There is a great flowchart on how to choose which pattern to use. This is a great chapter for principles and patterns lovers.
Chapter 5: DI Anti-patterns
In this chapter, the author discusses the patterns for intended use of DI can go wrong and talks about these being ‘anti-patterns’. The author discusses 4 anti-patterns in specific:
- Direct Control
- the use of the new keyword i.e var x = new ClassName();
- Bastard Injection
- having different constructors for unit testing that accept injected dependencies
- Constrained Construction
- Implementing abstraction but then doing something silly like passing a connection string to the constructor
- Service Locator
- This is an area of contention where some people like this pattern but the author doesn’t
This is a great chapter, it shows that sometimes everything doesn’t go exactly as expected. This almost demonstrates that we are all human and no matter how we code, we can sometimes get ourselves into a state where we introduce dependencies.
Chapter 6: DI Refactoring
After finding all about the anti-patterns of DI, how do we stop ourselves having a pile of dependency ridden spaghetti code? The answer is through refactoring, unit testing & integration testing.
When we get dependency cycles in our code we need to break the (see post on Breaking The Dependency) and that we can choose a suitable injection method, constructor or property in order to inject the dependency that we require. One thing we do need to do, is to make sure that we are not injecting too many different types. If this is the case we need to revisit our design to create smaller, more focused classes via refactoring.
We can use external tools in order to make sure dependencies are not created in our code, e.g. NDepend. But we can also use unit tests and integration tests to do a similar thing.
This is a very important chapter as it explains the theory behind refactoring dependencies out of our code and more importantly, they stay out.
Chapter 7: Object Composition
This chapter is concerned with object composition and how we can choose a suitable composition root for some examples of everyday projects, e.g. WCF applications, console applications, Powershell, Webforms and MVC. The theory of object composition was discussed a lot earlier in the book and this is actually how we can choose a composition root in reality.
This chapter has actually taught me how and where to start implementing “proper” DI into a new ASP.NET MVC 2 site I’m working on currently. As you can image, this was most useful to me. The next 2 chapters continues to talk about how we implement the basic parts of a DI container.
Chapter 8: Object Lifetime
Initially, it was discussed that a DI container took away the natural ability we have of controlling an object and its lifetime. This chapter actually proves that this initial thought is rubbish and gives examples of how objects can be controlled using different lifestyles.
This again is a key chapter in understanding actual ‘real-world’ implementation of a DI container. Initially for me i was creating all my lifestyles as ‘Transient’ but this chapter has taught me that this may not actually be correct.
Chapter 9: Interception
This chapter talks about Interception and how it can be used in conjunction with a DI container to keep code “clean”, “solid” and “DRY” – all principles that we would love to be able to adhere to. Interception is actually only available via a real DI container and NOT via “poor man DI”.
This almost puts DI containers and DI itself on a pedestal. It shows how superior it is to implement “real” DI and not “poor man” DI. The take away for me confirms that all the initial thoughts about how DI can be dangerous as we cannot control our object creation, lifetime and destruction is absolute rubbish
Chapters 10 – 15 – DI Containers
The different containers covered here were as follows:
- Castle Windsor
- Structure Map
- Microsoft Extensibility Framework
This was a fantastic book and I have since started to put into practice the principles I have learned and have been shown how to implement. It was tough to get going with this book as the immediate start to the book speaks about cooking and draws similarities of cooking to DI. These food similarities continued throughout the book, and to be totally honest, I was getting a bit put off by it. But then after finishing Part II of the book, things started to ‘click’. The penny dropped and I understood the similarities.
I’d very much recommend this book to people who are interested in DI. But I must stress that you need to stick with it as it can become quite heavy in places. One thing I’m sure of is that if you are not very much up to speed with the theory, principles and practices of DI, then you certainly will be after it. It gets 3 [.5] out of 5 for me.
Thanks to Manning books and the author (Mark Seemann) for the content.