i gotta dependency on dependency injection
Post on 02-Jul-2015
Embed Size (px)
DESCRIPTIONSatisfy your desire to be a better software developer by learning how to implement Dependency Injection (DI) in your application. Dependency Injection is one of the more popular implementations of Inversion of Control (IoC) that helps to increase modularity and extensibility of software. In this lecture, we'll discuss the benefits of DI, methods for implementing and refactoring existing code to use DI, adding unit tests using MSTest and Moq, popular DI frameworks like Unity, Ninject, and Castle Windsor, as well as alternative IoC patterns and anti-patterns.
- 1. I Gotta Dependence on Dependency Injection November 15 2014 Matt Henroid (@mhenroid) Senior Consultant Daugherty Business Solutions
2. Agenda SOLID Principles Coupling Refactoring Dependencies to Abstractions Inversion of Control Dependency Injection (DI) Constructor Injection Property / setter injection Method injection Ambient Context Automated Testing Object Composition / Lifetime Management DI Frameworks 2 3. SOLID S Single responsibility A class should have only a single responsibility O Open / closed principle Classes should be open for extension, but closed for modification L Liskov substitution principle Objects of a program should be replaceable with instances of their subtypes I Interface segregation principle Many client-specific interfaces are better than one general-purpose interface D Dependency inversion principle One should depend on abstractions and not concretions Not the same as Dependency Injection but related 3 The 5 commandments of OO design 4. ObjectA InterfaceB InterfaceC Method1() Method2() ObjectB ObjectC Method1() Method2() Loose Coupling ObjectA ObjectB ObjectC Method1() Method2() Tight Coupling Tight vs. Loose Coupling 4 Coupling Degree to which one component (i.e. dependency) has knowledge of another Tight Coupling A class has a direct reference to a concrete class. Loose Coupling A class has a reference to an abstraction which can be implemented by one or more classes. 5. ObjectA InterfaceB InterfaceC Method1() Method2() ObjectD ObjectE Method1() Method2() Loose Coupling ObjectA ObjectD ObjectE Method1() Method2() Tight Coupling Tight vs. Loose Coupling 5 Benefits of Loose Coupling Testability easier to test objects in isolation Reuse dependencies can be swapped without modifying target Open / Closed Principle - change behavior without modifying target Parallel development developers can work in parallel more easily 6. Tight Coupling Example 6 Violating Single Responsibility 7. Tight Coupling Example 7 How do we test WidgetDataProvider in isolation from its dependencies? How can we reuse or change WidgetDataProvider? 8. Refactoring Dependencies to Abstractions Interfaces Every declared method must be implemented by concrete class Abstract classes Only methods declared abstract must be implemented by concrete class Can provide some default implementation for methods not declared abstract 8 9. Refactoring Dependencies to Abstractions Extract interfaces from classes 9 Before After 10. Refactoring Dependencies to Abstractions Extract interfaces from classes Replace static classes / methods with non-static 10 Before After 11. Refactoring Dependencies to Abstractions Extract interfaces from classes Replace static classes / methods with non-static Extract non-deterministic dependencies Timers, Threading, DateTime dependent 11 Before After 12. Refactoring Dependencies to Abstractions Extract interfaces from classes Replace static classes / methods with non-static Extract non-deterministic dependencies Timers, Threading, DateTime dependent Replace concretions with abstractions 12 Before After 13. Abstraction Example 13 14. Inversion of Control (IoC) Traditional programming Dependencies are instantiated by a class that need them Inversion of Control (IoC) Dependencies are instantiated by a 3rd party and supplied to a class as needed 14 DependencyA DependencyB ChildClass IDependencyA IDependencyB ChildClass creates/consumes creates/consumes ParentClass creates/consumes ParentClass createsconsumes Traditional Inversion of Control consumesconsumes RootContext consumes SomeClass creates SomeClass creates SomeClass creates SomeClass creates RootContext creates/consumes 15. Inversion of Control (IoC) Dependency Injection Constructor Injection Property / Setter Injection Method Injection Ambient Context Factory pattern Dependencies created by factory class Factories can be injected via DI Service locator Class uses Service Locator to pull dependencies as needed Anti-pattern Hides a class dependencies Dependencies magically appear Great way to introduce runtime exceptions Caution Avoid using DI frameworks as Service Locator 15 Implementations 16. Dependency Injection 16 Constructor Injection Use readonly fields as backing store Inject dependencies via constructor Guard against null arguments Save dependencies to field When to use When a dependency is required Important considerations Use single constructor Keep constructors lightweight Minimize number of dependencies (1-3) 17. Dependency Injection 17 Property / Setter Injection Use public get/set to inject dependencies. Guard against null references (if necessary) When to use When a dependency is optional or changeable at runtime When default constructor is required (ASP.NET Pages/Controls) 18. Dependency Injection 18 Method Injection Dependencies passed as parameters on every call Guard against null arguments When to use When a method requires different dependency for each call 19. Dependency Injection 19 Ambient Context Set a default. If no default then use NullObject pattern Static get/set allows access to current logger Guard against null values Implement concrete logger Extract static methods to an interface When to use Cross cutting concerns (i.e. Logging, Security, etc.) Avoid polluting constructors with global dependencies Important considerations Thread safety Use sparingly 20. Automated Testing Unit Testing Test a class in isolation from dependencies Use mock objects in place of dependencies Roll your own Framework (i.e. Moq) Unit tests should never interact with a database Should be extremely fast Integration Testing Test a class along with its dependencies More complex than unit tests May include database calls which can be slow and brittle 20 21. TestInitialize 21 Create fields for our mocks and target for testing Create mocks and inject as needed Create mocks and inject into target constructor 22. TestMethod 22 GetWidgets() successful path Configure our mocks to return test data. Use Verifiable() to ensure that these specific methods were called. Execute the method were testing Verify the results are as expected 23. TestMethod 23 GetWidgets() exception handling Configure data feed to throw an exception Ensure exception is logged Verify the exception is thrown 24. Object Composition / Lifetime Management Object Composition How and where do we instantiate and inject dependencies? Object Lifetime Management How do we manage the lifetime of dependencies? How do we manage sharing dependencies? 24 Object creation Use the data provider Objects go out of scope and are garbage collected. 25. Object Composition Single place in application where object graph is created Nearest the application entry point Examples Console App = Main method Windows Services = Main method ASP.NET Web Forms = global.asax ASP.NET MVC = IControllerFactory WCF = ServiceHostFactory 25 Composition Root WidgetDataProvider SqlWidgetDataFeed WidgetDataReader Simple Object Graph Composition Root WidgetDataProvider SqlWidgetDataFeed WidgetDataReader More Realistic Object Graph Composition Root 26. Dependency Injection Frameworks How they make life easier Automatically detect and resolve dependencies (Autowiring) Manage object lifetime and sharing between objects (Lifetime Management) Allow disposing of all registered dependencies Lifecycle Register Perform early in application (application composition root) Perform all registrations at the same time Resolve Typically only resolve at the composition root Resolving elsewhere = Service Locator anti-pattern Dispose Dispose of DI container to ensure registered objects are disposed Examples Unity (Microsoft), Ninject, Castle Windsor, Autofac, StructureMap, 26 27. Unity Example Create DI container Register dependencies Resolve root component DI container and all components disposed 28. Unity 28 Registration Code Simplest but requires recompiling when changes made 29. Unity 29 Registration Code Simplest but requires recompiling when changes made XML More difficult (no editor) but no recompiling when changes made 30. Unity 30 Registration Code Simplest but requires recompiling when changes made XML More difficult (no editor) but no recompiling when changes made Convention Good for large applications 31. Unity Transient (default) New instance created for each call to Resolve Container Controlled (i.e. singleton) Shared instance when Resolve or dependency injected Externally Controlled Similar to Container Controlled (i.e. singleton) Weak reference kept so container does not handle disposing Per Thread One instance created per thread 31 Lifetime Managers 32. Unity 32 Resolving 33. Dependency Injection Frameworks Unity (3.0) Ninject Castle Windsor Autofac StructureMap License MS-PL Apache 2 Apache 2 MIT Apache 2 Code Configuration Yes Yes Yes Yes Yes XML Configuration Yes Yes Yes Yes Yes Auto Configuration Yes Yes Yes Yes Yes Auto Wiring Yes Yes Yes Yes Yes Lifetime Managers Yes Yes Yes Yes Yes Interception Yes Yes Yes Yes Yes Constructor Injection Yes Yes Yes Yes Yes Property Injection Yes Yes Yes Yes Yes 33 Feature Comparison Same basic features Each has advanced features that set them apart Be aware of performance Research a few before choosing 34. References Dependency Injection in .NET (Mark Seemann) http://techbus.safaribooksonline.com/book/programming/csharp/9781935182504 Adaptive Code via C# (Gary McLean Hall) http://techbus.safaribooksonline.com/9780133979749/ Intro to Inversion of Control (IoC) http://msdn.microsoft.com/en-us/library/ff921087.aspx Service Locator is an Anti-pattern (Mark Seemann) http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/ Developers Guide to Dependency Injection Using Unity http://msdn.microsoft.com/en-us/library/dn223671(v=pandp.