Dependency Injection
Without Veils!
Agenda
• Basic Concepts
• DI under the Microscope
• DI from the Telescope
• Strategic Refactoring
• Q&A
• References
Dependency
Injection
Without Veils!
Basic Concepts
Dependencies
Dependency is a relationship between components or classes that can be
thought of as a "uses" relationship:
Class A uses Class B
or
Class B is a dependency of ClassA
Inversion of Control
Principle that promotes components that relinquish control of aspects
of the code execution to external modules or frameworks, to obtain
weak coupling. The principle can be achieved in different ways, such as
Event Driven Development, Template Method Pattern, Dependency
Injection, Asynchronous Calls, etc.
Example: The Strategy Pattern
List<T>.Sort Method (IComparer<T>)
The sort method of a List was designed to relinquish the control over
the comparison strategy to the client.
The sort method only controls the use of the comparison as a contract
operation.
The client has control over the implementation,
creation and lifetime management of IComparer dependency.
Dependency Injection
Dependency injection is a software design pattern that implements
inversion of control for resolving dependencies. A dependency is an
object that can be used (a service). An injection is the passing of a
dependency to a dependent object (a client) that would use it.
Wikipedia
Dependency Injection (DI) is a set of related patterns and principles.
It’s a way to think about and design code more than it’s a specific
technology. The ultimate purpose of using DI is to create maintainable
software within the object-oriented paradigm.
Dependency Injection in .NET,
Mark Seemann
Benefits
1. Low coupling - Easy to refactor and reuse classes
2. Plug-In architecture - Easy to replace or extend functionality
3. Late Binding - Implementation can be swapped at runtime, typically
based on configuration
4. Transparency – Explicit dependencies makes it clearer what each
component does
5. Testability – Easy to isolate dependencies and create mocks
6. Work in Parallel – contracts enable simultaneous development of
interacting components (no need to wait for dependencies to be
finished)
Under the Microscope
The DI Transformation
The Over-Controlling Messenger
Certain users want to be notified when
changes occur in any order status.
User can subscribe on the order events
that they want to receive, and the
application will sent notifications to all
interested subscribers once the event
happens.
The events available for subscription are:
The DI Transformation
Adding Transparency: explicit dependencies as parameters
The DI Transformation
Abstract Dependencies (Dependency Inversion Principle – SOLID)
The DI Transformation
Apply the Law of Demeter
The DI Transformation
Apply the Single Responsibility Principle (From SOLID)
The DI Transformation
Design by Contract
Where to inject
Constructor Injection (Best)
Used when:
• Dependencies are known at creation time
• Dependencies do not change during the object lifetime
Method Injection
Used when:
• It is preferred to reuse the same instance to reduce the # of objects
• Dependencies are used only in methods where they are injected
Property/Field Injection (Worst)
Used when:
• Dependencies are optional
Signs that you are doing it wrong…
• Too many parameters!
• Passing through parameters
• Service Locators
• Using directly stateful system dependencies
(sessions, config. Managers, etc.)
Data is not Behavior!
• Dependency on data is weak and always better
than dependency on behavior
• It is ok to create data classes (entities, data
bags, value types, structs, etc.) with the new
statement outside the injector
• Usually there is no need to abstract data
classes
From The Telescope
Building the Car App
CAR
ENGINE
TRANSMISSION
SYSTEM
ELECTIC SYSTEM AUTOBODY
TRANSMISSION
BOX
DRIVE SHAFT DIFFERENTIAL
GEAR SHIFT SHIFT ROD SHIFT FORK …
BOLT #325 BOLT #25 GEAR #890 …
START
TIME
RUNTIME
Building the Car App with DI
TRANSMISSION
BOX
DRIVE SHAFT DIFFERENTIAL
GEAR SHIFT SHIFT ROD SHIFT FORK
CAR
ENGINE
TRANSMISSION
SYSTEM
ELECTIC SYSTEM AUTOBODY
…
BOLT #325 SCREW #25 GEAR #890 …
TIME
START
INIT
I
N
J
E
C
T
O
R
Facts About The Injector
• The Injector is a factory (GoF)
• The injector has the responsibility of creating all instances in the
application and manage their lifetime.
• The Injector has helper methods containing only creational logic to
instantiate specific components. These methods are usually static.
• The helper methods can be entirely coded manually or they can rely
on frameworks called IoC Containers that can automatically resolve
dependencies based on configuration.
• The Injector methods can only be called at the top level of the code
(main, /startup/bootstrap routines) before the application starts.
• Logically we only need one injector per application, but for
maintainability purposes in large applications we may have multiple)
Injector Example
DIY
Unity
Providers
A providers is small, injectable factory class with a single method to
create a specific instance that cannot be created by the Injector during
the application startup.
Unlike Injectors, providers are intended to be injected and called at
runtime.
Example cases for using providers:
• Many instances of a class are needed
• An instance can only be created after an event (e.g. user input) has
been received
• Lazy instantiation is important (e.g. time sensitive)
The Time Provider Example
Handling Cross Cutting Concerns
Cross cutting concern components (e.g. logger, error handlers,
etc.) can pollute all constructors if used everywhere.
There are two common ways to deal with this border line
cases in DI:
• Ambient Context Pattern (DIY)
Components are referenced statically, but the static
reference is valid within a defined context and can be
changed
• Dynamic Interception (IoC Container / AOP framework)
Dynamically creates object proxies (decorators) that can
add cross cutting behavior before and/or after each method
call
Strategic Refactoring
How To: From BBoM to DI in7 Moves
1. Identify a logical area of the legacy software where bugs are reported the
most or where maintenance is painful.
2. Create integration tests for that area to ensure correct behavior
3. Devise a plan to isolate that area into a separate service through
interface/facades. Consider code duplication if there is no other way to
break out of the mess.
4. Create an injector factory and gradually apply DI (bottom up is usually
better). In the transition period, it is ok to invoke the injector in the code.
5. Write unit tests shortly before or after a component is refactored.
6. Frequently compare integration test results with the legacy code to avoid
introducing new bugs
7. Rinse and repeat
References
1. Designing Reusable Classes
http://webcache.googleusercontent.com/search?q=cache:http://www.laputan.org/drc.html
2. Inversion of Control
http://martinfowler.com/bliki/InversionOfControl.html
3. The Dependency Inversion Principle
https://drive.google.com/file/d/0BwhCYaYDn8EgMjdlMWIzNGUtZTQ0NC00ZjQ5LTkwYzQtZj
RhMDRlNTQ3ZGMz/view
4. Inversion of Control Containers and the Dependency Injection pattern
http://martinfowler.com/articles/injection.html
5. The Clean Code Talks - Don't Look For Things!
https://www.youtube.com/watch?v=RlfLCWKxHJ0
6. DIY Dependency Injection
http://blacksheep.parry.org/wp-content/uploads/2010/03/DIY-DI.pdf
7. Dependency Injection in .NET
https://www.manning.com/books/dependency-injection-in-dot-net
giovanni.scerra@afsi.com
My Contact Info:
https://www.linkedin.com/in/giovanniscerra
Thank You!
Getting Started with Unit Testing
https://www.dropbox.com/s/ivrjgk27u26r9xt/2013-09-20%2012.00%20Getting%20Started%20With%20Testing.wmv
Thoughtful Software Design
https://www.dropbox.com/s/ska44dpu1sbizwl/2015-10-27%2012.01%20Thoughtful%20Software%20Design.mp4
Other Related Presentations at AFS:

Dependency Injection

  • 1.
  • 2.
    Agenda • Basic Concepts •DI under the Microscope • DI from the Telescope • Strategic Refactoring • Q&A • References Dependency Injection Without Veils!
  • 3.
  • 4.
    Dependencies Dependency is arelationship between components or classes that can be thought of as a "uses" relationship: Class A uses Class B or Class B is a dependency of ClassA
  • 5.
    Inversion of Control Principlethat promotes components that relinquish control of aspects of the code execution to external modules or frameworks, to obtain weak coupling. The principle can be achieved in different ways, such as Event Driven Development, Template Method Pattern, Dependency Injection, Asynchronous Calls, etc. Example: The Strategy Pattern List<T>.Sort Method (IComparer<T>) The sort method of a List was designed to relinquish the control over the comparison strategy to the client. The sort method only controls the use of the comparison as a contract operation. The client has control over the implementation, creation and lifetime management of IComparer dependency.
  • 6.
    Dependency Injection Dependency injectionis a software design pattern that implements inversion of control for resolving dependencies. A dependency is an object that can be used (a service). An injection is the passing of a dependency to a dependent object (a client) that would use it. Wikipedia Dependency Injection (DI) is a set of related patterns and principles. It’s a way to think about and design code more than it’s a specific technology. The ultimate purpose of using DI is to create maintainable software within the object-oriented paradigm. Dependency Injection in .NET, Mark Seemann
  • 7.
    Benefits 1. Low coupling- Easy to refactor and reuse classes 2. Plug-In architecture - Easy to replace or extend functionality 3. Late Binding - Implementation can be swapped at runtime, typically based on configuration 4. Transparency – Explicit dependencies makes it clearer what each component does 5. Testability – Easy to isolate dependencies and create mocks 6. Work in Parallel – contracts enable simultaneous development of interacting components (no need to wait for dependencies to be finished)
  • 8.
  • 9.
    The DI Transformation TheOver-Controlling Messenger Certain users want to be notified when changes occur in any order status. User can subscribe on the order events that they want to receive, and the application will sent notifications to all interested subscribers once the event happens. The events available for subscription are:
  • 10.
    The DI Transformation AddingTransparency: explicit dependencies as parameters
  • 11.
    The DI Transformation AbstractDependencies (Dependency Inversion Principle – SOLID)
  • 12.
    The DI Transformation Applythe Law of Demeter
  • 13.
    The DI Transformation Applythe Single Responsibility Principle (From SOLID)
  • 14.
  • 15.
    Where to inject ConstructorInjection (Best) Used when: • Dependencies are known at creation time • Dependencies do not change during the object lifetime Method Injection Used when: • It is preferred to reuse the same instance to reduce the # of objects • Dependencies are used only in methods where they are injected Property/Field Injection (Worst) Used when: • Dependencies are optional
  • 16.
    Signs that youare doing it wrong… • Too many parameters! • Passing through parameters • Service Locators • Using directly stateful system dependencies (sessions, config. Managers, etc.)
  • 17.
    Data is notBehavior! • Dependency on data is weak and always better than dependency on behavior • It is ok to create data classes (entities, data bags, value types, structs, etc.) with the new statement outside the injector • Usually there is no need to abstract data classes
  • 18.
  • 19.
    Building the CarApp CAR ENGINE TRANSMISSION SYSTEM ELECTIC SYSTEM AUTOBODY TRANSMISSION BOX DRIVE SHAFT DIFFERENTIAL GEAR SHIFT SHIFT ROD SHIFT FORK … BOLT #325 BOLT #25 GEAR #890 … START TIME RUNTIME
  • 20.
    Building the CarApp with DI TRANSMISSION BOX DRIVE SHAFT DIFFERENTIAL GEAR SHIFT SHIFT ROD SHIFT FORK CAR ENGINE TRANSMISSION SYSTEM ELECTIC SYSTEM AUTOBODY … BOLT #325 SCREW #25 GEAR #890 … TIME START INIT I N J E C T O R
  • 21.
    Facts About TheInjector • The Injector is a factory (GoF) • The injector has the responsibility of creating all instances in the application and manage their lifetime. • The Injector has helper methods containing only creational logic to instantiate specific components. These methods are usually static. • The helper methods can be entirely coded manually or they can rely on frameworks called IoC Containers that can automatically resolve dependencies based on configuration. • The Injector methods can only be called at the top level of the code (main, /startup/bootstrap routines) before the application starts. • Logically we only need one injector per application, but for maintainability purposes in large applications we may have multiple)
  • 22.
  • 23.
    Providers A providers issmall, injectable factory class with a single method to create a specific instance that cannot be created by the Injector during the application startup. Unlike Injectors, providers are intended to be injected and called at runtime. Example cases for using providers: • Many instances of a class are needed • An instance can only be created after an event (e.g. user input) has been received • Lazy instantiation is important (e.g. time sensitive)
  • 24.
  • 25.
    Handling Cross CuttingConcerns Cross cutting concern components (e.g. logger, error handlers, etc.) can pollute all constructors if used everywhere. There are two common ways to deal with this border line cases in DI: • Ambient Context Pattern (DIY) Components are referenced statically, but the static reference is valid within a defined context and can be changed • Dynamic Interception (IoC Container / AOP framework) Dynamically creates object proxies (decorators) that can add cross cutting behavior before and/or after each method call
  • 26.
  • 27.
    How To: FromBBoM to DI in7 Moves 1. Identify a logical area of the legacy software where bugs are reported the most or where maintenance is painful. 2. Create integration tests for that area to ensure correct behavior 3. Devise a plan to isolate that area into a separate service through interface/facades. Consider code duplication if there is no other way to break out of the mess. 4. Create an injector factory and gradually apply DI (bottom up is usually better). In the transition period, it is ok to invoke the injector in the code. 5. Write unit tests shortly before or after a component is refactored. 6. Frequently compare integration test results with the legacy code to avoid introducing new bugs 7. Rinse and repeat
  • 28.
    References 1. Designing ReusableClasses http://webcache.googleusercontent.com/search?q=cache:http://www.laputan.org/drc.html 2. Inversion of Control http://martinfowler.com/bliki/InversionOfControl.html 3. The Dependency Inversion Principle https://drive.google.com/file/d/0BwhCYaYDn8EgMjdlMWIzNGUtZTQ0NC00ZjQ5LTkwYzQtZj RhMDRlNTQ3ZGMz/view 4. Inversion of Control Containers and the Dependency Injection pattern http://martinfowler.com/articles/injection.html 5. The Clean Code Talks - Don't Look For Things! https://www.youtube.com/watch?v=RlfLCWKxHJ0 6. DIY Dependency Injection http://blacksheep.parry.org/wp-content/uploads/2010/03/DIY-DI.pdf 7. Dependency Injection in .NET https://www.manning.com/books/dependency-injection-in-dot-net
  • 29.
    giovanni.scerra@afsi.com My Contact Info: https://www.linkedin.com/in/giovanniscerra ThankYou! Getting Started with Unit Testing https://www.dropbox.com/s/ivrjgk27u26r9xt/2013-09-20%2012.00%20Getting%20Started%20With%20Testing.wmv Thoughtful Software Design https://www.dropbox.com/s/ska44dpu1sbizwl/2015-10-27%2012.01%20Thoughtful%20Software%20Design.mp4 Other Related Presentations at AFS: