Search

Categories

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Send mail to the author(s) E-mail

# Monday, 08 September 2014

Goal is to rewrite www.davesjokes.co.uk in a SOLID way:

Source is:  https://github.com/djhmateer/solidjokes

  • Single Responsibility
  • Open Closed Principle
  • Liskov substitution
  • Interface segregation
  • Dependency Inversion

Pure DI (Poor Mans), aim for open closed and SRP so testing is easier and  Decorator for logging

public class HomeController : Controller {
    private readonly ILogger logger;

    public HomeController() {
        logger = new Logger();
    }

    // So this is useful for testing now
    public HomeController(ILogger logger) {
        this.logger = logger;
    }

    public ActionResult Index() {
        logger.Log("In Index of Home Controller");
        return View();
    }

    public ActionResult About() {
        ViewBag.Message = "Your application description page.";

        return View();
    }

    public ActionResult Contact() {
        ViewBag.Message = "Your contact page.";

        return View();
    }
}

public interface ILogger { void Log(string text);}
public class Logger : ILogger {
    public void Log(string text) {
        Console.WriteLine(text);
    }
}

Simplest possible DI in MVC – in fact we’re only using DI when it’s called from a test method through the overloaded ctor.
public class HomeController : Controller {
    private readonly ILogger logger;

    public HomeController(ILogger logger) {
        this.logger = logger;
    }

    public ActionResult Index() {
        logger.Log("In Index of Home Controller");
        return View();
    }

    public ActionResult About() {
        ViewBag.Message = "Your application description page.";
        return View();
    }

    public ActionResult Contact() {
        ViewBag.Message = "Your contact page.";
        return View();
    }
}

public interface ILogger { void Log(string text);}
public class Logger : ILogger {
    public void Log(string text) {
        Console.WriteLine(text);
        Debug.WriteLine(text);
    }
}
public class MvcApplication : System.Web.HttpApplication {
    protected void Application_Start() {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        // Patch in our own Factory/Composition Root into MVC pipeline
        var controllerFactory = new SolidJokesControllerFactory();
        ControllerBuilder.Current.SetControllerFactory(controllerFactory);
    }
}

public class SolidJokesControllerFactory : DefaultControllerFactory {
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
        var logger = new Logger();
        if (controllerType == typeof(HomeController)) {
            return new HomeController(logger);
        }

        return base.GetControllerInstance(requestContext, controllerType);
    }
}

image
Debug.WriteLine logging, and our own Pure DI setup in the simplest way.

SRP – Decorating a Controller

HomeController has logging inside of it.  Lets decorate it, so making sure the HomeController does only 1 thing.

public class SolidJokesControllerFactory : DefaultControllerFactory {
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) {
        if (controllerType == typeof(HomeController)) {
            // Decorating HomeController with HomeControllerLogger
            return new HomeControllerLogger(new HomeController());
        }
        // AccountController will still go the normal tightly coupled way
        return base.GetControllerInstance(requestContext, controllerType);
    }
}
public interface IHomeController
{
    ActionResult Index();
    ActionResult About();
    ActionResult Contact();
}
    public class HomeControllerLogger : Controller, IHomeController {
        private readonly IHomeController homeController;

        public HomeControllerLogger(IHomeController homeController) {
            this.homeController = homeController;
        }

        public ActionResult Index() {
            Debug.WriteLine("In Index of HomeControllerLogger");
            var result = homeController.Index();
            Debug.WriteLine("End Index of HomeControllerLogger");
            return result;
        }

        public ActionResult About() {
            Debug.WriteLine("In About of HomeControllerLogger");
            var result = homeController.About();
            Debug.WriteLine("End About of HomeControllerLogger");
            return result;
        }

        public ActionResult Contact() {
            return homeController.Contact();
        }
    }

image

Added in a test project to solution taking the boilerplate tests from VS2013.  Using xunit.  Updated references and went to MVC5.2.2 in both projects.

| | # 
# Wednesday, 27 August 2014

Rewriting Mark Seemanns ComplexCommerce as PureCommerce using PureDI

http://www.programgood.net/CategoryView,category,Git.aspx – Setup source control to start with and put on GitHub

