Tuesday, July 23, 2013

Factories for Dummies

Today I was working on swapping a single threaded implementation of a piece of code to multithreaded version. Apart from concurrency issues, one exercise I've gone through was to use factories. Factories naturally facilitate the way we inject dependencies into our business logic. In order to make the previous statement more clear, lets go back to our awesome calculator service. It exposes an 'add' API. Let's start with a bad abstraction,

public class AwesomeCalculator {

    public long add(long a, long b) {
        Adder adder = new SimpleAdder();
        return adder.add(a, b);
    }
}

public Interface Adder {
    long add(long a, long b);
}

public SimpleAdder implements Adder {

    public long add(long a, long b) {
        //do something simple and stupid
    }
}

The client would do something like,

public class AwesomeCalculatorClient {
    private final AwesomeCalculator calculator = new AwesomeCalculator();

    public void foo() {
        calculator.add(1l, 2l);
    }
}

Now lets say we've got enlightenment and want to make our AwesomeCalculator use a better Adder implementation. The first place we've to update is the step inside add() method in AwesomeCalculator. The programmer who wants to do this change would want us to rot in hell for the poor design. It is just a one line change in this example, but think about a real piece of software where we'd end up changing all over the business logic wherever we've had assumptions about SimpleAdder. More importantly, it is almost impossible to mock out Adder in our unit tests.This is a total nightmare. Lets call our friend 'factory' to the rescue.

A decent version of our AwesomeCalculator would look something like,

public class AwesomeCalculator {

    private final AdderFactory adderFactory;

    public AwesomeCalculator(AdderFactory factory) {
        this.adderFactory = factory;         
    }

    public long add(long a, long b) {
        Adder adder = adderFactory.getAdder();
        return adder.add(a, b);
    }
}

public class AdderFactory {

    public Adder getAdder() {
        return new BetterAdder();
    }
}

With this version, we could modify the factory to produce a better Adder implementaion thus moving the change out of our AwesomeCalculator. To make the code more pretty, we can go one step further. Lets try one more revision.

public interface AdderFactory {
    public Adder getAdder();
}

public class StupidAdderFactory implements AdderFactory {

    @Override
    public Adder getAdder() {
        return new StupidAdder();
    }
}

public class BetterAdderFactory implements AdderFactory {

    @Override
    public Adder getAdder() {
        return new BetterAdder();
    }
}

This is even better, since we've completely moved the change to the client side. If the client wants a new implementation of Adder to be used, we just need to create a new factory which is capable of generating that Adder and let the client pass the new factory to AwesomeCalculator. Sweet isn't it ?

What have we done ?
  • Separated the concerns nicely.
  • Made the code constructor injectible. This will be super handy if we use framework like Spring which does inversion of control.
  • We can write clean unit tests by easily mocking out dependencies.
Ciao,
Surya.

Friday, July 19, 2013

Iterators are your friends!

We all know that Iterators nicely decouple the container from the implementation details of traversing the container. Today I was optimizing an existing piece of code and had to work through the details this post talks about.

More about Iterators here. I’m going to talk about  a specific advantage of using iterators – improved testability of the code.

Let’s consider this simple class AwesomeParser. It keeps an InputStream and reads tokens from the stream. The stream has a header which contains the number of tokens in the stream.

class AwesomeParser {
    private final InputStream fileStream;
    private int numberOfTokens;
    private int tokensRead;

    public AwesomeParser(fileInputStream) {
        fileStream = fileInputStream;       
        numberOfTokens = 0;
        tokensRead = 0;
    }

    public void readFileHeader() {
        numberOfTokens = extractTokensCountFromFileHeader();
    }

    public Token read() {
        Token token = parseTokenFromFile();
        tokensRead++;
        return token;
    }

    public boolean hasMoreTokens() {
        return tokensRead < numberOfTokens;
    }
}

A sample consumer of this class would look something like,

class Consumer {
    private  final AwesomeParser parser;
    
    public Consumer(AwesomeParser parser) {
        this.parser = parser;
    }

    public void fooBar() {
        AwesomeParser parser = new AwesomeParser(fooStream);
        parser.readFileHeader();
        while (parser.hasMoreTokens()) {
            parser.read();
        }
    }
}

Looks like a nice abstraction. Now let’s see how the unit tests for our consumer would look like.
  • We mock out the parser.
  • Now the only way to test fooBar() is to make hasMoreToken() return different values for different calls. For e.g,
when(parser.hasMoreTokens()).thenReturn(true).thenReturn(true).thenReturn(false);
when (parser.read()).thenReturn(dummyToken);
Wait a second, what would happen if I modify fooBar() to something like,

public void fooBar() {
    AwesomeParser parser = new AwesomeParser(fooStream);
    parser.readFileHeader();
    if (parser.hasMoreTokens()) {
        log(“Woohoo work to do”);
    }
    while (parser.hasMoreTokens()) {
        parser.read();
    }
}

We have broken our assumptions about hasMoreTokens() in fooBar(). The unit tests will start failing one after another as they are so brittle. So, what do we do now? Iterators to the rescue :)

Let’s redesign our AwesomeParser.

class AwesomeParser implements Iterable {
    private final InputStream fileStream;
    private int numberOfTokens;
    private int tokensRead;

    public AwesomeParser(fileInputStream) {
        fileStream = fileInputStream;       
        numberOfTokens = 0;
        tokensRead = 0;
    }

    public void readFileHeader() {
        numberOfTokens = extractTokensCountFromFileHeader();
    }

    private Token read() {
        Token token = parseTokenFromFile();
        tokensRead++;
        return token;
    }

    private boolean hasMoreTokens() {
        return tokensRead < numberOfTokens;
    }

    /*  Warning: Usually you don't keep the traversal state of a container
     *  outside the iterator. The code will miserably fail if some one
     *  calls iterator() on AwesomeParser multiple times, since we have 
     *  one single underlying stream. You can always create a deep copy of
     *  it in the constructor of AwesomeParserIterator.
     */
    public Iterator iterator() {
        return new AwesomeParserIterator();
    }
    
    class AwesomeParserIterator implements Iterator {

        @Override
        public boolean hasNext() {
            return hasMoreTokens();
        }

        @Override
        public Token next() {
            return read();
        }

        @Override
        public void remove() {
            // never mind
        }
    }
}

Let’s try this abstraction. If we have to unit test the consumer of our new design,
List <Token> tokens = new ArrayList<>();
//populate tokens
Iterator <Token> mockIterator = tokens.iterator();
when (AwesomeParser.iterator()).thenReturn(mockIterator);
Essentially we have covered the underlying parser’s stream with a simple dummy list of tokens and faked the iterator returned by our AwesomeParser with an iterator to our dummy list.

What have we achieved?

The unit tests are no longer brittle and would just test the behavior of the consumer of AwesomeParser and have no assumption about how we traverse. Neat isn’t it?

Ciao,
Surya.