Dependency Injection

42
DEPENDENCY INJECTION PART 1 Alastair Smith (after Mark Seemann)

Transcript of Dependency Injection

Page 1: Dependency Injection

DEPENDENCY INJECTIONPART 1

Alastair Smith (after Mark Seemann)

Page 2: Dependency Injection

Agenda

Overview Concepts The Scope of Dependency Injection Patterns and Anti-Patterns

Page 3: Dependency Injection

What is Dependency Injection?

What is Dependency Injection Not?

What Does Dependency Injection Buy You?

Overview

Page 4: Dependency Injection

What is Dependency Injection? A technique A collection of patterns for loosely-

coupled code Favour composition over inheritance Program to the interface not the

implementation A form of Inversion of Control

Page 5: Dependency Injection

What is Dependency Injection Not? Dependency Inversion (the D in

SOLID) You must first invert your dependencies

to properly apply dependency injection

Data Access Layer

Business Logic Layer

Presentation Layer

Page 6: Dependency Injection

What Does DI Buy You?

Testable and maintainable code Encourages SOLID code

Late binding Swapping services out for other

implementations Easy extensibility

Code can be extended in ways not originally envisaged

Page 7: Dependency Injection

The Purpose of DI

What to Inject (and What Not to Inject)

Concepts

Page 8: Dependency Injection

Tight Coupling

Wall

Page 9: Dependency Injection

How do we decouple?

Wall

Page 10: Dependency Injection

How do we get new functionality?

Wall

UPS

Page 11: Dependency Injection

How do we do multiple things?

Wall

UPS

Page 12: Dependency Injection

How do we use an incompatible device?

Wall

UPS

Page 13: Dependency Injection

Design Patterns will only get you so far How you assemble your bricks

matters

Page 14: Dependency Injection

What to Inject

VOLATILE DEPENDENCIESlibraries that: introduce the need to configure an

external environment are still in development aren’t installed on all machines in the

development organisation E.g.: EntityBroker, Phoenix,

SpreadsheetGear Inject across SEAMS

Page 15: Dependency Injection

What Not to Inject

STABLE DEPENDENCIESlibraries or frameworks that: won’t introduce breaking changes with

new versions you never expect to have to replace

E.g.: the BCL

Page 16: Dependency Injection

Object Composition

Lifetime Management

Interception

The Scope of Dependency Injection

Page 17: Dependency Injection

Object Composition

Building object graphs into functional units Creating objects Creating relationships between objects

No more new Foo() Single Responsibility Principle Regain control through a DI container

Provides late-binding, extensibility and parallel development benefits

Page 18: Dependency Injection

Lifetime Management

Must invert control of an object’s lifetime management as well as the dependency itself

Different lifetime options Singleton Per-request Per-thread (and others)

Page 19: Dependency Injection

A Word on IDisposable

Complicated by use of Dependency Injection

Do not mark your abstractions as IDisposable

Let the DI Container handle disposable implementations

Hide Ephemeral Disposables behind a SEAM Use an injected Abstract Factory to

create them Keep their using blocks short

Page 20: Dependency Injection

Interception

Applying functionality on the fly Used to add Cross-Cutting Concerns:

Logging Auditing Performance Access control Security ...

Page 21: Dependency Injection

Aspect-Oriented Programming Cross-Cutting Concerns applied via

attributes decorating a method [PrincipalPermission] [HandleError]

Requires either: Post-compilation step (e.g., PostSharp),

or A custom host (e.g., WCF, ASP.NET MVC,

NUnit)

Page 22: Dependency Injection

AOP Disadvantages

Attributes are compiled with the code they adorn Can’t easily change behaviour

Limited options for applying attributes

Attributes must have a simple constructor Makes lifetime management trickier

Page 23: Dependency Injection

Dynamic Interception

Can be achieved with liberal use of Decorators Violates DRY Lots of boilerplate code

Container-level feature Castle Windsor, Spring.NET, Unity and

