dependency injection або don’t call me, i’ll call you

103
Dependency Injection with Unity 2.0 Dmytro Mindra RnD Tech Lead Lohika AGILEBASECAMP Lviv, 2011

Upload: dmytro-mindra

Post on 29-Nov-2014

2.795 views

Category:

Documents


3 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Dependency Injection або Don’t call me, I’ll call you

Dependency Injection with Unity 2.0

Dmytro MindraRnD Tech Lead

Lohika

AGILEBASECAMPLviv, 2011

Page 2: Dependency Injection або Don’t call me, I’ll call you

Goal

• Get DI understanding

Page 3: Dependency Injection або Don’t call me, I’ll call you

Plan

• Inversion of Control (IoC)• Dependency Injection pattern (DI)• Dependency inversion principle• Unity 2.0, StructureMap• Guice, Spring• Live ASP.NET MVC Demo

Page 4: Dependency Injection або Don’t call me, I’ll call you

Problem

Page 5: Dependency Injection або Don’t call me, I’ll call you

Problem

•We live in an age where writing software to a given set of requirements is no longer enough.• We have to maintain and change existing

code.• Code quality ( What’s Bad ) R.Martin 1996

- Rigid (hard to modify)- Fragile ( errors occur on almost every change)- Immobile (not reusable)

Page 6: Dependency Injection або Don’t call me, I’ll call you

How?

Our solutions should be:• Modular• Testable• Adaptive to change

Page 7: Dependency Injection або Don’t call me, I’ll call you

Terms

• Service —An object that performs a well-defined function when called upon

• Client —Any consumer of a service; an object that calls upon a service to perform a well-understood function

Page 8: Dependency Injection або Don’t call me, I’ll call you

Terms

• Dependency —A specific service that is required by another object to fulfill its function.

• Dependent —A client object that needs a dependency (or dependencies) in order to perform its function.

Page 9: Dependency Injection або Don’t call me, I’ll call you

OLD SCHOOL (PRE DI STYLE)

Page 10: Dependency Injection або Don’t call me, I’ll call you

Ex1:Composition

Page 11: Dependency Injection або Don’t call me, I’ll call you

Ex1:Composition public class SpellCheckerService{}

public class TextEditor

{ private SpellCheckerService _spellCheckerService; public TextEditor() { _spellCheckerService = new SpellCheckerService(); } } class Program { static void Main(string[] args) { TextEditor textEditor = new TextEditor(); } }

TextEditor

SpellChecker

Page 12: Dependency Injection або Don’t call me, I’ll call you

What’s good

• It’s simple

Page 13: Dependency Injection або Don’t call me, I’ll call you

What’s bad

• It’s not testable• It’s hard to maintain/change

Page 14: Dependency Injection або Don’t call me, I’ll call you

Better approach

TextEditor

+ CheckSpelling() : bool

SpellCheckerServ ice

+ CheckSpelling() : string

«interface»ISpellCheckerServ ice

+ CheckSpelling() : string

Dependency Inversion

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.

B. Abstractions should not depend upon details. Details should depend upon abstractions.

Robert C. Martin 1996

Page 15: Dependency Injection або Don’t call me, I’ll call you

Context

Granny

+ Eat() : void

«interface»IAppleProv ider

+ GetApple() : IApple

RedAppleProv ider

+ GetApple() : IApple

GoldenAppleProv ider

+ GetApple() : IApple

«interface»IPillProv ider

ConcretePillProv ider

Context

Page 16: Dependency Injection або Don’t call me, I’ll call you

Ex2:Loose Coupling public class TextEditor { private readonly ISpellCheckerService

_spellCheckerService;

public TextEditor(ISpellCheckerService spellCheckerService)

{ _spellCheckerService = spellCheckerService; }

public string CheckSpelling() { return _spellCheckerService.CheckSpelling(); }

}

Page 17: Dependency Injection або Don’t call me, I’ll call you

Ex2: Unit Testing

// Mock ISpellCheckerService mock = new SpellCheckerServiceMock();

// InstantiateTextEditor textEditor = new TextEditor(mock);

// CheckAssert.AreEqual(“Mock”, textEditor.CheckSpelling());

Page 18: Dependency Injection або Don’t call me, I’ll call you