Start with a new MVC5 project, and connect to his existing database the simplest way possible and display some data

http://msdn.microsoft.com/en-us/data/jj200620 – Reverse Engineer Code Model - Existing db

Hard Coded Dependency

asdf

Dependency Injected

**need a very simple example of how to do this in MVC? or even ConsoleApp?
and on 1 page

| | # 
# Tuesday, 26 August 2014

“When it comes to talking about how to structure code to solve particular types of problems, we have Design Patterns that give names to common solutions”

Constructor Injection

“How do we guarantee that a necessary Dependency is always available to the class we’re currently developing?”

“By requiring all callers to supply the dependency as a parameter to the class’s constructor”

public class RepositoryBasketDiscountPolicy : BasketDiscountPolicy {
    private readonly DiscountRepository repository;

    public RepositoryBasketDiscountPolicy(DiscountRepository repository) {
        if (repository == null) {
            throw new ArgumentNullException("repository");
        }

        this.repository = repository;
    }
  • Use a guard clause to protect against nulls
  • Field holding the dependency as readonly – guarantees that it wont be changed
  • Tip – keep constructor free of any other logic.  SRP
  • Tip – if possible, constrain design to a single constructor

Should be the default choice.

Adding a currency provider to the shopping basket

image
The user can now select among 3 different currencies, and product prices and basket totals (on the basket page) will be displayed in that currency

image
Mark’s code is tied to the older pre MVC5 user authentication/authorisation model, so code doesn’t work as yet.  This may be a perfect opportunity to build up a new solution from scratch, so fully understanding the architecture, and build up in parallel with Mark’s solution which I’m cobbling together on the way in MVC5

http://stackoverflow.com/questions/23306916/unity-autowiring-to-use-or-not-to-use/23312402#23312402

And coming up to date, Mark is very pro ‘Poor Mans DI’ if possible.  I like his stance on ‘Magic happens’ in the team ie only 1 person really understands what is happening.  So maybe this next example from scratch should aim towards poor mans, and see how far I can push the example.

page 101

Pure DI (aka Poor Mans DI)

http://blog.ploeh.dk/2014/06/10/pure-di/

“DI is a set of principles and patterns; DI Containers are optional helper libraries.”

Mark has changed thinking slightly, and now favours firstly using Pure DI because:

  • Simpler
  • Compile time checking

So in that realm, I’m going to rewrite 4ComplexCommerce in that style

  • See the object composition he is using
  • See the patterns (eg constructor injection)
  • Make sure the tests are there

Why? Because:

  • DI enables loose coupling – an important part of maintainable code
  • It is a complex example which is worthy!
| | # 
# Friday, 08 August 2014

DI is a technique just like making ice cream
DI Containers are a technology just like an ice cream maker is

Intro

A DI Container (aka IoC Container) is a library that can automate many of the tasks involved in composing objects and managing their lifetimes.

DI is like logging or data access.  It is a general purpose library to compose object graphs.

ComplexCommerce

Making a new MVC5 project.  Got an FK on the ComplexCommerce on aspnet_users table, which we don’t use anymore in MVC5.  Made a dirt simple MVC5 project with no Controllers, and got something running!  Also put on GitHub.  Added references to the MVC project which shouldn’t be there – Sql for sure.. and?  A quick fix to get something running.

https://github.com/djhmateer/4ComplexCommerce

image

jumping back to ch2 to understand 4ComplexCommerce and do an overall diagram on paper.

Invalid object name 'dbo.aspnet_Users'.

https://code.google.com/p/uit-luan-an-tot-nghiep/source/browse/trunk/Source/SQLDatabases/?r=72#SQLDatabases%2FScripts

or I could just create the tables with an older version of code?

Unity, Castle Windsor and StructureMap

General shape is:
var controller = (IController)this.container.Resolve(controllerType);
Or Resolve<T> if know type at design time

Castle Windsor and StructureMap are similar eg StuctureMap:

var controller = (IController)this.container.GetInstance(controllerType);

If use Resolve<T>, need to take care not to use the DI Container as a Service Locator ????

Auto Wiring

image
A DI Container will recursively find concrete types and examine their constructors until it can define the entire object tree. (diagram and following ones all from Mark’s book).

image

image

XML Configuration

Unity is one of the more XML-centric DI Containers, so wiring it up using XML:

<unity>
  <assembly name="Ploeh.Samples.Commerce.Domain" />
  <assembly name="Ploeh.Samples.Commerce.Data.Sql" />
  <!--<assembly name="Ploeh.Samples.Commerce.Web" />-->
  <assembly name="CommerceWebMVC" />
  <assembly name="Ploeh.Samples.Commerce.Web.PresentationModel" />
  <namespace name="Ploeh.Samples.Commerce.Domain" />
  <namespace name="Ploeh.Samples.Commerce.Data.Sql" />
  <namespace name="Ploeh.Samples.Commerce.Web.Unity" />
  <namespace name="Ploeh.Samples.Commerce.Web.PresentationModel.Controllers" />
  <container>
    <register type="IBasketService"
              mapTo="BasketService" />
    <register type="BasketDiscountPolicy"
              mapTo="RepositoryBasketDiscountPolicy" />
    <register type="BasketRepository"
              mapTo="SqlBasketRepository">
      <constructor>
        <param name="connString">
          <value value="CommerceObjectContext"
                 typeConverter="ConnectionStringConverter" />
        </param>
      </constructor>
    </register>
    <register type="DiscountRepository"
              mapTo="SqlDiscountRepository">
      <constructor>
        <param name="connString">
          <value value="CommerceObjectContext"
                 typeConverter="ConnectionStringConverter" />
        </param>
      </constructor>
    </register>
    <register type="ProductRepository"
              mapTo="SqlProductRepository">
      <constructor>
        <param name="connString">
          <value value="CommerceObjectContext"
                 typeConverter="ConnectionStringConverter" />
        </param>
      </constructor>
    </register>
    <register type="CurrencyProvider"
              mapTo="SqlCurrencyProvider">
      <constructor>
        <param name="connString">
          <value value="CommerceObjectContext"
                 typeConverter="ConnectionStringConverter" />
        </param>
      </constructor>
    </register>
    <register type="AccountController">
      <constructor />
    </register>
  </container>
</unity>
And I wonder why XML went out of fashion….  As as app grows, this can become brittle.  Only use this approach when you need late binding.

Configuring Containers with Code

Most DI Containers (except Spring.NET) fully support Code as Configuration

Using StructureMap as it has a terser API:  This is the oldest IoC/DI tool for .NET having been in prod since 2004

Bringing in StructureMap 2.6.2 dll

image

Success with StructureMap, and configuring through code.

public static class CommerceCodeAsConfiguration
{
    public static void Configure(IContainer container)
    {
        container.Configure(c =>
        {
            c.For<IBasketService>().Use<BasketService>();
            c.For<BasketDiscountPolicy>()
                .Use<RepositoryBasketDiscountPolicy>();

            var connectionString = ConfigurationManager.ConnectionStrings ["CommerceObjectContext"].ConnectionString;
                
            c.For<BasketRepository>().Use<SqlBasketRepository>()
                .Ctor<string>().Is(connectionString);
            c.For<DiscountRepository>().Use<SqlDiscountRepository>()
                .Ctor<string>().Is(connectionString);
            c.For<ProductRepository>().Use<SqlProductRepository>()
                .Ctor<string>().Is(connectionString);
            c.For<CurrencyProvider>().Use<SqlCurrencyProvider>()
                .Ctor<string>().Is(connectionString);
        });

        container.Configure(c =>
        {
            c.For<IFormsAuthentication>().Use(new FormsAuthenticationService());
            c.For<IMembershipService>().Use(new AccountMembershipService());
        });
    }
}

Much more terse, and has compiler checking.

Configuring Containers by Convention

The more you can move your code towards conventions, the more maintainable it will be.

Using Autofac as it have a fairly readable auto-registration API

All four Data Access concrete types share some characteristics: (these seem to be the most repetitive)

  • All defined in the same assembly
  • Each is a concrete class inheriting from an abstract base class
  • Each has a name this start with Sql
  • Each has a single public constructor that takes a string parameter called connString
protected override void Load(ContainerBuilder builder) {
    builder.RegisterAssemblyTypes(typeof(HomeController).Assembly)
        .AsSelf()
        .InstancePerLifetimeScope();
    builder.RegisterAssemblyTypes(typeof(BasketService).Assembly)
        .Where(t => t.Name.EndsWith("Service"))
        .AsImplementedInterfaces()
        .SingleInstance();
    builder.RegisterAssemblyTypes(typeof(BasketDiscountPolicy).Assembly)
        .Where(t => t.Name.EndsWith("Policy"))
        .As(t => t.BaseType)
        .SingleInstance();

    string connectionString = ConfigurationManager.ConnectionStrings["CommerceObjectContext"].ConnectionString;
    var a = typeof(SqlProductRepository).Assembly;
    builder.RegisterAssemblyTypes(a)
        .Where(t => t.Name.StartsWith("Sql"))
        .As(t => t.BaseType)
        .InstancePerLifetimeScope()
        .WithParameter("connString", connectionString);
}

Composition Root

Where should we compose object graphs?  As close as possible to the app’s entry point

Acts as a 3rd party that connects consumers with their resources

Tip:  A DI Container should only be referenced from the Composition Root.  All other modules should have no reference to the container

Tip: Don’t worry about the perf overhead of using a DI Containers to compose large object graphs.  It’s almost never an issue

**StructureMap and Castle both need older versions to compile

http://blog.ploeh.dk/2009/11/17/UsingCastleWindsor'sPerWebRequestlifestylewithASP.NETMVConIIS7/

Couldn’t get Windsor working for reason above.

Tip:  Hollywood Principle – don’t call the container, it’ll call you

Register Resolve Release

You shouldn’t go back and reconfigure the container once you have started resolving object graphs.

public void Install(IWindsorContainer container, IConfigurationStore store) {
    //Register
    container.Register(AllTypes
        .FromAssemblyContaining<HomeController>()
        .BasedOn<IController>()
        .Configure(r => r.LifeStyle.PerWebRequest));
    //Register
    container.Register(AllTypes
        .FromAssemblyContaining<BasketService>()
        .Where(t => t.Name.EndsWith("Service"))
        .WithService
        .AllInterfaces());
    //Register
    container.Register(AllTypes
        .FromAssemblyContaining<BasketDiscountPolicy>()
        .Where(t => t.Name.EndsWith("Policy"))
        .WithService
        .Select((t, b) => new[] { t.BaseType }));

    string connectionString = ConfigurationManager.ConnectionStrings["CommerceObjectContext"].ConnectionString;
    //Register
    container.Register(AllTypes
        .FromAssemblyContaining<SqlProductRepository>()
        .Where(t => t.Name.StartsWith("Sql"))
        .WithService
        .Select((t, b) => new[] { t.BaseType })
        .Configure(r => r.LifeStyle.PerWebRequest
            .DependsOn((new {
                connString = connectionString
            }))));
}

Important to see here, just that there are 4 calls to the Register method. **code not working due to Castle issue with IIS7.  Solvable probably!

public class WindsorControllerFactory : DefaultControllerFactory
{
    private readonly IWindsorContainer container;

    public WindsorControllerFactory(IWindsorContainer container)
    {
        this.container = container;
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        return (IController)this.container.Resolve(controllerType);
    }

    public override void ReleaseController(IController controller)
    {
        this.container.Release(controller);
    }
}

ASP.NET MVC invokes GetControllerInstance method  and ReleaseController methods – appropriate for Resolve and Release.

DI Container Landscape

…”a DI Container will make you life easier, so use one whenever you can”

…”by isolating the Container usage to the Composition Root, you can shield the Container from beginners”

| | # 
# Wednesday, 16 July 2014

“DI is a way to enable loose coupling, and loose coupling is first and foremost an efficient way to deal with complexity”

image

“Anyone can draw a three-layer application diagram, and [this] proves that I can, too”!

Building a tightly coupled application

MVC, EF and MSSQL application.  E-commerce.

  • List of featured products
  • If user is a preferred customer, the price on all products should be discounted by 5%

Data Layer

image
Creates a table in SSMS

image
Uses EF to create an Entity Model (db first).  She has changed Featured to IsFeatured in the model

Domain Layer

How to know who is a preferred customer?

    public partial class ProductService {
        private readonly CommerceObjectContext objectContext;

        public ProductService() {
            this.objectContext = new CommerceObjectContext();
        }

        public IEnumerable<Product> GetFeaturedProducts(
            bool isCustomerPreferred) {
            var discount = isCustomerPreferred ? .95m : 1;
            var products = (from p in this.objectContext
                                .Products
                            where p.IsFeatured
                            select p).AsEnumerable();
            return from p in products
                   select new Product {
                       ProductId = p.ProductId,
                       Name = p.Name,
                       Description = p.Description,
                       IsFeatured = p.IsFeatured,
                       UnitPrice = p.UnitPrice * discount
                   };
        }
    }

She implements this in the domain layer.  However she needs a reference to the DAL as ObjectContext is defined there.

UI Layer

public ActionResult Index() {
    bool isPreferredCustomer = this.User.IsInRole("PreferredCustomer");

    var service = new ProductService();
    IEnumerable<Product> products = service.GetFeaturedProducts(isPreferredCustomer);
    this.ViewData["Products"] = products;

    return this.View();
}

Needs a reference to Domain layer, and DAL (as products are defined there). 

image
The answer as to why this was failing to compile on line 12 becomes clear when you use the type explicitly

image

Ahh, it is Product. Need a reference to System.Data.Entity (EF4) for EntityObject which Product inherits from.

MVC5

As I couldn’t get the project to compile easily (MVC3) in VS2013, I created a new MVC5 and fitted in the code.

@using Ploeh.Samples.Mary.ECommerce.Data.Sql

<asp:Content ID="indexTitle" ContentPlaceHolderID="TitleContent" runat="server">
    Home Page
</asp:Content>

<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Featured Products</h2>
    <div>
        @foreach (var prod in (IEnumerable<Product>) ViewData["products"]){
            @prod.Name
            <br />
            @Html.Encode(prod.Name)
            <br />
            @prod.UnitPrice
            <br/>
            @Html.Encode(prod.UnitPrice.ToString("C"))
            <br/><br/>
        }
    </div>
</asp:Content>

and web.config

  <system.web>
    <authentication mode="None" />
    <compilation debug="true" targetFramework="4.5.1">
      <assemblies>
        <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
      </assemblies>
    </compilation>

to get a reference to System.Data.Entity.  Also had to make sure the connection string was pointing to .\SQLEXPRESS where I generated the database.

Evaluation

Did Mary succeed?  No.  It looks like the coveted layered application, but the code is tightly coupled

image
Dependency graph showing how the modules depend on each other.  The arrows point towards a module’s dependency

The UI is dependant on both the Domain and Data Access layers!  It seems the UI may bypass the Domain in certain cases.

Evaluating Composability

Is it possible to use each module in isolation?

What is we want to replace the UI with a WPF one? – yes because nothing depends on the UI

Want to replace the DAL with one for Azure Table Store – no because domain and UI depend on it

IEnumerable<Product> products = service.GetFeaturedProducts(isPreferredCustomer);
  • UI reference Product which is defined in the DAL
this.objectContext = new CommerceObjectContext();
  • Domain library – tightly coupled to the DAL
  • A public Product class belongs in the Domain Model
  • Preferred Customer code is in UI whereas it belongs in the Domain Model
  • ProductService in Domain relies on web.config (for EF) – should be impertively configurable by callers
  • View contains specific string formatting.. should be in underlying model

Rebuilding the Commerce Application

Outside-in technique.  Here that means starting from the UI.  Closely related to You Aint Gonna Need It YAGNI.

He wrote a lot of unit tests in writing this application, as uses TDD

UI - FeaturedProductsViewModel

image

Interfaces or Abstract classes? – Important part is that you program against some sort of abstraction

custom IControllerFactory which will create an instance of the concrete ProductRepository and supply it to the home controller’s ctor.

image
Success!

Composition Root

Push the burden of controlling the dependency into another class – a composition root at the top of the application.  Where the different modules of an application can be composed.

Data Access

Using a separate Product POCO in the domain compared with auto generated Product in the DAL.  Aneimic model.

image
How dependencies are being connected

