dependency injection and inversion of control
Download
Skip this Video
Download Presentation
Dependency Injection and Inversion of Control

Loading in 2 Seconds...

play fullscreen
1 / 19

Dependency Injection and Inversion of Control - PowerPoint PPT Presentation


  • 70 Views
  • Uploaded on

Dependency Injection and Inversion of Control. Developing flexible, reusable and testable software Part 1 Nick Hines March 2006. Loosely Coupled Systems. Good OO Systems – organised as web of interacting objects Goal – High cohesion, low coupling. Advantages of low coupling Extensibility

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' Dependency Injection and Inversion of Control' - sydney-payne


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
dependency injection and inversion of control

Dependency Injection and Inversion of Control

Developing flexible, reusable and testable software

Part 1

Nick Hines

March 2006

loosely coupled systems
Loosely Coupled Systems
  • Good OO Systems – organised as web of interacting objects
  • Goal – High cohesion, low coupling
  • Advantages of low coupling
    • Extensibility
    • Testability
    • Reusability
  • Not so easy to achieve!
trade monitor the design
Trade Monitor – The design
  • TradeMonitor is coupled to LimitDao – this is not good!
    • Extensibility – what if not database but distributed cache
    • Testability – where do the limits for test come from?
    • Reusability – logic is fairly generic . . .

public class TradeMonitor

{

private LimitDao limitDao;

public TradeMonitor()

{

limitDao = new LimitDao();

}

public bool TryTrade(string symbol, int amount)

{

int limit = limitDao.GetLimit(symbol);

int exposure = limitDao.GetExposure(symbol);

return (exposure + amount > limit) ? false : true;

}

}

public class LimitDao

{

public int GetExposure(string symbol)

{

// Do something with the database

}

public int GetLimit(string sysmbol)

{

// Do something with the database

}

}

limitDao = new LimitDao();

trade monitor the design refactored 1
Trade Monitor – The Design Refactored (1)
  • Introduce interface/implementation separation
    • Logic does not depend on DAO anymore.
    • Does this really solve the problem?
  • The constructor still has a static dependency on DAO

public interface ILimitRepository

{

int GetExposure(string symbol);

int GetLimit(string symbol);

}

public class TradeMonitor

{

private ILimitRepository limitRepository;

public TradeMonitor()

{

limitRepository = new LimitDao();

}

public bool TryTrade(string symbol, int amount)

{

. . .

}

}

limitRepository = new LimitDao();

trade monitor the design refactored 2
Trade Monitor – The Design Refactored (2)
  • Introduce Factory
  • TradeMonitor decoupled from LimitDao
  • LimitDao still tightly-coupled albeit to Factory

public class LimitFactory

{

public static ILimitRepository GetLimitRepository()

{

return new LimitDao();

}

}

public class TradeMonitor

{

private ILimitRepository limitRepository;

public TradeMonitor()

{

limitRepository = LimitFactory.GetLimitRepository();

}

public bool TryTrade(string symbol, int amount)

{

. . .

}

}

LimitFactory

return new LimitDao();

<<creates>>

TradeMonitor

LimitDao

<<interface>>

LimitRepository

trade monitor the design refactored 3
Trade Monitor – The Design Refactored (3)
  • Introduce ServiceLocator
  • This gives us extensibility, testability, reusability

public class ServiceLocator

{

public static void RegisterService(Type type, object impl)

{. . .}

public static object GetService(Type type)

{. . .}

}

public class TradeMonitor

{

private ILimitRepository limitRepository;

public TradeMonitor()

{

object o =

ServiceLocator.GetService(typeof(ILimitRepository));

limitRepository = o as ILimitRepository;

}

public bool TryTrade(string symbol, int amount)

{

. . .

}

}

servicelocator problems
ServiceLocator - Problems
  • Sequence dependence
  • Cumbersome setup in tests
  • Service depends on infrastructure code, (ServiceLocator)
  • Code needs to handle lookup problems
  • Aren’t these problem minor?

Why settle for something we know has issues?

a different view
A Different View
  • What about adding a setter and let something else worry about creation and resolution?

public class TradeMonitor

{

private ILimitRepository limitRepository;

public TradeMonitor()

{

}

public ILimitRepository Limits

{

set { limitRepository = value;}

}

}

This is SetterDependency Injection

  • The dependencies are injected from the outside
  • Components are passive and are not concerned with locating or creating dependencies
another idea
Another Idea
  • Why not just use the constructor?

public class TradeMonitor

{

private ILimitRepository limitRepository;

public TradeMonitor(ILimitRepository limitRepository)

{

this.limitRepository = limitRepository;

}

}