What changed

• TextEditor lost its “Sovereignty” and is not able to resolve dependencies by himself.

Page 19: Dependency Injection або Don’t call me, I’ll call you

What’s good

• Dependencies are obvious.• Dependency resolution is not encapsulated.• Unit Testing is applicable• Architecture is much better

Page 20: Dependency Injection або Don’t call me, I’ll call you

What’s bad

• We are resolving dependencies manually while creating instances of TextEditor.

Page 21: Dependency Injection або Don’t call me, I’ll call you

Wiring By Hand

Page 22: Dependency Injection або Don’t call me, I’ll call you
Page 23: Dependency Injection або Don’t call me, I’ll call you
Page 24: Dependency Injection або Don’t call me, I’ll call you
Page 25: Dependency Injection або Don’t call me, I’ll call you
Page 26: Dependency Injection або Don’t call me, I’ll call you
Page 27: Dependency Injection або Don’t call me, I’ll call you
Page 28: Dependency Injection або Don’t call me, I’ll call you

Using Factory

Page 29: Dependency Injection або Don’t call me, I’ll call you

FactoryTextEditorFactory

+ GetEnglishTextEditor() : TextEditor+ GetFrenchTextEditor() : TextEditor

TextEditor

FrenchSpellCheckerServ ice

«interface»ISpellCheckerServ ice

EnglishSpellCheckerServ ice

Page 30: Dependency Injection або Don’t call me, I’ll call you

What changed

• Any required combination of Text Editor and Spell Checking Service is created by object factory.

Page 31: Dependency Injection або Don’t call me, I’ll call you

What’s good

• It’s testable• No manual wiring

Page 32: Dependency Injection або Don’t call me, I’ll call you

What’s bad

• You have to maintain factory or service locator• The more combinations the more methods we

have in factory.• Your code knows about the specific factory or

factory interface. This means that infrastructure logic is mixed with business logic.

• Factory may have states.

Page 33: Dependency Injection або Don’t call me, I’ll call you

Service Locator

Unfortunately, being a kind of Factory, Service Locators suffer from the same problemsof testability and shared state.

Page 34: Dependency Injection або Don’t call me, I’ll call you

What are we looking for?

Page 35: Dependency Injection або Don’t call me, I’ll call you

Inversion of Control

• Hollywood Principle:

Don’t call me, I’ll call you

Page 36: Dependency Injection або Don’t call me, I’ll call you

Inversion of Control

• IoC – is a common characteristic of frameworks.

• According to Martin Fowler the etymology of the phrase dates back to 1988.

Page 37: Dependency Injection або Don’t call me, I’ll call you

Dependency Injection

• DI is a kind of IoC• Inversion of Control is too generic a term• DI pattern – describes the approach used to

lookup a dependency. • Dependency resolution is moved to

Framework.

Page 38: Dependency Injection або Don’t call me, I’ll call you

SpellCheckerServ ice

+ CheckSpelling() : bool

TextEditor

+ CheckSpelling() : bool

«interface»ISpellCheckerServ ice

We have alreadyprepared basis.

Loosely coupled structure

Page 39: Dependency Injection або Don’t call me, I’ll call you

It’s time to introducenew role

Injector (sometimes referred to as a provider or container)

Page 40: Dependency Injection або Don’t call me, I’ll call you

Depedndecy Injection

DI in general consists of • a dependent consumers• their service dependencies• and an injector

Page 41: Dependency Injection або Don’t call me, I’ll call you

Unity

Page 42: Dependency Injection або Don’t call me, I’ll call you

Ex3: Unity

using Microsoft.Practices.Unity;

UnityContainer container = new UnityContainer();

container.RegisterType<ISpellCheckerService, SpellCheckingService>();

TextEditor textEditor = container.Resolve<TextEditor>();

Page 43: Dependency Injection або Don’t call me, I’ll call you

What changed

• Unity container now resolves dependencies

Page 44: Dependency Injection або Don’t call me, I’ll call you

What’s good

• Automated dependency resolution• Business logic and infrastructure are

decoupled.

Page 45: Dependency Injection або Don’t call me, I’ll call you

Injection Types

