Design patterns in real world use case scenarios – Service stub

The second pattern I would be presenting in my mini series of the patterns in real world is one of the main patterns used in Test Driven Development (TDD).

Service stub – decoupled business logic

To get a very detail explanation of what this pattern stands for check out the blog post of the person who ‘first documented’ it, Martin Fofler P of EAA: Service stub .

Problem – use case

Let’s imagine we have:

– a SomeManager class which has a LoadSomething method which reads data from sql server and that

– OtherType class which has a method which uses the LoadSomething method to get data on which he would imply some business process

That example coded could look like this:

using System.Collections.Generic;

 

namespace TestProject1

{

    public class SomeManager

    {

        public static ICollection<string> LoadSomething()

        {

            List<string> result = new List<string>();

            // read data from sql server

            // result.Add(…);

            return result;

        }

    }

 

    public class OtherType

    {

        public void PopulateSomething()

        {

            ICollection<string> collection= SomeManager.LoadSomething();

            foreach (string s in collection)

            {

                // do something with s

            }

        }

    }

}

 

The problems in this approach are:

  • to test OtherType.PopulateSomething() method I would have to create data rows in some SQL database which would be then read in SomeManager.LoadSomething() and then processed in PopulateSomething() method (which is to be tested). Imagine now that test dependency chain couple levels deep and you would come to the testing nightmare scenario where tests are very, very complexed and inter dependable.
  • if SomeManager.LoadSomething() is been developed in paralel with OtherType.PopulateSomething() there is a possibility that SomeManager won’t be finished on time when OtherType would need it to work on its functionality (e.g. DBAdmin’s a re too busy to create tables and rows needed)

Summarized: very hard dependency between the types is very inflexible design approach.

Why service stub?

Service stub in short is a pattern where we instead talking to the full type instance we talk to the interface representation of the type and that is exactlly what we need: to talk with abstracted form
of the DB  dependable type. If we refer the interface, ANY type implementing the interface could be used in our code. (Usually, this pattern goes together with some form of Dependency injection and service locator)

Rule of thumb

Use service stub if you have dependencies in your code to the parts of system which execution is expensive or dependable on some external information sources.

Problem solution example

Class diagram of the solution

SolutionDiagram

Diagram explanation

What are we testing? OtherType.PopulateSomething method. Not the SomeManager behavior (for which we would have have separate test).

Testing of PopulateSomething method means “test me the result of iteration for given set of data”

Knowing that, we could rewrite our starting example to extract the interface of the SomeManager type, like this

public interface ISomeManager

{

ICollection<string> LoadSomething();

}

 

And our manager would now just implement that interface on the same way it is implemented in starting example

 

public class SomeManager : ISomeManager

{

public ICollection<string> LoadSomething()

{

              List<string> result = new List<string>();

              // read data from sql server

              // result.Add(…);

              return result;

        }

}

 

Now when we have this done, we would alter the OtherType to contain the private field  of ISomeManager type , something like

 

public class OtherType

    {

        private readonly ISomeManager _someManager;

 

 

    }

 

Having this in place we can change the OtherType PopulateSomething method implementation to use the _someManager field instead of constructing the SomeManager instance, something like this:

        public void PopulateSomething()

        {

            ICollection<string> collection = _someManager.LoadSomething();

            foreach (string s in collection)

            {

                // do something with s

            }

        }

The code would compile , but we don’t have any code which would set that interface field value to a new SomeManager instance. To keep things decoupled we have to keep the instantiation of SomeManager type outside of the OtherType and one of the ways to do that is to use Dependency Injection – constructor type pattern, by defining constructor which accepts argument of ISomeManager type, something like this

        public OtherType (ISomeManager someManager)

        {

            _someManager = someManager;

        }

With this on place, we have now code which does:”Inside of OtherType.PopulateSomething method use a instance field of ISomeManager type which value someone outside of the OtherType would set”

Usage

Now with this approach I can make for my test purposes a mock object (in this example I would use static mock but dynamic is possible (and preferable) too) 

 

    internal class MockSomeManager : ISomeManager

    {

        public ICollection<string> LoadSomething()

        {

            List<string> result = new List<string>();

            result.Add(“1”);

            result.Add(“2”);

            result.Add(“3”);

            return result;

        }

    }

 

So my test method would look something like

 

        [TestMethod]

        public void TestMethod1()

        {

            OtherType other=new OtherType(new MockSomeManager());

            other.PopulateSomething();

        }

 

Notice that I have constructed the type which implements the ISomeManager interface and pass it to the constructor of the OtherType to use.

One small gotcha of the service stub pattern

The possible downside of this approach could be the fact that with original implementation in real world OtherType usage (TestMethod1 in this example) I would encapsulate the internals how PopulateSomething works:

        [TestMethod]

        public void TestMethod1()

        {

            OtherType other=new OtherType();

            other.PopulateSomething();

        }

That is a valid point, we do want to get flexibility, but not to loose encapsulation. 

To override this obstacle we would use “Poor man dependency injection” technique which would in our example add a new default constructor

        public OtherManager():this(new SomeManager())

        {

        }

That’s how even if the user would use the default (encapsulated) constructor the component would work on the way how it worked in original starting state and we would still have all the flexibility

Complete refactored code source

The from example now looks like:

public class OtherType

{

    private readonly ISomeManager _someManager;

 

    public OtherType(): this(new SomeManager())

    {

    }

 

    public OtherType(ISomeManager someManager)

    {

        _someManager = someManager;

    }

 

    public void PopulateSomething()

    {

        ICollection<string> collection = _someManager.LoadSomething();

        foreach (string s in collection)

        {

            // do something with s

        }

    }

}

Problem solved!

Posted on August 2, 2007, in Uncategorized. Bookmark the permalink. Leave a comment.

Leave a comment