Ninject all support it Neat way to achieve DRY and SOLID

code

Page 24: Dependency Injection

Constructor Injection

Property Injection

Method Injection

Ambient Context

Patterns

Page 25: Dependency Injection

Terminology

COMPOSITION ROOT Where the application is assembled

DEPENDENCY A Volatile Dependency from Part 1

DEFAULT value E.g. a no-op, such as a Null Object Not your default implementation!

Page 26: Dependency Injection

Constructor Injection

This should be your default choice for DI

Guarantees that a necessary DEPENDENCY is always available to the class

Advantages Disadvantages

Injection guaranteed Some frameworks make it difficult

Easy to implement

Page 27: Dependency Injection

Property Injection

Use when a DEPENDENCY is optional

There should be a good LOCAL DEFAULT

Advantages Disadvantages

Easy to understand Limited applicability

Not entirely simple to implement robustly

Page 28: Dependency Injection

Method Injection

Use when a DEPENDENCY varies per call of a method

Usually the DEPENDENCY represents some context for the method call

Limited applicability

Advantages Disadvantages

Allows the caller to provide operation-specific context

Limited applicability

Page 29: Dependency Injection

Ambient Context

Use to inject static DEPENDENCIES Only use when querying the

dependency A proper LOCAL DEFAULT exists It must be guaranteed available

Advantages Disadvantages

Doesn’t pollute APIs Implicit

Is always available Hard to implement correctly

May not work well in some runtimes

Page 30: Dependency Injection

Control Freak

Bastard Injection

Service Locator

Constrained Construction

Anti-Patterns

Page 31: Dependency Injection

Control Freak

DEPENDENCIES are controlled directly E.g., creating an instance of Foo for a

field of type IFoo. Usually occurs within a Factory Root these out of your codebase! Refactor to Constructor Injection

Page 32: Dependency Injection

Bastard Injection

Foreign DEFAULTS are used as default values for DEPENDENCIES E.g., AccountController in ASP.NET

MVC Refactor towards Constructor

Injection Refactor towards Property Injection

But only if there’s a LOCAL DEFAULT

Page 33: Dependency Injection

Service Locator

Calling into your IoC container outside of the COMPOSITION ROOT

Can tightly-couple your application to your IoC container!

Acts as a replacement for new Foo() Refactor towards Constructor

Injection

Page 34: Dependency Injection

Constrained Construction

Constructors are assumed to have a particular signature E.g., WebForms requires Pages to have a

default constructor No easy refactoring to DI

Some possibilities via Abstract Factory

Page 35: Dependency Injection

Any questions?

End of Part One

Page 36: Dependency Injection

DEPENDENCY INJECTIONPART 2

Alastair Smith (after Mark Seemann)

Page 37: Dependency Injection

ASP.NET MVC

WPF

WCF

ASP.NET

Manually Composing Applications

Page 38: Dependency Injection

ASP.NET MVC

COMPOSITION ROOT: global.asax + IControllerFactory Can also use WebActivator package from

NuGet Ignore IDependencyResolver!

Intended to be a Service Locator Removes ability to manage object

lifetime IControllerFactory is the

appropriate extensibility point Use Constructor Injection on your

Controllers

Page 39: Dependency Injection

WPF with MVVM

COMPOSITION ROOT: Application.OnStartup()

Use Constructor Injection on your MainWindowViewModel

Create an IWindow interface and inject this Implemented by a MainWindowAdapter for each

Window Create a MainWindowViewModelFactory

Needed because there is a circular dependency between the View and the ViewModel

Page 40: Dependency Injection

WCF

COMPOSITION ROOT: triplet of ServiceHostFactory ServiceHost IInstanceProvider

Page 41: Dependency Injection

ASP.NET

Suffers from Constrained Construction

COMPOSITION ROOT: each Page class Single Responsibility Principle

Model-View-Presenter (MVP) Keep Presenters fully independent of System.Web

Page 42: Dependency Injection

Any questions?

End of Part Two