• Interface injection (by Martin Fowler)• Constructor Injection (by Martin Fowler)• Setter injection (by Martin Fowler)• Method call injection (Unity)• Method decorator injection (Guice)

Page 46: Dependency Injection або Don’t call me, I’ll call you

Unity methods

• RegisterType• RegisterInstance• Resolve

• BuildUp

Page 47: Dependency Injection або Don’t call me, I’ll call you

Ex4: Unity Configuration <configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/> </configSections>

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> <alias alias="ISpellCheckerService" type="Unity.Config.ISpellCheckerService, Unity.Config" /> <alias alias="SpellCheckingService" type="Unity.Config.SpellCheckingService, Unity.Config" /> <namespace name="Unity.Config" /> <assembly name="Unity.Config" />

<container> <register type="ISpellCheckerService" mapTo="SpellCheckingService" /> </container> </unity>

Page 48: Dependency Injection або Don’t call me, I’ll call you

Ex4: Unity Configuration

using Microsoft.Practices.Unity;using Microsoft.Practices.Unity.Configuration;

UnityContainer container = new UnityContainer();container.LoadConfiguration();TextEditor textEditor = container.Resolve<TextEditor>();

Page 49: Dependency Injection або Don’t call me, I’ll call you

Dependency tree

Page 50: Dependency Injection або Don’t call me, I’ll call you

Ex5: Dependency treepublic interface IAdditionalDependency{}public class AdditionalDependency : IAdditionalDependency{}

public class SpellCheckingService: ISpellCheckerService {

public SpellCheckingService( IAdditionalDependency dependency){} }

Page 51: Dependency Injection або Don’t call me, I’ll call you

Ex5: Dependency Tree

UnityContainer container = new UnityContainer();container.RegisterType<ISpellCheckerService,

SpellCheckingService>();container.RegisterType<IAdditionalDependency,

AdditionalDependency>();TextEditor textEditor = container.Resolve<TextEditor>();

Page 52: Dependency Injection або Don’t call me, I’ll call you

Ex5: Dependency tree

SpellCheckerServ ice

+ CheckSpelling() : bool

TextEditor

+ CheckSpelling() : bool

«interface»ISpellCheckerServ ice

AdditionalDependency

+ CheckSpelling() : bool

«interface»IAditionalDependenct

Page 53: Dependency Injection або Don’t call me, I’ll call you

Ex6: Defining Injection Constructor

public class TextEditor { private readonly ISpellCheckerService _spellCheckerService;

[InjectionConstructor] public TextEditor(ISpellCheckerService spellCheckerService) { _spellCheckerService = spellCheckerService; }

public TextEditor(ISpellCheckerService spellCheckerService,string name) { _spellCheckerService = spellCheckerService; } }

Page 54: Dependency Injection або Don’t call me, I’ll call you

Ex7: Property Injection public class TextEditor { public ISpellCheckerService SpellCheckerService {get; set;}

[Dependency] public ISpellCheckerService YetAnotherSpellcheckerService{get;set;} } UnityContainer container = new UnityContainer(); container.RegisterType<TextEditor>(new InjectionProperty("SpellCheckerService")); container.RegisterType<ISpellCheckerService, SpellCheckingService>(); TextEditor textEditor = container.Resolve<TextEditor>();

Page 55: Dependency Injection або Don’t call me, I’ll call you

Ex8: Method call injection public class TextEditor { public ISpellCheckerService SpellcheckerService {get; set;}

[InjectionMethod] public void Initialize (ISpellCheckerService spellcheckerService) { _spellCheckerService = spellcheckerService; } }UnityContainer container = new UnityContainer();//container.RegisterType<TextEditor>(

new InjectionMethod("SpellcheckerService"));container.RegisterType<ISpellCheckerService, SpellCheckingService>();TextEditor textEditor = container.Resolve<TextEditor>();

Page 56: Dependency Injection або Don’t call me, I’ll call you

Lifetime Managers

• TransientLifetimeManagerReturns a new instance of the requested type for each call. (default behavior)

• ContainerControlledLifetimeManagerImplements a singleton behavior for objects. The object is disposed of when you dispose of the container.

Page 57: Dependency Injection або Don’t call me, I’ll call you

Lifetime Managers

• ExternallyControlledLifetimeManagerImplements a singleton behavior but the container doesn't hold a reference to object which will be disposed of when out of scope.

• HierarchicalifetimeManagerImplements a singleton behavior for objects. However, child containers don't share instances with parents.

Page 58: Dependency Injection або Don’t call me, I’ll call you

Lifetime Managers

• PerResolveLifetimeManagerImplements a behavior similar to the transient lifetime manager except that instances are reused across build-ups of the object graph.

• PerThreadLifetimeManagerImplements a singleton behavior for objects but limited to the current thread.

Page 59: Dependency Injection або Don’t call me, I’ll call you

Ex9: Unity Singleton

UnityContainer container = new UnityContainer();container.RegisterType<ISpellCheckerService, SpellCheckingService>(new ContainerControlledLifetimeManager());TextEditor textEditor = container.Resolve<TextEditor>();

Page 60: Dependency Injection або Don’t call me, I’ll call you

Container Hierarchy

Page 61: Dependency Injection або Don’t call me, I’ll call you

Unity Limitations

• When your objects and classes have no dependencies on other objects or classes.

• When your dependencies are very simple and do not require abstraction.

Page 62: Dependency Injection або Don’t call me, I’ll call you

Performance

Page 63: Dependency Injection або Don’t call me, I’ll call you

Performance

Page 64: Dependency Injection або Don’t call me, I’ll call you

Performance

Page 65: Dependency Injection або Don’t call me, I’ll call you

What DI stands for

For• Wiring framework

components

Not for• Wiring small parts

Page 66: Dependency Injection або Don’t call me, I’ll call you

STRUCTURE MAP

Page 67: Dependency Injection або Don’t call me, I’ll call you

Structure Map Example

// BootstrapContainer container = new Container(x => x.For<ISpellCheckingService>(). Use<FrenchSpellCheckingService>());// UseTextEditor textEditor = container.GetInstance<TextEditor>();

Page 68: Dependency Injection або Don’t call me, I’ll call you

Compared to Unity

// BootstrapUnityContainer container = new UnityContainer();container.RegisterType<ISpellCheckingService,

EnglishSpellCheckingService>();

// Using containerTextEditor textEditor = container.Resolve<TextEditor>();

Page 69: Dependency Injection або Don’t call me, I’ll call you

Unity vs StructureMap

Unity• XML Configuration• In Code configuration• Attributes

• Benefits– Easy code initialization– Good documentation

StructureMap• XML Configuration• In Code configuration• Attributes

• Benefits– Http & Session lifetime

managers out of the box.– Convenient XML

configuration.

Page 70: Dependency Injection або Don’t call me, I’ll call you

.NET DI Frameworks

• Unity 2.0• AutoFac 2.4.3• StructureMap 2.6.1• Castle Windsor 2.5.3• Ninject 2.0

Page 71: Dependency Injection або Don’t call me, I’ll call you

SCOPE, CONTEXT, LIFETIME

Page 72: Dependency Injection або Don’t call me, I’ll call you

Singleton scope

• Singleton scoped objects lifetime is bound to injector lifetime.

Page 73: Dependency Injection або Don’t call me, I’ll call you

Difference

• Singleton scoped object vs. singleton anti pattern

Page 74: Dependency Injection або Don’t call me, I’ll call you

No scope

Page 75: Dependency Injection або Don’t call me, I’ll call you

Connection pool

Page 76: Dependency Injection або Don’t call me, I’ll call you

Web request scope

• HTTP protocol is stateless and web request scope is quite natural for web applications

Page 77: Dependency Injection або Don’t call me, I’ll call you

Session scope

• Session is an abstraction that hides HTTP stateless nature. Such scope should be used carefully.

Page 78: Dependency Injection або Don’t call me, I’ll call you

CIRCULAR REFERENCES

Page 79: Dependency Injection або Don’t call me, I’ll call you

Circular References

• Objects depend on each other forming cycle in dependency graph.

Page 80: Dependency Injection або Don’t call me, I’ll call you

General case

• A depends on B• B depends on A

Page 81: Dependency Injection або Don’t call me, I’ll call you

Introducing proxy

Page 82: Dependency Injection або Don’t call me, I’ll call you

Diagram

• Dynamic proxy is constructed

A B

«interface»A

