2. Agenda
• Basic Concepts
• DI under the Microscope
• DI from the Telescope
• Strategic Refactoring
• Q&A
• References
Dependency
Injection
Without Veils!
4. 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
5. 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.
6. 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
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)
9. 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:
15. 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
16. Signs that you are doing it wrong…
• Too many parameters!
• Passing through parameters
• Service Locators
• Using directly stateful system dependencies
(sessions, config. Managers, etc.)
17. 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
19. 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
20. 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
21. 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)
23. 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)
25. 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
27. 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
28. 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
29. 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: