Template Method or Dependency Injection?

Mystical

Dependency Injection used was always something very mystical to me. Until I learned what it’s really about.

I’d like to share this revelation with you. So let’s take an easy problem and solve it in couple of different ways.

Cowboy FizzBuzz

The problem is the well-known FizzBuzz Kata. This is the simplest code that makes it work:

public class FizzBuzzCowBoy {
    public static void main(final String... args) {
        for (int i = 1; i <= 100; i++) {
            if (i % 15 == 0) {
                System.out.println("FizzBuzz");
            } else if (i % 5 == 0) {
                System.out.println("Buzz");
            } else if (i % 3 == 0) {
                System.out.println("Fizz");
            } else {
                System.out.println(i);
            }
        }
    }
}

What’s wrong with this code? First of all, it’s very difficult to test.

Then, it’s unnecessarily difficult to make certain changes:

  • Collect 5 lines and print them in a separate Thread
  • Print the FizzBuzz of the first 20 Fibonacci number.
  • Or you could emit Fizz when the number is divisible with 3 or contains the digit 3

Suppose this code plays an important role in a lean startup. You need to make certain statistics whether the email FizzBuzz or the Standard out FizzBuzz is more profitable. So you want to do some A/B testing. Well, that’ll hurt.

Template FizzBuzz

The Template Method Pattern is a straightforward way to decompose this cowboy code into smaller pieces.

This is the template method:


public class FizzBuzzTemplate {
    
    public void doFizzBuzz() {
        getFizzBuzzNumbers.forEach(num -> {
            final String msg = getFizzBuzzText(num);
            printFizzBuzz(msg);
        });
    }
    //...
}

The template above needs three operations:

  • getFizzBuzzNumbers
  • getFizzBuzzText
  • printFizzBuzz

You can find the operations in the same class:


public class FizzBuzzTemplate {
    //...
    protected Stream getFizzBuzzNumbers() {
        return IntStream.rangeClosed(1, 100).boxed();
    }

    protected void printFizzBuzz(final String msg) {
        System.out.println(msg);
    }

    protected String getFizzBuzzText(final int num) {
        if (isDividable(num, 15)) {
            return "FizzBuzz";
        }
        if (isDividable(num, 5)) {
            return "Buzz";
        }
        if (isDividable(num, 3)) {
            return "Fizz";
        }
        return Integer.toString(num);
    }

    private boolean isDividable(final int num, final int div) {
        return num % div == 0;
    }
}

Invoking it

Finally, this is how we can invoke it from a main method:

public class Main {
    public static void main(final String[] args) {
        final FizzBuzzTemplate fizzBuzz = new FizzBuzzTemplate();
        fizzBuzz.doFizzBuzz();
    }
}

A/B testing is a bit coarse-grained. We can use a system property or whatever so we run either FizzBuzzTemplateA or FizzBuzzTemplateB.

Testing the template with test subclass

Now that we have well-factored methods, it’s easy to create a new FizzBuzz solution. Well, actually I already created one when I tested the template method:

public class TestFizzBuzzTemplateWithTestClass {
    // ... test methods that rely on the testing subclass
    private static class TestFizzBuzz extends FizzBuzzTemplate {

        private final List printed = new ArrayList();

        @Override
        protected Stream getFizzBuzzNumbers() {
            return IntStream.of(1, 2, 3).boxed();
        }

        @Override
        protected void printFizzBuzz(final String msg) {
            printed.add(msg);
        }

        @Override
        protected String getFizzBuzzText(final int num) {
            return "TEST";
        }
    }

Based on  JUnit recipes, this is how we should test template methods. See, this is a case when testing makes your code more flexible: we didn’t only test all the parts in isolation but we made sure that we can create new kind of FizzBuzz-es if we want to.

Unfortunately, it takes lots of time to write these test-subclasses. It’s also difficult to read these test. What now?

Partial Mocking

Alternatively, you can test the code with partial mocking, like Mockito.spy:

public class TestFizzBuzzTemplateWithSpy {

    private FizzBuzzTemplate sut;
    private Stream oneTwoThree;

    @BeforeMethod
    public void setUp() {
        final FizzBuzzTemplate template = new FizzBuzzTemplate();
        sut = spy(template);
        oneTwoThree = IntStream.of(1, 2, 3).boxed();
        doReturn(oneTwoThree).when(sut).getFizzBuzzNumbers();
        doNothing().when(sut).printFizzBuzz(anyString());
    }