«interface»B

«interface»Proxy A

Page 83: Dependency Injection або Don’t call me, I’ll call you

Sequence

• 1. Instantiate Proxy A• 2. Instantiate B using Proxy A• 3. Instantiate A using B from step 2• 4. Initialize Proxy A with A• Proxy A passes all requests to concrete A

Page 84: Dependency Injection або Don’t call me, I’ll call you

GRANNY AND APPLESREINJECTION

Page 85: Dependency Injection або Don’t call me, I’ll call you

G&A Diagram

• Granny receives concrete apple via injection.• Granny eats apple

Granny

+ Eat() : void

«interface»IApple

RedApple

GoldenApple

Page 86: Dependency Injection або Don’t call me, I’ll call you

G&A Sequence

• Granny needs apples for proper operation• New apples should be injected runtime

Page 87: Dependency Injection або Don’t call me, I’ll call you

G&A Solution

• Instead of single apple we should inject apple “provider”

Granny

+ Eat() : void

«interface»IApple

RedApple

GoldenApple

«interface»IAppleProv ider

+ GetApple() : IApple

RedAppleProv ider

+ GetApple() : IApple

GoldenAppleProv ider

+ GetApple() : IApple

Page 88: Dependency Injection або Don’t call me, I’ll call you

G&A New Sequence

Page 89: Dependency Injection або Don’t call me, I’ll call you

Drawback

• If you want produced instances to be configured by general injection rules then your factories will depend on concrete injection framework.

• Google Guice has special interface to support such behavior but you’ll depend on google Guice.

• No silver bullet.

Page 90: Dependency Injection або Don’t call me, I’ll call you

GUICE AND SPRING

Page 91: Dependency Injection або Don’t call me, I’ll call you

History

• Spring project brought DI to mainstream.• And thank Spring Guice appeared.• Guice introduced new features and stimulated

further Spring development.• Now Guice and Spring are almost equal in DI

field and which one to use depends on developer.

Page 92: Dependency Injection або Don’t call me, I’ll call you

Spring

• Spring holds a huge DI market share. More than 80%.

• Proven enterprise solution• DI is only a small part of its functionality• Supports all major injection approaches• Current version 3

Page 93: Dependency Injection або Don’t call me, I’ll call you

Guice

• New kid on the block• Introduced new features based on Java 5

support. ( e.g. Provider methods to circumvent type erasure)

• First-class error messaging.• Very fast.• Provides only DI• Current version 2 ( Version 3 RC )

Page 94: Dependency Injection або Don’t call me, I’ll call you

Spring or Guice

• In DI Spring and Guice are almost equal.• Guice provides only DI• DI in Spring is only a part of functionality• Google extensively uses Guice• Guice is trendy and developers just want to

give it a try.• So which framework to use heavily depends

on project and concrete developer ( team)

Page 95: Dependency Injection або Don’t call me, I’ll call you

Where to use Guice

• If you are sure that you do not need full Spring functionality and your project is not a huge enterprise level application then you can give it a try.

• Spring is standard de facto in the industry.

Page 96: Dependency Injection або Don’t call me, I’ll call you

Patterns

• Builder• Wrapper• Adapter• Abstract Factory and Factory method

Page 97: Dependency Injection або Don’t call me, I’ll call you

Additional reading

Page 98: Dependency Injection або Don’t call me, I’ll call you

Additional reading

Page 99: Dependency Injection або Don’t call me, I’ll call you

Live Demo

Page 100: Dependency Injection або Don’t call me, I’ll call you

ASP.NET MVC

Page 101: Dependency Injection або Don’t call me, I’ll call you

QUESTIONS ?

Page 102: Dependency Injection або Don’t call me, I’ll call you

THANK YOU !

Page 103: Dependency Injection або Don’t call me, I’ll call you

References

1. Martin Fowler – Dependency Injectionhttp://martinfowler.com/articles/injection.html2. DI Comixhttp://www.bonkersworld.net/2010/08/11/programmers-only-shaving-who/3. Consultants comixhttp://stuffthathappens.com/blog/2007/09/26/comic-tribute-to-crazy-bob/4. R. Martin - Dependency Inversion principlehttp://www.objectmentor.com/resources/articles/dip.pdf