After hearing about Microsoft Unity from the .NET architects at my current company (my daily job), I bought the book Dependency Injection in .NET, by Mark Seemann some weeks ago to learn dependency injection and Inversion of Control (IoC) containers, just for curiosity because I thought it wouldn’t apply to my MZ-Tools add-in, or to Visual Studio extensions. I couldn’t be more wrong. I think this is the book that more profoundly has changed my mindset about creating software , because the concepts of programming against interfaces and loose coupling (explained in part 1 of the book) are one of the most important things that you need to master as a developer to create maintainable software, as now I have realized. Dependency Injection (DI) is the means to achieve loose coupling. The second part of the book explains DI patterns, anti-patterns and refactorings. The third part explains the three dimensions of DI: object composition, object lifetime and interception. The fourth part explains several DI containers of the many ones available for .NET. As the book explains, DI containers are optional, but even if you don’t use them, the software will benefit a lot from a loose coupled design.
How does this relate to developing Visual Studio add-ins? After reading the book I have realized that in my case in at least three aspects, and I wish I had read the book before:
1) Visual Studio add-ins hold a tight coupling with some dependencies such as the EnvDTE.dll, EnvDTE80.dll and VSLangProj.dll assemblies, that provide the automation model for add-ins. In all likelihood, all the features of your add-in depend on EnvDTE.Solution, EnvDTE.Project, EnvDTE.EditPoint, etc. Imagine now that you have to migrate your add-in to a Visual Studio package (SDK), because Microsoft plans to remove add-ins. It would be much easier if the features of your add-in would depend only on interfaces such as ISolution, IProject, IEditPoint that are implemented by classes that encapsulate the automation model for add-ins (EnvDTE.Solution, EnvDTE.Project), and later by classes that encapsulate the SDK services of packages (IVsSolution, IVsProject).
2) A loose coupled design and dependency injection allows to use unit testing more easily. Automated testing for add-ins is hard. So far I had done integration testing (with my own test runner), which while it is automated, it is slow and can’t be integrated easily with continuous integration (CI). Now I want to use unit testing too (because of the fast speed) through stubs, but since I haven’t used dependency injection I am finding problems to achieve a clean approach.
3) MZ-Tools 8.0 will support Visual Studio, VB6 and VBA as hosts. I am encapsulating the very different automation models with concrete classes such as SolutionEx, ProjectEx, etc. using partial classes and conditional compilation. But after reading the book I have realized that it would be better to use either interfaces or abstract classes.
I will try to find time to write a series of posts with code about using loose coupled design and dependency injection developing add-ins for Microsoft IDEs. Stay tuned.