Dataworks Blog

    INVERSION OF CONTROL REVIEW

  • Inversion of Control Review

    The quality of a software system is determined by how easily and efficiently it can be updated.

    When designing a software system we should take in consideration following principles:

    • Maintainability

    • Testability

    • Scalability

    • Flexibility and Extensibility

    • Parallel development

    • Crosscutting concerns

    • Loose coupling

    Loose Coupling – sometimes examples may look like complicating the application, however this technique is intended to simplify and manage large & complex applications.

    Five principles of Object Oriented Programming and Design

    • Single responsibility principle

    • Open/close principle

    • Liskov substitution principle

    • Interface segregation principle

    • Dependency inversion principle

    The principle that we are going to focus on in this article is Dependency Inversion Principle:

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

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

    Best known patterns that implement Dependency Inversion Principle are

    1. Factory Pattern(s)

    2. Service Locator

    3. Dependency Injection

    Factories, service locators, and dependency injection are all approaches that can be used to move the responsibility for instantiating and managing objects on behalf of other client objects.

     

     

    Figure 1 - Dependencies in the factory pattern (http://msdn.microsoft.com/en-us/library/dn178469(v=pandp.30).aspx)

    A common feature of the factory patterns and the service locator pattern is that it is still the high-level client object's responsibility to resolve its own dependencies by requesting the specific instances of the types that it needs.

    With dependency injection, another class is responsible for injecting (pushing) the dependencies into the high-level client classes at runtime. 

    In a typical application that uses dependency injection we will have many cases that require some other classes/components that require passing necessary dependencies.

    1. Constructor Injection

    2. Property / Setter injection

    3. Method Injection

    This must happen very early in the application's lifecycle: for example, in the Main method of a console application, in the Global.asax in a web application, in a role's OnStart method in a Windows Azure application, or in the initialization code for a test method. This is known as Composition Root.

    Type registration and resolving do incur a runtime penalty: very negligible for resolving, but more so for registration. However, the registration should only happen once.

    The Dependency Injection Lifecycle:

    1. Register

    2. Resolve

    3. Dispose

    An IoC (Inversion of Control) container will manage the DI Lifecycle.

    We should design container agnostic systems in order to decouple it from a specific IoC container.

    We are going to review following containers:

    • Castel Windsor

    • Ninject

    • Autofac

    • StructureMap

    • Unity      

     

     

    Singleton – The instance will be created the first time someone requests it, and subsequently reused every time it's needed. State-less components or objects with big state, in which case producing multiple instances may unnecessarily raise memory consumption of your application, are good candidates for this.

    Transient - a new instance is created every time a dependency is requested.  Transient components are not bound to any tangible scope. Transient lifestyle is a good choice when you want to be in control of an instance's lifetime or when you need a new instance with new state every time. Also transient components don't need to be thread safe, unless you explicitly use them in multi-threaded situations.

    Per Request - Instance of a component will be shared in scope of a single web request. The instance will be created the first time it's requested in scope of the web request. Releasing it explicitly does nothing. Instance will be released upon the end of the web request

    Performance comparison charts: (http://www.iocbattle.com/)

     

     

     

    Using Dependency Injection looks to be a great pattern to design a SOLID application.  However there are a few common pitfalls that we should take into consideration:

    • Constructor over injection.

    • Sometimes counterintuitive

    • May be Overkill in small projects

  • Back to Blogs