This is ConstructorDependency Injection

  • No setters for dependent components, (obviously)
  • One-shot initialisation – components are always initialised correctly
  • All dependencies are clearly visible from code
  • It is impossible to create cyclic dependencies
what about inversion of control
What about Inversion of Control?
  • Dependency Injection - one example of IoC design principle.
  • Also known as the Hollywood Principle
    • Don’t call us, we’ll call you!
  • Objects rely on their environment to provide dependencies rather than actively obtaining them.
  • Inversion of Control can make the difference between a library and a framework.
ioc containers
IoC Containers
  • There are still some open questions
    • Who creates the dependencies?
    • What if we need some initialisation code that must be run after dependencies have been set?
    • What happens when we don’t have all the components?
  • IoC Containers solve these issues
    • Have configuration – often external
    • Create objects
    • Ensure all dependencies are satisfied
    • Provide lifecycle support
it gets better
It Gets Better
  • We can use reflection to determine dependencies – no need for config files.
  • Most IoC containers support auto-wiring.
  • Make components known to container.
  • Container examines constructors and determines dependencies.
  • Auto-wiring provides other benefits.
  • Less typing, especially long assembly names.
  • Static type checking by IDE at edit time.
  • More intuitive for developer.
the solution test case
The Solution – Test Case

[TestFixture]

public class TradeMonitorTest

{

[Test]

public void MonitorBlocksTradesWhenLimitExceeded()

{

DynamicMock mockRepository = new DynamicMock(typeof(ILimitRepository));

mockRepository.SetupResult(\'GetLimit\', 1000000, new Type[] { typeof(string) });

mockRepository.SetupResult(\'GetExposure\', 999999, new Type[] { typeof(string) });

TradeMonitor monitor = new TradeMonitor((ILimitRepository)mockRepository.MockInstance);

Assert.IsFalse(monitor.TryTrade(\'MSFT\', 1000), \'Monitor should block trade\');

}

}

public class TradeMonitor

{

private ILimitRepository repository;

public TradeMonitor(ILimitRepository repository){this.repository = repository; }

public bool TryTrade(string symbol, int amount)

{

int limit = repository.GetLimit(symbol);

int exposure = repository.GetExposure(symbol);

return ((amount + exposure) <= limit);

}

}

the solution using the windsor container
The Solution – Using the Windsor Container
  • Code configuration

IWindsorContainer container = new WindsorContainer();

container.AddComponent(\'limitRepository\', typeof(ILimitRepository), typeof(LimitDao));

container.AddComponent(\'tradeMonitor\', typeof(TradeMonitor));

TradeMonitor monitor = (TradeMonitor)container[\'tradeMonitor\'];

monitor.TryTrade(\'MSFT\', 1000);

  • External configuration

IWindsorContainer container = new WindsorContainer(\'config.xml\');

TradeMonitor monitor = (TradeMonitor)container[\'tradeMonitor\'];

monitor.TryTrade(\'MSFT\', 1000);

<configuration>

<components>

<component id=\'limitRepository\' service=\'AAABank.ILimitRepository, AAABank\'

type=\'AAABank.LimitDao, AAABank\' />

<component id=\'tradeMonitor\' type=\'AAABank.TradeMonitor, AAABank\' />

</components>

</configuration>

the solution complex configuration
The Solution – Complex Configuration
  • What if components take parameters?

public class LimitDao

{

public LimitDao(string connectionString) {…}

}

<configuration>

<components>

<component id=\'limitRepository\' service=\'AAABank.ILimitRepository, AAABank\'

type=\'AAABank.LimitDao, AAABank\'>

<connectionString>Data Source=AServer;Initial Catalog=BankDB;User ID=sa</connectionString>

</component>

. . .

public class TradeMonitor

{

public TradeMonitor(string[] monitoredSymbols) {…}

}

<configuration>

<components>

<component id=\'tradeMonitor\' type=\'AAABank.TradeMonitor, AAABank\'>

<monitoredSymbols>

<array>

<elem>MSFT</elem>

<elem>TWUK</elem>

</array>

</monitoredSymbols>

. . .

many other possibilities
Many other possibilities
  • Container creates objects – but what objects?
  • Can return proxy – no need for MarshalByRef inheritance.
  • Object instance caching.
  • Aspect Oriented Programming.
  • Remoting by configuration.
  • Automatic Web Service creation.
  • . . .
summary
Summary
  • Container based DI facilitates: -
    • Testability
    • Extensibility
    • Reusability
  • Makes the difference between framework and library
    • Not just use but extend
  • Essential for complex Domain Driven Design
    • Easier to separate \'infrastructure\' from business logic
ad