  • Injects SqlProductRepository into a new instance on HomeController
  • Index creates a new ProductService passing SqlProductRepository and invoking GetFeaturedProducts

image
Domain library has no dependencies!

  • Can we replace the WebUI with a WPF one.  Yes.  Nothing is dependant on it
  • Can we replace the Data Access library.  Yes.  It is loaded with late binding and the type is defined in web.config.

image
Late binding cannot find the DAL type – this can be solved by adding a reference from the UI to SQL layer.  Defeats the object (I think) though!  Ahh  - http://www.manning-sandbox.com/thread.jspa?threadID=47901  so the point here was to show they are separate.  Copy in the dll and all will be well.  No direct references so everything is separate.

Domain Unit Tests

image
For fun am going to explore the tests he wrote while developing this application.  Split tests into

  • ProductTest
    • Test both properties are writeable
    • Test try and false for ApplyDiscountFor
  • DiscountProductTest
    • Test null name will throw and properties match ctor args
  • ProductServiceTest

Uses AutoFixture https://github.com/AutoFixture/AutoFixture  which he is a author on.  Design to:

“minimize the 'Arrange' phase of your unit tests”

Also Moq and xUnit

Fixture automatically put in a value for both properties – Name and Unit Price.  Handy.

MVC Unit Tests

More difficult as lots has changed in MVC5.2 from 3.  Well, I got some of it compiling, however the tests are so granular, and I prefer BDD style. 

HomeControllerTests – there is one which is good ie ReturnVMWithCorrectProductsWhenUserIsPreferred..and not preferred.

Expanding the Sample Application

“Because one of the main purposes of DI is to manage complexity, we need a complex application to fully appreciated its power”

image
The UI will now only contain Views and bootstrap code: the Composition Root.  Contains only the bare minimum of code after which it delegates all other work to testable modules. A Humble Object.

The 4ComplexCommerce code is really complex! On to chapter 3.

| | # 
# Thursday, 12 June 2014

After a very interesting discussion at the Brighton Alt.NET meeting, and some follow up blog posts, I thought I’d explore why to use DI, then use it in my personal project to see if it does help.

This is a follow up to an interesting discussion the other night at the Brighton Alt.NET group on: “when is a project big enough to warrant using DI”

http://flat9.wordpress.com/2014/06/04/when-should-i-use-dependency-injection/

http://www.artisancode.co.uk/2014/06/appropriate-dependency-injection/

http://blog.ploeh.dk/2014/06/03/compile-time-lifetime-matching/

Interesting quote from Mark Seeman who wrote the book on DI in .NET: http://www.manning.com/seemann/

“Since I wrote the article on when to use a DI Container, I've only strengthened my preference for Poor Man's DI. Unless I'm writing a very complex code base that could benefit from Convention over Configuration, I don't use a DI Container, but since I explicitly architect my systems to be non-complex these days, I haven't used a DI Container in production code for more than 1½ years.”

My initial concerns are:

  • Complexity
  • Harder to navigate through the code

What I’m hoping may happen is:

  • Less code
  • Greater testability
  • Less complex systems

What is Dependency Injection

“Dependency injection is a software design pattern that implements inversion of control and allows a program design to follow the dependency inversion principle” Wikipedia

“Dependency injection means giving an object its instance variables.” James Shore

Dependency Injection (DI) is the proper way to write loosely coupled code when using Object-Oriented Design.” Mark Seemann

Pluralsight – John Sonmez course

http://pluralsight.com/training/Courses/TableOfContents/inversion-of-control

