SlideShare ist ein Scribd-Unternehmen logo
1 von 27
Downloaden Sie, um offline zu lesen
Designing for Inversion of Control
        Architecture Camp 2007

                        Alex Henderson
                      DevDefined Limited
About Me
   Senior Developer / Director at DevDefined Limited.
   Used IoC in all major projects since 2005.
   Specialise in product development & consultancy.
   .Net Developer since First Beta of the 1.0 Framework.

   Email: alex@devdefined.com
   Blog: http://blog.bittercoder.com/




                            Please Complete Your Session Evaluation Sheets
What drives us towards using IoC ?
   Difficulty responding to change.

   Tight coupling.
   Difficulty managing dependencies.

   Cant easily switch implementations at runtime.
   Need for Lifestyle management.



                         Please Complete Your Session Evaluation Sheets
So what is IoC

It’s a principle!
   Approach to designing components which are more
    reusable.
     By moving control away from your components
   Better reusability by enforcing isolation.
   Key goal: Loosen the coupling between services.
   IoC Not really a design pattern.
   Dependency Injection (DI) helps achieve this isolation.
   Increases testability of components

                            Please Complete Your Session Evaluation Sheets
Dependency Injection Example
In this example we look a service which can
handle processing a purchase request for a
lottery ticket.


               Checking we can still purchase the ticket for the
                selected draw number (has it already been
                drawn?)
               Collecting payment for the ticket.
               Send a notification message to the person
                buying the ticket with the outcome of their
                purchase.

                            Please Complete Your Session Evaluation Sheets
First take on the Ticket Processor
public partial class LottoTicketProcessor : ITicketProcessor
{
    public void Process(Ticket ticket)
    {
        if (DrawManager.Instance
            .CanStillPurchaseFor(ticket.DrawNumber))
        {
            if (CollectionAgency.Instance
                .Collect(ticket.Customer, ticket.Cost))
            {
                ticket.TicketStatus = TicketStatus.Purchased;
                SendTicketDetailsNotification(ticket);
                return;
            }
        }

        SendPurchaseFailedNotification();
    }
}


                             Please Complete Your Session Evaluation Sheets
Something smells..
There are problems with the implementation

   Heavy use of singletons
   Difficult, perhaps even impossible to test *
   Tightly coupled (where’s the abstractions?)
   The ticket processor knows too much!
   Violates single responsibility principle
   Hard to reuse the ticket processor – not flexible.


