Solving the switch statement

If you’ve read the age old refactoring book by Martin Fowler, you’d have come across his distaste for everything “if / switch”. There are some grounds to this, if you were to believe on some concept of SOLID principles, where

  • your class should have only a single responsibility
  • your class should be closed for modification and open to extension

There was a discussion this week on why a factory pattern might look ugly on a certain program that was being written and I came across the opportunity on how we can solve a very specific problem.

Given a request, a specific view(s) are created. The view(s) are created based on a certain context (rules).

Naturally the first iteration went to having a factory with switch statements that returns views based on rules.

So here, I have an example on how we can solve the switch statement problem using a known pattern similar to the abstract factory pattern (examples in c#).

namespace SolvingTheManagerProblem
{
public abstract class DataViewBase
{
}
public class FirstView : DataViewBase
{
}
public class SecondView : DataViewBase
{
}
}
view raw DataViewBase.cs hosted with ❤ by GitHub
using System.Collections.Generic;
using System.Linq;
namespace SolvingTheManagerProblem
{
public interface IProvideRules
{
IEnumerable<IRule> GetRules(DataViewBase view);
}
public abstract class DataViewFactory<T> : IProvideRules where T : class
{
public IEnumerable<IRule> GetRules(DataViewBase view)
{
var specificView = view as T;
if (specificView == null)
return Enumerable.Empty<IRule>();
return GetRulesFor(specificView);
}
protected abstract IEnumerable<IRule> GetRulesFor(T specificView);
}
public class FirstViewDataViewFactory : DataViewFactory<FirstView>
{
protected override IEnumerable<IRule> GetRulesFor(FirstView specificView)
{
yield return new DummyRule();
}
}
public class SecondViewDataViewFactory : DataViewFactory<SecondView>
{
protected override IEnumerable<IRule> GetRulesFor(SecondView specificView)
{
yield return new DummyRule();
yield return new AnotherDummyRule();
}
}
}
namespace SolvingTheManagerProblem
{
public interface IRule
{
}
public class DummyRule : IRule
{
}
public class AnotherDummyRule : IRule
{
}
}
view raw Rules.cs hosted with ❤ by GitHub
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
namespace SolvingTheManagerProblem
{
[TestFixture]
public class TestThings
{
[Test]
public void FirstViewShouldReturnJustOneRule()
{
var firstView = new FirstView();
var ruleProviders = new List<IProvideRules>
{
new FirstViewDataViewFactory(),
new SecondViewDataViewFactory()
};
var rulesForFirstView = ruleProviders.SelectMany(t => t.GetRules(firstView));
Assert.That(rulesForFirstView.Count(), Is.EqualTo(1));
}
[Test]
public void SecondViewShouldReturnTwoRules()
{
var secondView = new SecondView();
var ruleProviders = new List<IProvideRules>
{
new FirstViewDataViewFactory(),
new SecondViewDataViewFactory()
};
var rulesForSecondView = ruleProviders.Select(t => t.GetRules(secondView));
Assert.That(rulesForSecondView.Count(), Is.EqualTo(2));
}
}
}
view raw Test.cs hosted with ❤ by GitHub

I hope this pattern helps you in making better software.

MVVM everything

There is an age old saying in the field of software engineering: “abstraction, and abstraction”; abstraction / indirection is basically the “42” of computer science. So before you read on, let me tell you the case I am going to make, “abstract x“.

Recently I’ve been working on a legacy WCF web service that sits pretty low in the n-tier architecture. One of the things that strike me about this web service is that there is an object that is being returned, but the object contains other objects therefore creating a hierarchy of sorts. So in a normal world, you accept a request, you build a response and you return the response.

typical-CRUD

One of the problems you get this model is say, what happens when you want to expand a response child object?


public class Result
{
int ID { get; }
int Name { get; }
IRandomDetails ResponseDetail { get; }
}

public class Details : IRandomDetails
{
bool Success { get; }
string Message { get; }
}

First of all, the object is ridiculous, but for confidentiality reasons I can’t disclose any reasonable class. Say now I want to add to the details object a Severity() method? Why? Maybe it’s because there’s high cohesion and it naturally should belong to the class. However, I can’t simply add a new attribute or method to this class, because it may break the consumer. It is now what we class a published interface. One of the things you can do is to implement an extension class. You do not change the structure of the outgoing message but still maintain some illusion of cohesion.

internal static class IRandomDetailsExtension
{
public static int Severity(this IRandomDetails obj, string descriptiveValue)
{
//some logic here
}
}

But what’s the better approach? Why, whatever the answer to it … it must be indirection! I believe that whenever we’re presenting a published interface or object, it should always be abstracted away from any logic. In this case, the Result object (and any published interface / object) exist only as far as the surface of the web service. No internal class should reference the published interface directly, and we can / should clone a resulting interface to be passed through the business logic layer. Here, the similarity of MVVM really begins.

typical CRUD_2

We introduce a new layer of indirection that simply converts the published interface to an IFD (internal format document) to be processed through the business logic. In this, the IFD reflects many similar attributes to the ViewModel, as it acts like a binding model between logic and presentation (the published inteface). This way, we have complete freedom to change / modify the classes within the business domain without fear of it ever changing the structure of the published interface. There are some cost involved of course, like mapping process, extra objects and maintaining the mapping itself. I believe in most cases, the first two are fairly negligible in exchange for the benefits we receive. Thankfully, with helpful third party libraries like automapper, we can achieve the third feat with fair ease as well!

What do you think? Should I even mislead and claim MVVM to this? Or does it look a bit more like MVP, where the IFD is the view and the published interface should really be the presenter? Plausible but I think it probably requires its own design name.