  • Dependency Inversion Principle – (DIP)
  • Inversion of Control – a pattern
  • DI - Implementation of IoC to invert dependencies
  • IoC Container – a framework

3rd module.. a quick demo on DI.. using types before they are made to help drive out… like TDD.

google TDD IoC DI C#?

Rob Conery

http://tekpub.com/blogs/tekpub-free-bin/7964835-concepts-1-dependency-injection-and-inversion-of-control

“You’ve got to be kidding me!”

ie why should we use this

Pluralsight – Jeremy Clark

http://pluralsight.com/training/Courses/TableOfContents/dependency-injection-on-ramp

| | # 

http://www.manning.com/seemann/

“I think Dependency Injection is like sauce béarnaise.  It’s assumed to be difficult and so few employ it”

DI is a set of software design principles and patterns that enable us to develop loosely coupled code

http://blog.ploeh.dk/2014/06/10/pure-di/ – an updated article on Constructor Based DI

Overview

2.5 years it took Mark to write this book.  It is concise, yet deep.  I’ve done an hours overview of the book, and looked at the source code (which doesn’t compile nicely in VS2013 but am sure will be ok).  It looks like a book which is much more than an DI book, and covers ‘good code’.

A DI Tasting Menu – 1.1 Writing Maintainable Code

DI may seem like a rather backward way of coding – there is much FUD (Fear, Uncertainty and Doubt) involved.  We must learn about the purpose of DI:

Writing Maintainable Code

Ultimately the purpose of programming is to deliver working software as efficiently as possible

You’ll find yourself maintaining and extending code

One of the ways to make maintainable code is through loose coupling

  • Deliver working software efficiently
  • Write maintainable code
  • Loose coupling (makes code extensible which makes it maintainable)
  • DI enables loose coupling

Hairdryers and Plugs

Through the use of sockets and plugs – a hair dryer can be loosely coupled to the wall outlet

  • Replace 1 end without changing the other
  • Liskov Substitution Principle – replace one implementation of an interface with another without breaking client or implementation
  • If unplug from wall, neither should break down.  “Null Object design pattern”

UPS

Way of intercepting one implementation with another of the same interface is known as the Decorator design pattern

Power Strip

Composite design pattern

Power Adapter

Adapter design pattern – match 2 related yet separate interfaces

Hello DI

In c:\dev\test\hellodi  page 46

class Program {
    static void Main(string[] args) {
        IMessageWriter writer = new ConsoleMessageWriter();
        var salutation = new Salutation(writer);
        salutation.Exclaim();
    }
}

public interface IMessageWriter {
    void Write(string message);
}

public class ConsoleMessageWriter : IMessageWriter {
    public void Write(string message) {
        Console.WriteLine(message);
    }
}

public class Salutation {
    private readonly IMessageWriter writer;

    public Salutation(IMessageWriter writer) {
        if (writer == null) {
            throw new ArgumentNullException("writer");
        }

        this.writer = writer;
    }

    public void Exclaim() {
        this.writer.Write("Hello DI!");
    }
}

2014-07-08 07.46.36

The Salutation class depends on a custom interface called IMessageWriter, and it requests an instance of it through it’s constructor.

The ConsoleMessageWriter class wraps the BCL Console class.  This is a simple application of the Adapter pattern as we are getting 1 Interface to work with another.

“You may be wondering about the benefit of replacing a single line of code with two
classes and an interface with a total line count of 11, and rightly so. There are several
benefits to be harvested from doing this.”

“In this example, DI adds an overhead of 1,100%, but, as complexity increases from one line of code to tens of thousands, this overhead diminishes and all but disappears.”

Benefits Gained from Loose Coupling

  • Late binding
    • Services can be swapped with other services
    • Valuable in standard software but perhaps less so in enterprise where runtime env is well defined
  • Extensibility
    • Code be be extended and reused in ways not planned for
  • Parallel Dev
    • Code be be dev’d in parallel
    • Valuable in large complex applications
  • Maintainability
    • Classes with clearly defined responsibilities are easier to maintain
  • Testability
    • Classes can be tested

Late Binding

static void Main(string[] args) {
    //IMessageWriter writer = new ConsoleMessageWriter();

    // Late binding - using reflection to create instance of IMessageWriter
    // without knowing concrete type at compile time
    var typeName = ConfigurationManager.AppSettings["messageWriter"];
    var type = Type.GetType(typeName, true);
    var writer = (IMessageWriter) Activator.CreateInstance(type);
        
    var salutation = new Salutation(writer);
    salutation.Exclaim();
}

Extensibility

Want to add security by only allowing authenticated users to write messages.  So can add the feature without changing any of the existing features.

Decorator - way of intercepting one implementation with another of the same interface

Decorate the old ConsoleMessageWriter instance with the new SecureMessageWriter class.  The salutation class is unmodified because it only consumes the IMessageWriter interface

// Decorator - way of intercepting one implementation
// with another of the same interface
public class SecureMessageWriter : IMessageWriter
{
    private readonly IMessageWriter writer;
       
