Sunday, July 4, 2010

Push API vs Pull API

I have found that Pull APIs are much harder to implement than Push APIs, but often the Pull API is much easier to use.

First I shall show an example of each, suppose I want an API for generating the numbers from 1 to 100.

As a Pull API I get the following.

public class RangePull {
    private int i;

    public RangePull() {
        i = 1;
    }

    public boolean hasNext() {
        return i <= 100;
    }

    public Integer next() {
        int out = i;
        i++;
        return out;
    }

    public static void main(String[] args) {
        RangePull r = new RangePull();
        while (r.hasNext()) {
            Integer i = r.next();
            // do something with i
            System.out.println(i);
        }
    }
}
as a Push API I get the following.
public class RangePush {
    public interface Visitor {
        void accept(int i);
    }

    public void visit(Visitor v) {
        for (int i = 1; i <= 100; i++) {
            v.accept(i);
        }
    }

    public static void main(String[] args) {
        RangePush r = new RangePush();
        r.visit(new Visitor() {
            @Override
            public void accept(int i) {
                // do something with i
                System.out.println(i);
            }
        });
    }
}

The push version is smaller, and in some ways simpler, but the control is inverted so it is not as versatile.

For example, only the pull version can be used to do a side by side comparison of the range generator results, since two of them would be iterating at the same time.

It is also trivial to turn a Pull API into a Push API, by just looping over the result generator and calling back to the visitor.

I have found that the complexity of changing a Push API into a Pull API is braking up the algorithm at the result emitting step, which often requires it to be re-worked as a state-machine. This is especially challenging where the algorithm is recursive.

No comments:

Post a Comment