* Well, maybe not impossible... There’s always the big hammer known as TypeMock.Net
(http://www.typemock.com/ ) – but being able to test it doesn’t stop your code smelling!

                                              Please Complete Your Session Evaluation Sheets
I heard factories were good...
public partial class LottoTicketProcessor2 : ITicketProcessor
{
    public void Process(Ticket ticket)
    {                                                       We’ve just swapped
                                                          knowledge of a singleton,
        if (DrawManagerFactory.Create().
                                                             for knowledge of a
            CanStillPurchaseFor(ticket.DrawNumber))
                                                                  factory...
        {
            if (CollectionAgencyFactory.Create()
                .Collect(ticket.Customer, ticket.Cost))
            {
                ticket.TicketStatus = TicketStatus.Purchased;
                NotificationSenderFactory.Create()
                  .SendTicketDetailsNotification(ticket);      But at least we can
                return;                                       change the concrete
            }                                                implementation used.
        }
        NotificationSenderFactory.Create().SendPurchaseFailedNotification();
    }
}

                                 Please Complete Your Session Evaluation Sheets
Service Locators

   Provides a way to manage dependencies.
   Concept already used in the .Net Framework.
   As the name suggest, a service locator is used... to locate
    services – could be seen as a “registry”.




                               Please Complete Your Session Evaluation Sheets
Example with Service Locator
public partial class LottoTicketProcessor3 : ITicketProcessor {
   private ServiceLocator _locator;
                                                                    We can now
   public LottoTicketProcessor3(ServiceLocator locator) {
                                                                   test the ticket
       _locator = locator;
                                                                    processor by
   }
                                                                    mocking the
   public void Process(Ticket ticket) {
                                                                  service locator
       if (_locator.DrawManager.CanStillPurchaseFor(ticket.DrawNumber))
       {
           if (_locator.CollectionAgency.Collect(ticket.Customer, ticket.Cost))
           {
               ticket.TicketStatus = TicketStatus.Purchased;
               _locator.NotificationSender
                     .SendTicketDetailsNotification(ticket);
               return;
           }
       }
       _locator.NotifcationSender.SendPurchaseFailedNotification(ticket);
   }

                                   Please Complete Your Session Evaluation Sheets
Service Locators have issues

   All classes will depend on the service locator.
   Dependencies are generally resolved as-needed –
    requires additional coding to support “failing fast” when
    constructed.
   Often requires complicated code to setup as service
    count grows.
   Can impair reusability.

   But some people find it easier to “grok”


                             Please Complete Your Session Evaluation Sheets
Dependency Injection
Range of mechanisms available...

   The constructor
       Normally implies it’s compulsory.
       Should probably remove default constructor.
   A property setter
       Often implying it’s optional, but not always.
       If optional should probably have a default value.
   Other methods
       Interface (not that common)
       Method (even less common)
       Virtual property getter (very rare, needs a proxy to be generated)
       And some even more obscure ideas...

                                    Please Complete Your Session Evaluation Sheets
Back to the example...
Constructor based injection
public partial class LottoTicketProcessor4 : ITicketProcessor
{
    private readonly ICollectionAgency _agency;                 Using read-only
    private readonly IDrawManager _drawManager;                 properties here
    private readonly IEmailSender _sender;                        - assert that
                                                                 these services
    public LottoTicketProcessor4(ICollectionAgency agency,         should not
        IDrawManager drawManager, IEmailSender sender)           change during
    {
                                                                    lifetime..
        _agency = agency;
        _drawManager = drawManager;
        _sender = sender;
    }



                                 Please Complete Your Session Evaluation Sheets
And the implementation...
Simple eh?

public void Process(Ticket ticket)
{
    if (_drawManager.CanStillPurchaseFor(ticket.DrawNumber))
    {
        if (_agency.Collect(ticket.Customer, ticket.Cost))
        {
            ticket.TicketStatus = TicketStatus.Purchased;
            _sender.SendTicketDetailsNotification(ticket);
            return;
        }
    }
    _sender.SendPurchaseFailedNotification(ticket);
}


                           Please Complete Your Session Evaluation Sheets
A taste of testing...
// start recording...
MockRepository repository = new MockRepository();
Ticket ticket = new Ticket(10); // Set Draw Number
IDrawManager drawManager = repository.CreateMock<IDrawManager>();
Expect.Call(drawManager.CanStillPurchaseFor(ticket.DrawNumber))
  .Return(false);                                        Here we’re setting
INotificationSender sender =                           expectations (that this
  repository.CreateMock<INotificationSender>();        method will be called)
sender.SendPurchaseFailedNotification(ticket);
LastCall.Constraints(Is.Same(ticket));
ICollectionAgency agency = repository.CreateMock<ICollectionAgency>();
repository.ReplayAll();

// start replaying...
LottoTicketProcessor4 processor =
  new LottoTicketProcessor4(agency, drawManager, sender);
processor.Process(ticket);
repository.VerifyAll();       Verify the expectations were met... throws if not
                               Please Complete Your Session Evaluation Sheets
Designing for Dependency Injection
   Systems are comprised of small, focused services –
    Services are abstractions (Interfaces).
    Components implement the services – Concrete
    classes.
   A component declares exactly what dependencies
    (services) it relies on.
   A component does not dictate it’s own lifestyle.
     Don’t implement singleton behaviour yourself.
   You can test all facets of your application.


                          Please Complete Your Session Evaluation Sheets
IoC Containers
   Single point of access for all services in app.
   IoC containers can fill many needs, but simple
    containers generally handle:
     Assembling services by resolving and injecting
      dependencies.
     Managing the lifestyle of services.
   Some containers allow you to use configuration files.
   Automatically resolves all the dependencies - auto-
    wiring – constructors called for you via reflection.


                          Please Complete Your Session Evaluation Sheets
Example container
public class SimpleContainer
{                                                                   Singleton lifestyle
    private IDrawManager _drawManager = new DrawManager();      achieved by the container
    private INotificationSender _notificationSender =           holding onto references...
         new SmsNotificationSender("cheapnsms.net.nz");
    private ICollectionAgency _collectionAgency = new MBillWebServiceCollectionAgency();

    public T Resolve<T>()
    {
        if (typeof(T) == typeof(IDrawManager)) return (T)_drawManager;
        if (typeof(T) == typeof(INotificationSender)) return (T)_notificationSender;
        if (typeof(T) == typeof(ICollectionAgency)) return (T)_collectionAgency;
        if (typeof(T) == typeof(ITicketProcessor))
        {                                                 Wire up a transient component
            ITicketProcessor processor =                   every time it’s requested...
                 new LottoTicketProcessor4(_collectionAgency, _drawManager,
    _notificationSender);
            return (T) processor;
        }
        throw new NoMatchingComponentException(“Cant resolve service: {0}", typeof(T));
    }

                                           Please Complete Your Session Evaluation Sheets
Available containers (with .Net impls)

   Castle’s Windsor Container & Micro Kernel - .Net
   ObjectBuilder – .Net (Microsofts Implementation)
       Used in CAB & Enterprise Library

   Pico/Nano Container - Java, .Net, Ruby, PHP
   Seasar2 – Java, PHP, .Net (needs work!)
   Spring.Net – Java, .Net
   StructureMap - .Net

                               Please Complete Your Session Evaluation Sheets
What a container can do for a project
   Save time and repetitive code to wire up dependencies.
   Provides an easy way to inject configuration information.
   Easily move between configurations
       Test / Production
       Different clients – different configurations.
   Transparently proxy components & intercept methods
       Implement cross cutting concerns (logging, security) – AOP.
   Lifestyle management (Singleton, Transient, Per-Request,
    Per-Thread, Pooled etc.)
   Lifecycle management.

                                   Please Complete Your Session Evaluation Sheets
What they don’t tell you
   Debugging container configuration problems can be frustrating
     Often caused by no refactoring support.
   Components configured with the wrong lifestyle can introduce
    difficult to diagnose problems
     may not become apparent during unit tests.
   Obfuscation and container configuration files don’t mix.
   Cross-cutting concerns makes solutions less predictable, use
    AOP only if you understand the impacts.
                            Golden Rule
   IoC should only be used if you know how it helps you.
     Otherwise you will think it's a pointless obstruction.


                              Please Complete Your Session Evaluation Sheets
Resources
   Castle project
       http://www.castleproject.org/
   Ayendes (Oren Eini) presentations & blog
       http://www.ayende.com/
       http://msdn2.microsoft.com/en-us/library/aa973811.aspx
   Object Builder
       http://www.codeplex.com/ObjectBuilder
   Martin Fowler of Dependency Injection
       http://www.martinfowler.com/articles/injection.html
   Stefano Mazzocchi – On Inversion of Control
       http://www.betaversion.org/~stefano/linotype/news/38/

                                 Please Complete Your Session Evaluation Sheets
Evaluations and Contact
   Thanks for listening!
   Don’t forget to fill in your evaluations
   Presentation downloads available from
       My Blog
       Also available from http://www.dot.net.nz within a week of
        this event.

   Email: alex@devdefined.com
   Work: http://www.devdefined.com/
   Blog: http://blog.bittercoder.com/

                                Please Complete Your Session Evaluation Sheets
Decorator Patterns in IoC
                                Selects an
                             implementation
                            based on weight...




                 Please Complete Your Session Evaluation Sheets
Decorator Patterns in IoC
public class ThresholdPackageDeliverer : IOrderDeliverer {
   private readonly decimal thresholdInKgs;
   private readonly IOrderDeliverer smallDeliverer;
   private readonly IOrderDeliverer largeDeliverer;


   public ThresholdPackageDeliverer(IOrderDeliverer smallDeliverer,
    IOrderDeliverer   largeDeliverer, decimal thresholdInKgs) {         Notice both
       this.smallDeliverer = smallDeliverer;                             config and
       this.largeDeliverer = largeDeliverer;                          dependencies in
       this.thresholdInKgs = thresholdInKgs;                           constructor...
   }

   public void OrganiseDelivery(Order orderToDeliver) {
       if (orderToDeliver.TotalWeight < thresholdInKgs) {
           smallDeliverer.OrganiseDelivery(orderToDeliver);
       }
       else {
           largeDeliverer.OrganiseDelivery(orderToDeliver);
       }
   }


                                         Please Complete Your Session Evaluation Sheets
Decorator Patterns in IoC
<component
  id="joesDeliverer"
  service="MyApp.JoesSmallPackageDeliverer, MyAssembly"
  type="MyApp.JoesSmallPackageDeliverer, MyAssembly"/>

<component
  id ="acmeDeliverer"
  service="MyApp.AcmeLargePackageDeliverer, MyAssembly"
  type="MyApp.AcmeLargePackageDeliverer, MyAssembly"/>
                                                                Threshold package
<component
                                                              deliver is wired up the
  id="defaultDeliverer"
  service="MyApp.IOrderDeliverer, MyAssembly"                      joes and acme
  type="MyApp.ThresholdPackageDeliverer, MyAssembly">         deliverer + threshold
  <parameters>                                                      in the config.
    <smallDeliverer>${joesDeliverer}</smallDeliverer>
    <largeDeliverer>${acmeDeliverer}</largeDeliverer>
    <thresholdInKgs>2000</thresholdInKgs>
  </parameters>
</component>



                                    Please Complete Your Session Evaluation Sheets
Decorator Patterns in IoC
<!-- on strike, so just use joes deliverer -->
<component
                                                                   No recompile to
 id="joesDeliverer"
 service="MyApp.IOrderDeliverer, MyAssembly"                     handle the strike... We
 type="MyApp.JoesSmallPackageDeliverer, MyAssembly"/>                  just swap
                                                                  implementations at
<!-- delivery company on strike ... uncomment after friday...
<component
                                                                  runtime, then swap
  id ="acmeDeliverer"                                            them back again after
  service="MyApp.AcmeLargePackageDeliverer, MyAssembly"                 a week...
  type="MyApp.AcmeLargePackageDeliverer, MyAssembly"/>


<component
  id="OrderDeliverer.Default"
  service="MyApp.IOrderDeliverer, MyAssembly"
  type="MyApp.ThresholdPackageDeliverer, MyAssembly">
                                                                In this case the only real
  <parameters>                                                    change is the service
    <smallDeliverer>${joesDeliverer}</smallDeliverer>                attribute on the
    <largeDeliverer>${acmeDeliverer}</largeDeliverer>
                                                                      joesDeliverer
   <thresholdInKgs>20</thresholdInKgs>
 </parameters>                                                         component.
</component>-->




                                          Please Complete Your Session Evaluation Sheets

Weitere ähnliche Inhalte

Ähnlich wie Architecture Camp 2007 - Inversion Of Control

Aspect-Oriented Programming
Aspect-Oriented ProgrammingAspect-Oriented Programming
Aspect-Oriented Programming
Andrey Bratukhin
 
Ruslan Platonov - Transactions
Ruslan Platonov - TransactionsRuslan Platonov - Transactions
Ruslan Platonov - Transactions
Dmitry Buzdin
 
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMConcurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Mario Fusco
 

Ähnlich wie Architecture Camp 2007 - Inversion Of Control (20)

Declarative presentations UIKonf
Declarative presentations UIKonfDeclarative presentations UIKonf
Declarative presentations UIKonf
 
How to dispatch redux action with timeout
How to dispatch redux action with timeoutHow to dispatch redux action with timeout
How to dispatch redux action with timeout
 
Policy Injection in ASP.NET using Enterprise Library 3.0
Policy Injection in ASP.NET using Enterprise Library 3.0Policy Injection in ASP.NET using Enterprise Library 3.0
Policy Injection in ASP.NET using Enterprise Library 3.0
 
OSMC 2021 | inspectIT Ocelot: Dynamic OpenTelemetry Instrumentation at Runtime
OSMC 2021 | inspectIT Ocelot: Dynamic OpenTelemetry Instrumentation at RuntimeOSMC 2021 | inspectIT Ocelot: Dynamic OpenTelemetry Instrumentation at Runtime
OSMC 2021 | inspectIT Ocelot: Dynamic OpenTelemetry Instrumentation at Runtime
 
Generalized Functors - Realizing Command Design Pattern in C++
Generalized Functors - Realizing Command Design Pattern in C++Generalized Functors - Realizing Command Design Pattern in C++
Generalized Functors - Realizing Command Design Pattern in C++
 
Aspect-Oriented Programming
Aspect-Oriented ProgrammingAspect-Oriented Programming
Aspect-Oriented Programming
 
Ruslan Platonov - Transactions
Ruslan Platonov - TransactionsRuslan Platonov - Transactions
Ruslan Platonov - Transactions
 
Mocks Enabling Test-Driven Design
Mocks Enabling Test-Driven DesignMocks Enabling Test-Driven Design
Mocks Enabling Test-Driven Design
 
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMConcurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
 
Chaincode Use Cases
Chaincode Use Cases Chaincode Use Cases
Chaincode Use Cases
 
Devoxx 2012 (v2)
Devoxx 2012 (v2)Devoxx 2012 (v2)
Devoxx 2012 (v2)
 
Tdd,Ioc
Tdd,IocTdd,Ioc
Tdd,Ioc
 
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
PVS-Studio and Continuous Integration: TeamCity. Analysis of the Open RollerC...
 
Toonz code leaves much to be desired
Toonz code leaves much to be desiredToonz code leaves much to be desired
Toonz code leaves much to be desired
 
React Native custom components
React Native custom componentsReact Native custom components
React Native custom components
 
ReactiveCocoa in Practice
ReactiveCocoa in PracticeReactiveCocoa in Practice
ReactiveCocoa in Practice
 
Inversion Of Control
Inversion Of ControlInversion Of Control
Inversion Of Control
 
CDI and Weld
CDI and WeldCDI and Weld
CDI and Weld
 
To Study The Tips Tricks Guidelines Related To Performance Tuning For N Hib...
To Study The Tips Tricks  Guidelines Related To Performance Tuning For  N Hib...To Study The Tips Tricks  Guidelines Related To Performance Tuning For  N Hib...
To Study The Tips Tricks Guidelines Related To Performance Tuning For N Hib...
 
Angular 16 – the rise of Signals
Angular 16 – the rise of SignalsAngular 16 – the rise of Signals
Angular 16 – the rise of Signals
 

Kürzlich hochgeladen

+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
Asli Kala jadu, Black magic specialist in Pakistan Or Kala jadu expert in Egy...
Asli Kala jadu, Black magic specialist in Pakistan Or Kala jadu expert in Egy...Asli Kala jadu, Black magic specialist in Pakistan Or Kala jadu expert in Egy...
Asli Kala jadu, Black magic specialist in Pakistan Or Kala jadu expert in Egy...
baharayali
 

Kürzlich hochgeladen (20)

Sports Writing (Rules,Tips, Examples, etc)
Sports Writing (Rules,Tips, Examples, etc)Sports Writing (Rules,Tips, Examples, etc)
Sports Writing (Rules,Tips, Examples, etc)
 
Albania Vs Spain South American coaches lead Albania to Euro 2024 spot.docx
Albania Vs Spain South American coaches lead Albania to Euro 2024 spot.docxAlbania Vs Spain South American coaches lead Albania to Euro 2024 spot.docx
Albania Vs Spain South American coaches lead Albania to Euro 2024 spot.docx
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Muzaffarpur Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Muzaffarpur Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMuzaffarpur Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Muzaffarpur Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
WhatsApp Chat: 📞 8617697112 Birbhum Call Girl available for hotel room package
WhatsApp Chat: 📞 8617697112 Birbhum  Call Girl available for hotel room packageWhatsApp Chat: 📞 8617697112 Birbhum  Call Girl available for hotel room package
WhatsApp Chat: 📞 8617697112 Birbhum Call Girl available for hotel room package
 
Personal Brand Exploration - By Bradley Dennis
Personal Brand Exploration - By Bradley DennisPersonal Brand Exploration - By Bradley Dennis
Personal Brand Exploration - By Bradley Dennis
 
UEFA Euro 2024 Squad Check-in Which team is Top favorite.docx
UEFA Euro 2024 Squad Check-in Which team is Top favorite.docxUEFA Euro 2024 Squad Check-in Which team is Top favorite.docx
UEFA Euro 2024 Squad Check-in Which team is Top favorite.docx
 
Hire 💕 8617697112 Kasauli Call Girls Service Call Girls Agency
Hire 💕 8617697112 Kasauli Call Girls Service Call Girls AgencyHire 💕 8617697112 Kasauli Call Girls Service Call Girls Agency
Hire 💕 8617697112 Kasauli Call Girls Service Call Girls Agency
 
Unveiling the Mystery of Main Bazar Chart
Unveiling the Mystery of Main Bazar ChartUnveiling the Mystery of Main Bazar Chart
Unveiling the Mystery of Main Bazar Chart
 
European Football Icons that Missed Opportunities at UEFA Euro 2024.docx
European Football Icons that Missed Opportunities at UEFA Euro 2024.docxEuropean Football Icons that Missed Opportunities at UEFA Euro 2024.docx
European Football Icons that Missed Opportunities at UEFA Euro 2024.docx
 
2k Shots ≽ 9205541914 ≼ Call Girls In Sheikh Sarai (Delhi)
2k Shots ≽ 9205541914 ≼ Call Girls In Sheikh Sarai (Delhi)2k Shots ≽ 9205541914 ≼ Call Girls In Sheikh Sarai (Delhi)
2k Shots ≽ 9205541914 ≼ Call Girls In Sheikh Sarai (Delhi)
 
Asli Kala jadu, Black magic specialist in Pakistan Or Kala jadu expert in Egy...
Asli Kala jadu, Black magic specialist in Pakistan Or Kala jadu expert in Egy...Asli Kala jadu, Black magic specialist in Pakistan Or Kala jadu expert in Egy...
Asli Kala jadu, Black magic specialist in Pakistan Or Kala jadu expert in Egy...
 
JORNADA 6 LIGA MURO 2024TUXTEPECOAXACA.pdf
JORNADA 6 LIGA MURO 2024TUXTEPECOAXACA.pdfJORNADA 6 LIGA MURO 2024TUXTEPECOAXACA.pdf
JORNADA 6 LIGA MURO 2024TUXTEPECOAXACA.pdf
 
Who Is Emmanuel Katto Uganda? His Career, personal life etc.
Who Is Emmanuel Katto Uganda? His Career, personal life etc.Who Is Emmanuel Katto Uganda? His Career, personal life etc.
Who Is Emmanuel Katto Uganda? His Career, personal life etc.
 
Spain Vs Italy Spain to be banned from participating in Euro 2024.docx
Spain Vs Italy Spain to be banned from participating in Euro 2024.docxSpain Vs Italy Spain to be banned from participating in Euro 2024.docx
Spain Vs Italy Spain to be banned from participating in Euro 2024.docx
 
Ramban Escorts ☎️8617697112 Starting From 5K to 15K High Profile Escorts In...
Ramban  Escorts ☎️8617697112  Starting From 5K to 15K High Profile Escorts In...Ramban  Escorts ☎️8617697112  Starting From 5K to 15K High Profile Escorts In...
Ramban Escorts ☎️8617697112 Starting From 5K to 15K High Profile Escorts In...
 
Slovenia Vs Serbia UEFA Euro 2024 Fixture Guide Every Fixture Detailed.docx
Slovenia Vs Serbia UEFA Euro 2024 Fixture Guide Every Fixture Detailed.docxSlovenia Vs Serbia UEFA Euro 2024 Fixture Guide Every Fixture Detailed.docx
Slovenia Vs Serbia UEFA Euro 2024 Fixture Guide Every Fixture Detailed.docx
 
UEFA Euro 2024 Squad Check-in Who is Most Favorite.docx
UEFA Euro 2024 Squad Check-in Who is Most Favorite.docxUEFA Euro 2024 Squad Check-in Who is Most Favorite.docx
UEFA Euro 2024 Squad Check-in Who is Most Favorite.docx
 
JORNADA 5 LIGA MURO 2024INSUGURACION.pdf
JORNADA 5 LIGA MURO 2024INSUGURACION.pdfJORNADA 5 LIGA MURO 2024INSUGURACION.pdf
JORNADA 5 LIGA MURO 2024INSUGURACION.pdf
 
Spain Vs Albania- Spain at risk of being thrown out of Euro 2024 with Tournam...
Spain Vs Albania- Spain at risk of being thrown out of Euro 2024 with Tournam...Spain Vs Albania- Spain at risk of being thrown out of Euro 2024 with Tournam...
Spain Vs Albania- Spain at risk of being thrown out of Euro 2024 with Tournam...
 

Architecture Camp 2007 - Inversion Of Control

  • 1. Designing for Inversion of Control Architecture Camp 2007 Alex Henderson DevDefined Limited
  • 2. About Me  Senior Developer / Director at DevDefined Limited.  Used IoC in all major projects since 2005.  Specialise in product development & consultancy.  .Net Developer since First Beta of the 1.0 Framework.  Email: alex@devdefined.com  Blog: http://blog.bittercoder.com/ Please Complete Your Session Evaluation Sheets
  • 3. What drives us towards using IoC ?  Difficulty responding to change.  Tight coupling.  Difficulty managing dependencies.  Cant easily switch implementations at runtime.  Need for Lifestyle management. Please Complete Your Session Evaluation Sheets
  • 4. So what is IoC It’s a principle!  Approach to designing components which are more reusable.  By moving control away from your components  Better reusability by enforcing isolation.  Key goal: Loosen the coupling between services.  IoC Not really a design pattern.  Dependency Injection (DI) helps achieve this isolation.  Increases testability of components Please Complete Your Session Evaluation Sheets
  • 5. Dependency Injection Example In this example we look a service which can handle processing a purchase request for a lottery ticket.  Checking we can still purchase the ticket for the selected draw number (has it already been drawn?)  Collecting payment for the ticket.  Send a notification message to the person buying the ticket with the outcome of their purchase. Please Complete Your Session Evaluation Sheets
  • 6. First take on the Ticket Processor public partial class LottoTicketProcessor : ITicketProcessor { public void Process(Ticket ticket) { if (DrawManager.Instance .CanStillPurchaseFor(ticket.DrawNumber)) { if (CollectionAgency.Instance .Collect(ticket.Customer, ticket.Cost)) { ticket.TicketStatus = TicketStatus.Purchased; SendTicketDetailsNotification(ticket); return; } } SendPurchaseFailedNotification(); } } Please Complete Your Session Evaluation Sheets
  • 7. Something smells.. There are problems with the implementation  Heavy use of singletons  Difficult, perhaps even impossible to test *  Tightly coupled (where’s the abstractions?)  The ticket processor knows too much!  Violates single responsibility principle  Hard to reuse the ticket processor – not flexible. * Well, maybe not impossible... There’s always the big hammer known as TypeMock.Net (http://www.typemock.com/ ) – but being able to test it doesn’t stop your code smelling! Please Complete Your Session Evaluation Sheets
  • 8. I heard factories were good... public partial class LottoTicketProcessor2 : ITicketProcessor { public void Process(Ticket ticket) { We’ve just swapped knowledge of a singleton, if (DrawManagerFactory.Create(). for knowledge of a CanStillPurchaseFor(ticket.DrawNumber)) factory... { if (CollectionAgencyFactory.Create() .Collect(ticket.Customer, ticket.Cost)) { ticket.TicketStatus = TicketStatus.Purchased; NotificationSenderFactory.Create() .SendTicketDetailsNotification(ticket); But at least we can return; change the concrete } implementation used. } NotificationSenderFactory.Create().SendPurchaseFailedNotification(); } } Please Complete Your Session Evaluation Sheets
  • 9. Service Locators  Provides a way to manage dependencies.  Concept already used in the .Net Framework.  As the name suggest, a service locator is used... to locate services – could be seen as a “registry”. Please Complete Your Session Evaluation Sheets
  • 10. Example with Service Locator public partial class LottoTicketProcessor3 : ITicketProcessor { private ServiceLocator _locator; We can now public LottoTicketProcessor3(ServiceLocator locator) { test the ticket _locator = locator; processor by } mocking the public void Process(Ticket ticket) { service locator if (_locator.DrawManager.CanStillPurchaseFor(ticket.DrawNumber)) { if (_locator.CollectionAgency.Collect(ticket.Customer, ticket.Cost)) { ticket.TicketStatus = TicketStatus.Purchased; _locator.NotificationSender .SendTicketDetailsNotification(ticket); return; } } _locator.NotifcationSender.SendPurchaseFailedNotification(ticket); } Please Complete Your Session Evaluation Sheets
  • 11. Service Locators have issues  All classes will depend on the service locator.  Dependencies are generally resolved as-needed – requires additional coding to support “failing fast” when constructed.  Often requires complicated code to setup as service count grows.  Can impair reusability.  But some people find it easier to “grok” Please Complete Your Session Evaluation Sheets
  • 12. Dependency Injection Range of mechanisms available...  The constructor  Normally implies it’s compulsory.  Should probably remove default constructor.  A property setter  Often implying it’s optional, but not always.  If optional should probably have a default value.  Other methods  Interface (not that common)  Method (even less common)  Virtual property getter (very rare, needs a proxy to be generated)  And some even more obscure ideas... Please Complete Your Session Evaluation Sheets
  • 13. Back to the example... Constructor based injection public partial class LottoTicketProcessor4 : ITicketProcessor { private readonly ICollectionAgency _agency; Using read-only private readonly IDrawManager _drawManager; properties here private readonly IEmailSender _sender; - assert that these services public LottoTicketProcessor4(ICollectionAgency agency, should not IDrawManager drawManager, IEmailSender sender) change during { lifetime.. _agency = agency; _drawManager = drawManager; _sender = sender; } Please Complete Your Session Evaluation Sheets
  • 14. And the implementation... Simple eh? public void Process(Ticket ticket) { if (_drawManager.CanStillPurchaseFor(ticket.DrawNumber)) { if (_agency.Collect(ticket.Customer, ticket.Cost)) { ticket.TicketStatus = TicketStatus.Purchased; _sender.SendTicketDetailsNotification(ticket); return; } } _sender.SendPurchaseFailedNotification(ticket); } Please Complete Your Session Evaluation Sheets
  • 15. A taste of testing... // start recording... MockRepository repository = new MockRepository(); Ticket ticket = new Ticket(10); // Set Draw Number IDrawManager drawManager = repository.CreateMock<IDrawManager>(); Expect.Call(drawManager.CanStillPurchaseFor(ticket.DrawNumber)) .Return(false); Here we’re setting INotificationSender sender = expectations (that this repository.CreateMock<INotificationSender>(); method will be called) sender.SendPurchaseFailedNotification(ticket); LastCall.Constraints(Is.Same(ticket)); ICollectionAgency agency = repository.CreateMock<ICollectionAgency>(); repository.ReplayAll(); // start replaying... LottoTicketProcessor4 processor = new LottoTicketProcessor4(agency, drawManager, sender); processor.Process(ticket); repository.VerifyAll(); Verify the expectations were met... throws if not Please Complete Your Session Evaluation Sheets
  • 16. Designing for Dependency Injection  Systems are comprised of small, focused services – Services are abstractions (Interfaces).  Components implement the services – Concrete classes.  A component declares exactly what dependencies (services) it relies on.  A component does not dictate it’s own lifestyle.  Don’t implement singleton behaviour yourself.  You can test all facets of your application. Please Complete Your Session Evaluation Sheets
  • 17. IoC Containers  Single point of access for all services in app.  IoC containers can fill many needs, but simple containers generally handle:  Assembling services by resolving and injecting dependencies.  Managing the lifestyle of services.  Some containers allow you to use configuration files.  Automatically resolves all the dependencies - auto- wiring – constructors called for you via reflection. Please Complete Your Session Evaluation Sheets
  • 18. Example container public class SimpleContainer { Singleton lifestyle private IDrawManager _drawManager = new DrawManager(); achieved by the container private INotificationSender _notificationSender = holding onto references... new SmsNotificationSender("cheapnsms.net.nz"); private ICollectionAgency _collectionAgency = new MBillWebServiceCollectionAgency(); public T Resolve<T>() { if (typeof(T) == typeof(IDrawManager)) return (T)_drawManager; if (typeof(T) == typeof(INotificationSender)) return (T)_notificationSender; if (typeof(T) == typeof(ICollectionAgency)) return (T)_collectionAgency; if (typeof(T) == typeof(ITicketProcessor)) { Wire up a transient component ITicketProcessor processor = every time it’s requested... new LottoTicketProcessor4(_collectionAgency, _drawManager, _notificationSender); return (T) processor; } throw new NoMatchingComponentException(“Cant resolve service: {0}", typeof(T)); } Please Complete Your Session Evaluation Sheets
  • 19. Available containers (with .Net impls)  Castle’s Windsor Container & Micro Kernel - .Net  ObjectBuilder – .Net (Microsofts Implementation)  Used in CAB & Enterprise Library  Pico/Nano Container - Java, .Net, Ruby, PHP  Seasar2 – Java, PHP, .Net (needs work!)  Spring.Net – Java, .Net  StructureMap - .Net Please Complete Your Session Evaluation Sheets
  • 20. What a container can do for a project  Save time and repetitive code to wire up dependencies.  Provides an easy way to inject configuration information.  Easily move between configurations  Test / Production  Different clients – different configurations.  Transparently proxy components & intercept methods  Implement cross cutting concerns (logging, security) – AOP.  Lifestyle management (Singleton, Transient, Per-Request, Per-Thread, Pooled etc.)  Lifecycle management. Please Complete Your Session Evaluation Sheets
  • 21. What they don’t tell you  Debugging container configuration problems can be frustrating  Often caused by no refactoring support.  Components configured with the wrong lifestyle can introduce difficult to diagnose problems  may not become apparent during unit tests.  Obfuscation and container configuration files don’t mix.  Cross-cutting concerns makes solutions less predictable, use AOP only if you understand the impacts. Golden Rule  IoC should only be used if you know how it helps you.  Otherwise you will think it's a pointless obstruction. Please Complete Your Session Evaluation Sheets
  • 22. Resources  Castle project  http://www.castleproject.org/  Ayendes (Oren Eini) presentations & blog  http://www.ayende.com/  http://msdn2.microsoft.com/en-us/library/aa973811.aspx  Object Builder  http://www.codeplex.com/ObjectBuilder  Martin Fowler of Dependency Injection  http://www.martinfowler.com/articles/injection.html  Stefano Mazzocchi – On Inversion of Control  http://www.betaversion.org/~stefano/linotype/news/38/ Please Complete Your Session Evaluation Sheets
  • 23. Evaluations and Contact  Thanks for listening!  Don’t forget to fill in your evaluations  Presentation downloads available from  My Blog  Also available from http://www.dot.net.nz within a week of this event.  Email: alex@devdefined.com  Work: http://www.devdefined.com/  Blog: http://blog.bittercoder.com/ Please Complete Your Session Evaluation Sheets
  • 24. Decorator Patterns in IoC Selects an implementation based on weight... Please Complete Your Session Evaluation Sheets
  • 25. Decorator Patterns in IoC public class ThresholdPackageDeliverer : IOrderDeliverer { private readonly decimal thresholdInKgs; private readonly IOrderDeliverer smallDeliverer; private readonly IOrderDeliverer largeDeliverer; public ThresholdPackageDeliverer(IOrderDeliverer smallDeliverer, IOrderDeliverer largeDeliverer, decimal thresholdInKgs) { Notice both this.smallDeliverer = smallDeliverer; config and this.largeDeliverer = largeDeliverer; dependencies in this.thresholdInKgs = thresholdInKgs; constructor... } public void OrganiseDelivery(Order orderToDeliver) { if (orderToDeliver.TotalWeight < thresholdInKgs) { smallDeliverer.OrganiseDelivery(orderToDeliver); } else { largeDeliverer.OrganiseDelivery(orderToDeliver); } } Please Complete Your Session Evaluation Sheets
  • 26. Decorator Patterns in IoC <component id="joesDeliverer" service="MyApp.JoesSmallPackageDeliverer, MyAssembly" type="MyApp.JoesSmallPackageDeliverer, MyAssembly"/> <component id ="acmeDeliverer" service="MyApp.AcmeLargePackageDeliverer, MyAssembly" type="MyApp.AcmeLargePackageDeliverer, MyAssembly"/> Threshold package <component deliver is wired up the id="defaultDeliverer" service="MyApp.IOrderDeliverer, MyAssembly" joes and acme type="MyApp.ThresholdPackageDeliverer, MyAssembly"> deliverer + threshold <parameters> in the config. <smallDeliverer>${joesDeliverer}</smallDeliverer> <largeDeliverer>${acmeDeliverer}</largeDeliverer> <thresholdInKgs>2000</thresholdInKgs> </parameters> </component> Please Complete Your Session Evaluation Sheets
  • 27. Decorator Patterns in IoC <!-- on strike, so just use joes deliverer --> <component No recompile to id="joesDeliverer" service="MyApp.IOrderDeliverer, MyAssembly" handle the strike... We type="MyApp.JoesSmallPackageDeliverer, MyAssembly"/> just swap implementations at <!-- delivery company on strike ... uncomment after friday... <component runtime, then swap id ="acmeDeliverer" them back again after service="MyApp.AcmeLargePackageDeliverer, MyAssembly" a week... type="MyApp.AcmeLargePackageDeliverer, MyAssembly"/> <component id="OrderDeliverer.Default" service="MyApp.IOrderDeliverer, MyAssembly" type="MyApp.ThresholdPackageDeliverer, MyAssembly"> In this case the only real <parameters> change is the service <smallDeliverer>${joesDeliverer}</smallDeliverer> attribute on the <largeDeliverer>${acmeDeliverer}</largeDeliverer> joesDeliverer <thresholdInKgs>20</thresholdInKgs> </parameters> component. </component>--> Please Complete Your Session Evaluation Sheets