Simulators or not?

Posted by: Eric Gunnersons C# Compendium, on 04 Oct 2014 | View original | Bookmarked: 0 time(s)

Ive been spending some time playing with Cockburns hexagonal architecture  (aka ports and adapters), and the extension I learned from Arlo, simulators. Ive found it to be quite useful.

I was writing some code, and I ended up at a place I didnt expect. Heres the situation. I have the following external class (ie port).

class EntityLoader
{
    public EntityLoader(string connectionInformation) {}

    public IEnumerable<Entity> Fetch(EntithyType itemType) { }
}

I need to use this class to some different kinds of entities, do some light massaging of data, and then query against the data. Ill start figuring out what the adapter should be, and Ill define it by the question that I want to ask it:

interface IPeopleStore
{
    IEnumerable<Employee> GetAllEmployeesForManager(Employee employee);
}

Now that I have the interface, I can use TDD to write a simulator that implements the interface:

class PeopleStoreSimulator: IPeopleStore
{
    public IEnumerable<Employee> GetAllEmployeesForManager(Employee employee) { ...}
}

The implementation for this will be pretty simple; I just add a way to get the list of employees for a manager into the simulator. Now I have unblocked my team members; they can code against the interface and use the simulator for their testing while I figure out how to write the version that talks to the EntityLoader.

And this is where it got interesting

One of the cool things about port/simulator/adapter is that you can write one set of tests and run them against all of the adapters, including the simulator. This verifies that the simulator and the real adapter have the same behavior.

Thats going to be problematic because the interface for Entity doesnt give me any way to put data into it, so I cant use the simulator tests on it. It will also do two things; fetch the data from the entity and implement the GetAllEmployeesForManager() method, and because I cant put data into it, I dont have a way to write a test for the method().

It also violates one of my guidelines, which is to separate the fetching of data and the processing of data whenever possible. The problem is that we have the lookup method logic in a class that we cant test ie so we cant adapt the data into what we need. Thats a good sign that adapter may not be a good choice here. How about a simpler approach, such as wrapper?

Lets start with the lookup logic. Well make PeopleStore a simple container class, and that will make the lookup logic trivial to test.

class PeopleStore
{
    IList<Employee> m_employees;
    IList<Employee> m_managers;

    public PeopleStore(IList<Employee> employees, IList<Employee> managers)
    {
        m_employees = employees;
        m_managers = managers;
    }
   
    public IEnumerable<Employee> GetAllEmployeesForManager(Employee employee)
    {
       
    }
}

Now, Ill work on the wrapper level. After going with an interface, I end up switching to an abstract class, because there is a lot of shared code.

abstract class EntityStoreBase
{
    protected IEnumerable<Employee> m_employees;
    protected IEnumerable<Employee> m_managers;

    IEnumerable<Employee> FetchEmployees() { return m_employees; }
    IEnumerable<Employee> FetchManagers() { return m_managers; }
}

class EntityStoreSimulator: EntityStoreBase
{
    public EntityStoreSimulator(IEnumerable<Employee> employees, IEnumerable<Employee> managers)
    {
        m_employees = employees;
        m_managers = managers;
    }
}

class EntityStore : EntityStoreBase
{
    public EntityStore(string connectionInformation)
    {
        EntityLoader loader = new EntityLoader(connectionInformation);

        m_employees = loader.Fetch(EntityType.Employee)
                            .Select(entity => new Employee(entity));
        m_managers = loader.Fetch(EntityType.Manager)
                            .Select(entity => new Employee(entity));
    }
}

That seems to work fine. Now I need a way to create the PeopleStore appropriately. How about a factory class?

public static class EntityStoreFactory
{
    public static EntityStoreBase Create(IEnumerable<Employee> employees, IEnumerable<Employee> managers)
    {
        return new EntityStoreSimulator(employees, managers);
    }

    public static EntityStoreBase Create(string connectionInformation)
    {
        return new EntityStore(connectionInformation);
    }
}

This feels close; its easy to create the right accessor and the EntityLoader class is fully encapsulated from the rest of the system. But looking through the code, Im using 4 classes just for the entity-side part, and the code there is either not testable (the code to fetch the employees from the EntityLoader), or trivial. Is there a simpler solution? I think so

public static class PeopleStoreFactory
{
    public static PeopleStore Create(IEnumerable<Employee> employees, IEnumerable<Employee> managers)
    {
        return new PeopleStore(employees, managers);
    }

    public static PeopleStore Create(string connectionInformation)
    {
        EntityLoader loader = new EntityLoader(connectionInformation);

        var employees = loader.Fetch(EntityType.Employee)
                            .Select(entity => new Employee(entity));
        var managers = loader.Fetch(EntityType.Manager)
                            .Select(entity => new Employee(entity));

        return Create(employees, managers);
    }
}

This is where I ended up, and I think its a good place to be. I have a class that is well-adapted to what the program needs (the PeopleStore), and very simple ways to create it (PeopleStoreFactory).

Thinking at the meta level, I think the issue with the initial design was the read-only nature of the EntityStore; thats what made the additional code untestable. So, as fond as I am of port/adapter/simulator, there are situations where a simple factory method is a better choice.

Category: Refactor | Other Posts: View all posts by this blogger | Report as irrelevant | View bloggers stats | Views: 1065 | Hits: 10

Similar Posts

  • Unit test success using Ports, Adapters, & Simulatorskata walkthrough more
  • Unit Test Success using Ports, Adapters, and Simulators more
  • Unit Test Web Code Without A Web Server Using HttpSimulator more
  • Color Blindness Simulator Now Available more

News Categories

.NET | Agile | Ajax | Architecture | ASP.NET | BizTalk | C# | Certification | Data | DataGrid | DataSet | Debugger | DotNetNuke | Events | GridView | IIS | Indigo | JavaScript | Mobile | Mono | Patterns and Practices | Performance | Podcast | Refactor | Regex | Security | Sharepoint | Silverlight | Smart Client Applications | Software | SQL | VB.NET | Visual Studio | W3 | WCF | WinFx | WPF | WSE | XAML | XLinq | XML | XSD