    @Test
    public void testStreamRetrieved() {
        // WHEN
        sut.doFizzBuzz();

        // THEN
        verify(sut).getFizzBuzzNumbers();
    }
    // ... more test methods
}

Are we happy? No, not really. According to this SO page and to Mockito.spy documentation, partial mocking is a bad practice, recommended only for legacy code. You don’t use this with TDD, they say.

Dependency injection

We can beautify this code even further. We can create method objects for the individual operators.

The parts

One for the numbers we want to process:

public class FizzBuzzNumberProvider {
    public Stream getFizzBuzzNumbers() {
        return IntStream.rangeClosed(1, 100).boxed();
    }
}

Another for deciding what to print:

public class FizzBuzzTextProvider {

    public String getFizzBuzzText(final Integer num) {
        if (isDividable(num, 15)) {
            return "FizzBuzz";
        }
        if (isDividable(num, 5)) {
            return "Buzz";
        }
        if (isDividable(num, 3)) {
            return "Fizz";
        }
        return num.toString();
    }

    private boolean isDividable(final int num, final int div) {
        return num % div == 0;
    }
}

And here is a class for printing the fizzbuzz text:

public class FizzBuzzPrinter {
    public void printFizzBuzz(final String msg) {
        System.out.println(msg);
    }
}

Indeed, there’s a Method Object for printing FizzBuzz to the standard output. Isn’t it this overkill? It depends on what your crystal ball tells you about upcoming requirements how far you want to go for clean code.

Bringing the pieces together

I used constructor injection for this case.

Constructor injection means that an object receives its collaborators in a constructor and stores them. Later it uses them when needed:

public class FizzBuzzManualInjection {

    private final FizzBuzzNumberProvider numberProvider;
    private final FizzBuzzTextProvider textProvider;
    private final FizzBuzzPrinter printer;

    public FizzBuzzManualInjection(final FizzBuzzNumberProvider numberProvider,
        final FizzBuzzTextProvider textProvider,
        final FizzBuzzPrinter printer) {
        this.numberProvider = numberProvider;
        this.textProvider = textProvider;
        this.printer = printer;
    }

    public void doFizzBuzz() {
        numberProvider.getFizzBuzzNumbers().forEach(num -> {
            final String msg = textProvider.getFizzBuzzText(num);
            printer.printFizzBuzz(msg);
        });
    }
}

And this is how they’re wired together in a main method:

public class Main {
    public static void main(final String[] args) {
        final FizzBuzzNumberProvider numberProvider = new FizzBuzzNumberProvider();
        final FizzBuzzTextProvider textProvider = new FizzBuzzTextProvider();
        final FizzBuzzPrinter printer = new FizzBuzzPrinter();
        final FizzBuzzManualInjection fizzBuzz = new FizzBuzzManualInjection(numberProvider, textProvider, printer);
        fizzBuzz.doFizzBuzz();
    }
}

Testing it is quite easy now: you can mock out the collaborators.

Invoking it

It’s easy to add different FizzBuzz implementations for A/B testing: We need some system property that helps us decide which particular implementation we need to inject.

Wrapping up

In this post we could see that the Template Method is a good alternative to Dependency Injection.

Well, good for the FizzBuzz kata. What about real world examples then? Why are there lots of frameworks for Dependency Injection, and only a few for Template Method? Let’s see:

  • Template Method won’t create separate code for configuration. That’s a must in complicated projects.
  • If you need to flexibly combine the pieces, then you need Dependency Injection.
  • If you have heavy-weight, general-purpose dependencies, like an ORM or a Transaction Manager, then Template Method just won’t fit.

Wrapping up, really

You can use Template Method for fairly simple cases. For Big Things (TM) you need Dependency Injection. Later we’re gonna explore that.


Where you can find the code

You can find the code on github: cowboy, template method and manual dependency injection.

Advertisements

About tamasrev

A software developer, specialized in Java, addressing himself as generalist. A proud daddy.
This entry was posted in java, programming and tagged , , , . Bookmark the permalink.

One Response to Template Method or Dependency Injection?

  1. Pingback: Lessons learned from the IoC framework comparison. | tamasrev

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s