    public SecureMessageWriter(IMessageWriter writer){
        if (writer == null) {
            throw new ArgumentNullException("writer");
        }
        this.writer = writer;
    }

    public void Write(string message){
        if (Thread.CurrentPrincipal.Identity.IsAuthenticated){
            this.writer.Write(message);
        }
    }
}

and call it differently

IMessageWriter writer = new SecureMessageWriter(new ConsoleMessageWriter());
var salutation = new Salutation(writer);
salutation.Exclaim();

2014-07-08 07.46.50

Loose coupling enables you to write code which is open for extensibility but closed for modification.  Open/Closed principle.  Only place where you need to modify the code is at the app’s entry point – we call this the composition root

Parallel Development

SecureMessageWriter and ConsoleMessageWriter don’t depend on each other so could be dev’d in parallel.  All that is needed is a common interface

Maintainability

As the responsibility of each class becomes clearly defined and constrained, maintenance becomes easier.

Single Responsibility Principle – each class should have only a single responsibility

Adding new features becomes simpler because it’s clear where changes should be made.  More often than not, we don’t even need to change existing code, but can add new classes, and recompose the app.  This is Open/Closed Principle again

Testability

Test Doubles – implementations of dependencies that act as stand-ins for real or intended implementations

  • Stubs
  • Mocks
  • Fakes

Ctrl U L – Run all unit tests in sln (R#) – and auto display window
Ctrl U D – Debug unit test
Ctrl U R – Run unit test(s)

public class SalutationTests {
    [Fact]
    public void InjectedMessageWriter_Exclaim_WriteCorrectMessage() {
        var writerMock = new Mock<IMessageWriter>();
        var sut = new Salutation(writerMock.Object);
            
        sut.Exclaim();

        // Verify Salutation.Exclaim method has passed correct message to injected
        // Writer by calling the Write method
        writerMock.Verify(w => w.Write("Hello DI!"));
    }
}

Interesting tests for his SecureMessageWriter on identity

Seams

We have a seam between ConsoleMessageWriter and Salutation

Stable Dependencies

  • Class or module already exists
  • Expect that new versions won’t contain breaking changes
  • Never expect to have to replace the class or module

Most types in the BCL as stable.  DI containers.  Specialised libraries. 

Volatile Dependencies

Introducing seams is extra work

A dependency should be considered volatile if any of the following are true:

  • Set up and configure a runtime environment eg a db.  We hide the db behind a seam, so can replace it by automated unit tests.  Message Queues, web services, file system
  • Dependency doesn’t exist yet
  • Dependency isn’t installed on all machines eg expensive 3rd party library
  • Dependency contains nondeterministic behaviour eg random numbers, date and time

DI Scope

We break up responsibilities into different classes.  One responsibility we take away from classes is the task of creating dependencies.

SRP – classes should only deal with their given area of responsibility without concerning themselves with how the dependencies are created

Object Composition

This is often the foremost motivation for introducing DI.

image

Modules can be composed into applications.  Only aspect discussed in Martin Fowler’s original article in 2004 (IoC and DI pattern)

Lifetime Management

What is objects want to share an instance of another object eg a db connection

Interception

Can modify a dependency before passing onto the class consuming them eg SecureMessageWriter above.  Example of decorator pattern.  This is moving along towards Aspect-Oriented Programming.

With interception we can apply Cross-Cutting concerns eg logging, auditing, access control, validation etc..

DI in 3D

  • Object composition (DI started out as a series of patterns aimed at solving this)
  • Object lifetime
  • Interception

Summary

DI is the best way to enable loose coupling – an important part of maintainable code

The benefits we can reap from loose coupling aren’t immediately apparent – they become visible over time as the complexity of the code base grows.

DI must be pervasive.  You can’t easily retrofit loose coupling onto an existing codebase

| | #