On Sunday, 7 December 2014 at 13:47:09 UTC, Dicebot wrote:
However I was not speaking about plain procedural/imperative paradigm as better alternative but functional and generic ones. First one helps with eliminating state in general. Second one allows to use the very same mocks in much more light-weight way because no runtime binding is necessary - no dependency injection stuff and unnecessary interfaces, just using stub policy is enough.

To give some examples from personal experience of what frustrates me in typical OOP testing approach:

Imagine we have a simple cache class that internally communicates with external dht:

class Cache
{
    private DhtClient client;
    this(string addr) { this.client = new DhtClient(addr); }
}

Now we want to test it which implies adding mock client. Canonical way do it is by dependency injection and interface:

class Cache
{
    private IDhtClient client;
    this(IDhtClient client) { this.client = client; }
}

And know what? This just plain sucks. Not only you are now forced to modify yoru application code in many places to just comply to test-related changes that don't help actual app. You also introduce unnecessary interface indirection potentially killing inlining opportunities in the process.

Same stuff with policy approach:

class CacheT(DhtClient)
{
    static assert (isDhtClient!DhtClient);

    private DhtClient client;
    this(string addr) { this.client = new DhtClient(addr); }
}

alias Cache = CacheT!DhtClient;

Effectively the same code as sample 1 and makes no difference for rest of the application. And how would I test it?

alias TestCache = CacheT!StubDhtClient;

No changes to application, no extra indirections, same effective testing coverage. Much better.

And, of course, any utility functions that contain complex logic are better moved to free functions so that those can be tested with no relation to other code at all.

Reply via email to