Tag Archives: c#

Batching Data by Time or Count Using Reactive Extensions (Rx)

Motivation

The time-series database InfluxDB provides a HTTP API to write data. Data points (measurements) are inserted via a Line protocol, which allows batching of data by writing multiple points in one HTTP request.

While experimenting for a simple InfluxDB C++ client, I wanted to create an asynchronous fire-and-forget API, so that the data points can be sent over HTTP without blocking the instrumented C++ code. Several “readymade” options to implement concurrency in this scenario are available.

A simple PAIR of ZeroMQ sockets would do the job, but I’d have to implement batching separately. Thus, I turned my attention to a higher-level abstraction: Rx

Rx Window Operator

Quickly looking through the cross-language Reactive Extensions site, I found the right operator: Window.

This operator has luckily been implemented in RxCpp, thus I proceeded with the experiment.

Batching Design

Batching using Rx Winodw Operator

Rx Window Operator (CC BY 3.0 reactivex.io)1

The window operator takes an observable sequence of data and splits it into windows (batches) of observables. To batch requests, the observable windows of data are aggregated to a single value upon the last value from the windows (via other aggregating Rx operators).

A Toy Problem

To validate the approach, the following problem is set:

Given a stream of integers, append the integers into a series of strings, either every second, or every N integers

String appends with integer-to-string conversions in C++ will be done via the {fmt} library.

Batching in One Line of Code

A stream of numbers batched either by time or count:

auto values = rxcpp::observable<>::range(1, 1000'000)
    .window_with_time_or_count(std::chrono::seconds(1), 100'000);

Note, there is an almost one-to-one translation into a C# version:

var values = Observable.Range(1, 1000000)
               .Window(TimeSpan.FromSeconds(1), 100000);

This indicates the power of the Rx abstraction across languages. The Rx website provides just the right sorting of the documentation to be able to translate Rx code from one language to another.

Aggregating the Batches

In order to do something useful with the batched data, the Scan operator is used to gather the data in a string buffer, and after the last value has been received, the string buffer is assembled into a string and processed:

values.subscribe(
    [](rxcpp::observable<int> window) {
        // append the number to the buffer
        window.scan(
            std::make_shared<fmt::MemoryWriter>(),
            [](std::shared_ptr<fmt::MemoryWriter> const& w, int v)
        {
            *w << v;
            return w;
        })

        // what if the window is empty? Provide at least one empty value
        .start_with(std::make_shared<fmt::MemoryWriter>())

        // take the last value
        .last()

        // print something fancy
        .subscribe([](std::shared_ptr<fmt::MemoryWriter> const& w) {
            fmt::print(
                "Len: {} ({}...)\n",
                w->size(),
                w->str().substr(0, 42)
            );
        });            
    }
);

The Tale of Two Bugs

In the initial (non-TDD) spike, the batching seemed to work, however, something caught my attention (the code bites back):

[window 0] Create window
Count in window: 170306
Len: 910731 (123456789101112131415161718192021222324252...)

the window wasn’t capped at 100’000. This could have been either a misunderstanding or a bug, thus I formulated a hesitant issue #277. As it turned out, it indeed was a bug, which was then fixed in no time. However, the first bug has hidden another one: the spike implementation started to crash at the end: when all the windows were capped by count, and not by time, last window was empty, as all values fit exactly into 10 batches.

The Last operator rightly caused an exception due to an empty sequence. Obviously, there’s no last value in an empty sequence. Rubber Ducking and a hint from Kirk Shoop fixed the issue by utilizing the StartWith operator to guarantee, the sequence is never empty. An empty string buffer can be ignored easier downstream.

Active Object

The active object pattern was applied to implement a fire-and-forget asynchronous API. A Rx Subject to bridge between the function call and the “control-inverted” observable:

struct async_api {
    //...
    rxcpp::subjects::subject<line> subj;
    //...

    async_api(...)
    {
        auto incoming_requests = subj
            .get_observable()
            .map([](auto line) {
                return line.to_string();
            });

        incoming_requests
            .window_with_time_or_count(
                window_max_ms,
                window_max_lines,
                // schedule window caps on a new thread
                rxcpp::synchronize_new_thread()
            )
            .subscribe(...)
        ;
    }

    // fire-and-forget
    void insert(line const& line)
    {
        subj
            .get_subscriber()
            .on_next(line);
    }
};

in order not to block the caller (which would be the default behavior), the observable watches the values from each window on a new thread. Here, scheduling on a thread pool (currently missing in RxCpp) would probably be beneficial.

While this implementation might not be an optimal one, the declarative nature of Rx, once the basics are understood, allows to “make it work and make it right” pretty quickly by composing the right operators.

Code

The runnable code of the example can be found at Github: C++ version.

In order to show, how similar the high level code can be between different languages when writing, I’ve “ported” the example to C# 2.

  1. Source: reactivex.io License: (CC BY 3.0)
  2. The C# version appears to run faster on my windows machine while solving the same toy problem

Presenting at TU-Munich: testing on c++ projects, Thursday, March 26, 2015 7:00 PM

Expecting Thank you to all for a superb heated debate! next week

“no excuses for not testing on c++ projects”

Thursday, March 26, 2015
7:00 PM

details: http://www.meetup.com/MUCplusplus/events/220628575/

If only all test were comprehensible…

SCENARIO("acquiring wisdom") {

  GIVEN("an oracle") { 
    oracle gus;
    
    WHEN("I ask it to speak") {
      auto answer = gus.speak();

      THEN("wisdom is apparent") {
        CHECK( answer != "bla" );
      }
    }
  }
}

1

→ The code can be found @github, including the presentation slides.

ris – a lightweight cross-platform resource compiler for c++ projects

Why a resource compiler in the 21st century?

Starting a c++ project that will potentially need static string resources (i.e. Lua scripts) makes one search for an easy way to embed large strings in an executable. There are many ways of including static resources, but there seems to be no simple but robust, platform-independent way 1. For fast prototyping and one-shot projects, I’d like to have lightweight, minimum-configuration and install solution to the problem of embedding binary resources without having to use a large framework.

Premake, my favourite light-weight meta-build system contains a number of Lua scripts in its binary. These are embedded using a Lua script into a simple array of C-string constants. This is the simplicity that in my view should be strived for. ris is an attempt to do something similar for general c++ projects with a possibility of embedding binary blobs.

ris – cross-platform resource compiler for c++

The project (ris@github) is in its infancy, but seems already to be usable. Here’s a preview:

Defining and compiling resources

ris <path_to>/<resources>.json

with an input file as this self-explaining one:

{
    "namespace" : "test",
    "header" : "acceptance_test/resource.h",
    "source" : "acceptance_test/resource.cpp",
    "resources" : [
        {
            "name" : "string_test",
            "source_type" : "string",
            "source" : "plain text"
        },
        {
            "name" : "binary_file_test",
            "source_type" : "file",
            "source" : "test.bin"
        }
    ]
}

will generate two c++11 files to include in your project, enabling easy resource retrieval:

std::string res = test::Resource::string_test();

or

std::string res = test::Resource::Get("string_test");

Update 30.07.2015: now resources can be defined more concisely in YAML. A minimal resource definition in YAML looks like the following:

header: "res.h"
source: "res.cpp"

resources:
  -
    compression: "LZ4F"
    name: "some_text"
    source: "some text"
    source_type: "string"

Enumerating the resources

Resource keys in the compiled resource can be enumerated passing a callable to GetKeys:

std::vector<std::string> keys;
test::Resource::GetKeys([&keys](char const* key){
    keys.emplace_back(key);
});

Compression

Using an optional compression library bundle, adding a compression property to a resource description enables transparent (de)compression:

"compression" : "LZ4HC"

Customization

updated 24.11.2014:
ris now uses text resources generated and bootstrapped by its own early version. The goal is to make The code generator is customizable. The default template can be seen in template.json, and the generated header in template.h. The generation sequence can be seen in ris.cpp.

Using the second parameter to ris, it’s possible to override strings in the generator template. See an example below.

C++03

updated 27.11.2014:
One such customization is available in template_cpp03.json, where the C++11 constructs are replaced with generateable C++03 constructs.

To generate the resources using the C++03 template:

ris my_template.json template_cpp03.json

Why C++?

Such code generator as ris could most probably be developed more rapidly using any other programming language with a huge framework and a ton of libraries behind them. My personal preference for certain kinds of small projects lies in the area of self-contained single-binary/single-file executables or libraries, such as Lua. Lua is the primary motivation for this project, as it is itself a compact library for building flexible and extensible prototypes and tools. ris can act as a bootstrapping component to embed resources for building specialized shell-scripting replacements, i.e. for massive scripted file operations.

Source

https://github.com/d-led/ris

There is a number of paths this project can take from here. Features, such as robustness, performance or flexibility could all be addressed, but most probably ris will be shaped by its usage or absence of such.

A simple github + travis-ci project for quick c++ to lua binding tests

It’s sometimes necessary to create a simple example for C++ to Lua bindings on the run. Travis-CI might be of great help in that, while online C++ compilers will not suffice.

Here’s the project and a sample code:

https://github.com/d-led/lua_cpp_tryout

#include <lua.hpp>
#include <LuaBridge.h>
#include <RefCountedPtr.h>
#include <LuaState.h>
#include <iostream>

void luabridge_bind(lua_State* L) {
	class Test {
	public:
		Test() {
			std::cout<<__FUNCTION__<<std::endl;
		}

		~Test() {
			std::cout<<__FUNCTION__<<std::endl;
		}
	};

	luabridge::getGlobalNamespace(L)
		.beginClass<Test>("Test")
			.addConstructor<void(*)(),RefCountedPtr<Test>>()
		.endClass()
	;
}

int main() {
    lua::State state;
    luabridge_bind(state.getState());
    try {
    	state.doString("Test()");
    	state.doString("blabla()");
    } catch (std::exception& e) {
    	std::cerr<<e.what()<<std::endl;
    }
}

Test
[string "blabla()"]:1: attempt to call global 'blabla' (a nil value)
~Test

note the automatic lifetime management

In the process of searching for a quick header-only wrapper for the Lua state I came across LuaState which was the first one that compiled out of the box. Its advantage over other wrappers for my needs was that it did reveal the actual Lua state, with the effect of other binding libraries being usable. It could itself provide an alternative to LuaBridge for writing bindings and could be investigated further.

It’s now easy to fork the project and try out bindings online.

Beginning another quest – scripting business logic in .NET: using dynamiclua

Let’s start with Lua

The current state of things is that the lightweight but mighty Lua has become ubiquitous in the world of computing as a scripting and configuration component. Lua’s strategy of “mechanism, not policies” allows the language to be extremely malleable. It’s worth watching Roberto Ierusalimschy’s talks on the evolution of Lua 1.

The latest adoptions of Lua are for example the Redis’ EVAL Query with Lua scripting, and Wikipedia’s template automation using user-written Lua scripts.

dynamiclua

There have been several attempts to bring Lua into the world of .NET, and one of the most recent efforts by Niklas Rother, dynamiclua, combines the previous achievements with the dynamic type of .NET 4.0, and lays path for an easily reusable business logic scripting component, which is now even available via nuget.

After adding dynamiclua as a reference, here’s your first business logic:

using (dynamic lua = new DynamicLua.DynamicLua()) {
 Console.WriteLine(lua("return 2+2"));
}

note the IDisposable usage for freeing native resources.

Discovering the features

Static configuration

As an author of a configurable component,
In order to reduce my support effort,
I want the users of my component to write their static configuration themselves

While for that user story JSON or XML would suffice, we’re on the Lua track, hence this is how it could work:

// comes from some user input or file
string user_static_config = @"
 config = {
  url = 'https://github.com/nrother/dynamiclua'
 }
";

lua(user_static_config);
string url = lua.config.url;
Console.WriteLine(url);

… it does look like JSON, but it isn’t. Here, one can observe the harmony resulting from the use of the dynamic keyword to interact with a dynamic language from a statically typed one. DynamicLua can leverage reflection capabilities of both languages to create an “automagical” interop, compared sometimes tedious writing of bindings for a language, such as native C++.

The power of Lua at the user’s fingertips

As an author of a customizable business software,
In order to reduce my own support effort,
And create a new business of customizations,
I want the administrators of my software to write their business logic scripts themselves

Many systems grow out of static configurability, and business logic definition and evaluation in some programming language becomes inevitable. Whether this is a good thing or a bad one for one’s business 2 is not in the scope of this article, as it is assumed, we want to make our software customizable via scripting 3.

The static configuration entries can be dynamically evaluated at script run time. Various bindings may be used in the script, as i.e. the math standard library here:

lua("config.answer = nil or math.floor(131.94689145078/math.pi)");
int answer = (int)lua.config.answer;
Console.WriteLine(answer);

Using Lua as an expression evaluator

Lua supports multiple return values, which makes certain scenarios fun:

dynamic result = lua("return 1, 'world'");
Console.WriteLine("{0} {1}", result[0], result[1]);

Binding .NET code

Dynamiclua does not have an explicit class binding syntax 4, but it doesn’t matter much, as functions can be bound, and thus, constructors. Via reflection all public 5 members are bound. The domain code is therefore very easy to bind. Take an example:

class Example
{
    int answer = 42;
    public int Answer { get { return answer; } }

    public int Add(int a, int b)
    {
        return a + b;
    }
}

The binding is quite trivial:

lua.NewExample = new Func<Example>(() => new Example());

// Lua functions may be called via dynamiclua
Example my_example = lua.NewExample();
Console.WriteLine(my_example.Answer);

lua(@"
    local example = NewExample()
    print(example.Answer)
    print(example:Add(2,3))
");

Minimal sandboxing

As an author of a scripting component,
In order to mitigate the risk of damage by malicious user-supplied code,
I want the script executing environment to be sandboxed.

Sandboxing is a very complex issue and perhaps only approximations of an undefined ideal sandbox can be made 6. A sane attitude towards this security-related issue should go along the lines of trusting nobody, even oneself, and even that distrust should not be enough. Depending on the posed security requirements, the logic execution component might even be physically separated from your business software, i.e. running on another machine or in another process. But that is perhaps another concern and should be independent of your script execution component.

Since Lua is malleable, one can configure or manipulate the Lua virtual machine to make certain actions unlikely, such as accessing the file system. This can be achieved by setting the bound names to nil as in 7:

lua("import = nil");
lua("require = nil");

new Action(() => lua("import 'System'"))
    .ShouldThrow<Exception>();

In this little spec you can also observe what should happen (non-specifically) if there’s a Lua syntax or a runtime error. You can also see how to import assemblies into the Lua state.

Here’s another quote from the test:

lua.import("System");

Func<int> func = () => (int)lua("return Console.BufferHeight")[0];
new Action(() => func())
    .ShouldNotThrow();
func().Should().Be(Console.BufferHeight);

Without further ado

Some things should perhaps be further investigated:

  • Is dynamiclua prepared for the Mono runtime on *x platforms?
  • Is it possible to crash the process uncontrollably, even while catching exceptions?
  • Fix crash on finalization

Lua can appear simple enough, such that, given a syntactic constraint, even non-programmers could write business logic scripts and configurations. However, there is a company experimenting with alternative ways to define business logic using different approaches to a logic-definition UI. It’s worth checking out: LogicEditor.

Other language and runtime candidates will hopefully be investigated within the next posts of the quest: IronRuby and Boo. The readers of this blog entry are welcome to criticize, point out omitted or wrong information, and interact freely.

Code

https://github.com/d-led/BusinessLogicScripting

  1. Video 1, more slides, Video 2, more Roberto
  2. User scripts are software, and thus might never terminate
  3. I won’t repeat the meme about great power here
  4. as is the case with many C++ bindings i.e. LuaBridge
  5. In my opinion, access to privates should throw…
  6. see wiki: SandBoxes and Daniel Silverstone’s talk at Lua Workshop 2013 on his approach
  7. More …

A C++ Background Ticker, now with Rx.cpp

Finally, Rx.cpp

Some time ago I have written that I didn’t have enough patience to recreate the background ticker example in C++ using Rx.cpp. Since then the Rx.cpp project seems to have grown out of the spike phase, and even has a native NuGet package. It has also gone multiplatform (Windows, OSX and Linux): observe the green Travis-CI Button.

Update: new blog post, discussing RxCpp v2 and testing using the test scheduler.

A simple console ticker

As in .Net, Reactive Extensions provide a simple way to process streams of data asynchronously, while keeping the concurrency-related code declarative and thus readable. Here’s a simple ticker in the console which runs asynchronously to the main thread:

auto scheduler = std::make_shared<rxcpp::EventLoopScheduler>();
auto ticker = rxcpp::Interval(std::chrono::milliseconds(250), scheduler);

rxcpp::from(ticker)
	.where([](int val) { return val % 2 == 0; })
	.take(10)
	.subscribe([](int val) {
		std::cout << "tick " << val << std::endl;
	});

std::cout << "starting to tick" << std::endl;

resulting in something like:

starting to tick
tick 0
tick 2
tick 4
tick 6
tick 8
...

where the ticks appear once in 250 milliseconds.

Throwing away code

The PPL example was simulating polling a sensor and printing the value. It had an error-prone and buggy ad-hoc implementation of an active object, ticking at predefined intervals. This can be now happily thrown away, as Rx allows a cleaner concurrency control and testability using schedulers, and implements a timed sequence: Interval.

Preconditions

FrequencyMeter FM;
auto scheduler = std::make_shared<rxcpp::EventLoopScheduler>();

The scheduler will be used for all subscriptions.

The tickers

The first one:

auto measure = rxcpp::Interval(std::chrono::milliseconds(250),scheduler);
auto measure_subscription = rxcpp::from(measure)
	.subscribe([&FM](int val) {
		std::cout << FM.Hz() << std::endl;
	});

where measure_subscription is a rxcpp::Disposable for subscription lifetime control.

And the other one:

auto ticker = rxcpp::Interval(std::chrono::milliseconds(500), scheduler);
rxcpp::from(ticker)
	.take(10)
	.subscribe([](int val) {
		std::cout << "tick " << val << std::endl;
	});

where you can observe the LINQ-style filter take

Managing subscriptions

In the PPL example, one could start and stop the ticker. However, in Rx.cpp this can be simply modeled by disposable subscriptions. Hence, after some kind of sleeping, the measurement can be stopped:

sleep(2000);
std::cout << "Canceling measurement ..." << std::endl;
measure_subscription.Dispose(); // cancel measurement

Resulting in similar output:

60
63
tick 0
61
62
tick 1
63
63
tick 2
62
60
tick 3
Canceling measurement ...
tick 4
tick 5
tick 6
tick 7
tick 8
tick 9

Restarting measurement can be done by creating a new subscription.

Why not simply signals/slots?

Almost quoting the Intro to Rx book, the advantages of using Rx over (at least) simple implementations of signal/slot mechanism are:

  • Better maintainability due to readable, composable, declarative code
  • Scheduler abstraction allowing for fast, deterministic, clock-independent tests of concurrency concerns
  • Declarative concurrency through the same scheduler abstraction
  • LINQ-like composition and filtering of event streams
  • Easy subscription control via disposables
  • Completion and exception handling built-in in the Observer concept

Code

@GitHub

Corrections, suggestions and comments are welcome!

Update 26.6.2014: There’s been a new release of Rx.cpp on nuget, and Kirk Shoop pushed a pull request, upgrading the project and the api usage to Rx.cpp 2.0.0. There have been some changes, and there are some interesting patterns, which should be blogged about in the near future.

header-only non-intrusive json serialization in c++

A while ago I’ve started a convenience, zero error-handling, json serializer wrapper around picojson based on the Boost.Serialization and hiberlite APIs. Today the wrapper got even less intrusive for DTOs that expose their members.

Given a class that cannot be extended in its declaration, but the internals are accessible (following to the Boost.Serialization free function API):

struct Untouchable {
    int value;
};

With a free function defined in the ::picojson::convert namespace,

namespace picojson {
    namespace convert {

        template <class Archive>
        void json(Archive &ar, Untouchable &u) {
            ar &picojson::convert::member("value", u.value);
        }

    }
}

serialization is “again” possible:

Untouchable example = { 42 };
std::string example_string( picojson::convert::to_string(example) );

Untouchable example_deserialized = { 0 };
picojson::convert::from_string( example_string, example_deserialized );
CHECK( example.value == example_deserialized.value );

github.com/d-led/picojson_serializer

The quest for a c++ Dependency Injection Container library. Part 3, beginning dicpp

Dependency Injection + C++ = dicpp

The first article introduced the example problem – an almost trivial example for dependency injection. One of the implementation classes is mocked within a test to show the resulting implementation configuration flexibility.

Another library in the quest is dicpp. It is somewhat similar to sauce with little twists, hence it required some trial and error to get right after sauce. Dicpp configures the dependencies in code and allows configurable lifetime scopes.

Modules

Modules are, again, similar to sauce’s modules, as they can be simple functions for registering the bindings of interfaces to implementations.

The library uses a slightly intrusive macro that puts a special typedef in the class’ declaration. One constructor is supported and should be split into declaration and definition. The macro for the renderer looks as follows:

class DicppKeyRenderer : public IRender {
public:
	DI_CONSTRUCTOR(DicppKeyRenderer,(std::shared_ptr< IGetKeyValue > m));
...
};

Without changing the existing factory, the default implementations are used:

DicppKeyRenderer::DicppKeyRenderer(std::shared_ptr< IGetKeyValue > m) :
	pimpl ( NewKeyRenderer(m) ) { }

The module with the bindings looks as follows (dicpp_module.cpp):

void dicpp_module( di::registry& r ) {
	r.add( r.type< IGetKeyValue >().implementation<DicppJsonDecoder>() );
	r.add( r.type< IRender >     ().implementation<DicppKeyRenderer>() );
}

Mock and the Singleton scope

To set the mock expectations on an instance of a dependency, one needs to obtain a pointer to that dependency. Once again, the mock implementation of an interface is done via googlemock:

class MockModel : public IModel {
public:
	MOCK_METHOD0(Get, std::string());
};

To obtain the same instance of the mocked IModel as which gets resolved automatically, one can use a dedicated scope, such as the singleton scope. The mock is added to the module in the singleton scope:

void mock_module( di::registry& r ) {
	r.add( r
		.type<IModel>()
		.implementation<MockModel>()
		.in_scope<di::scopes::singleton>() )
	;
}

Configuring the injector

test_dicpp.cpp

The injector is the container of bindings that gets configured by adding modules:

di::injector inj;
inj.install( dicpp_module );
inj.install( mock_module );

Configuring the mock

With the modules “installed” in the injector, the singleton mock instance can be obtained:

auto mock_model = inj.construct_ptr< IModel >();

MockModel* mock_model_ptr = dynamic_cast< MockModel* >(mock_model.get());
ASSERT_TRUE( mock_model_ptr );

EXPECT_CALL(*mock_model_ptr, Get())
	.Times(AtLeast(1))
	.WillRepeatedly(Return("{ \"a\" : 1 , \"b\" : 2 }"));

Logging in dicpp

An interesting feature in dicpp is logging of the library activity. The feature can be overridden or turned off via macro definition. The construction of dependencies can be traced, such as here, slightly shortened :

[DICPP]: Registering: IGetKeyValue with implementation: DicppJsonDecoder in scope: di::scopes::no_scope
[DICPP]: Registering: IModel with implementation: MockModel in scope: di::scopes::singleton
[DICPP]: Registering: MockModel with implementation: MockModel in scope: di::scopes::no_scope
[DICPP]: Constructing: di::type_key<IModel, void>
[DICPP]: Provided type: di::type_key<IModel, void>
[DICPP]: Singleton: constructing: di::type_key<IModel, void>
[DICPP]: Generic constructing IModel with implementation: MockModel
[DICPP]: Completed constructing: di::type_key<IModel, void> with address: 0x7fd0b2600e40
...
[DICPP]: Singleton: returning existing: di::type_key<IModel, void>

As one can see, two bindings are registered for one implementation – the interface and implementation can be resolved at later time.

Summary

The rest of the example is very similar to the first and the second parts of the quest:

auto renderer = inj.construct_ptr< IRender >();
ASSERT_EQ( "a,b", renderer->Render() );

Although the library is very similar to sauce, the binding definition language doesn’t read as fluently as that of wallaroo or sauce. Further articles may elaborate on the outstanding features of either library.

Source: https://github.com/d-led/test-ioc-cpp

Updates

05.11.2014: Removed boost<->std shared_ptr conversions, as dicpp has been updated in the meanwhile

More to come…

The quest for a c++ Dependency Injection Container library. Part 2, some Sauce

Introduction

In Part 1 I have started with a list of C++ dependency injection libraries, and sketched an example problem, solved and tested with the help of Wallaroo. For the second part, Hypodermic should have been in focus, but unfortunately, no version compiled out of the box on MacOS with Clang 1. Hence, the article is about sauce, an inspiration from google-guice.

Dependency Injection using sauce

A little repetition, the example problem contains of 3 interfaces with a linear dependency graph of the implementations. Not to repeat the implementations, and not change the structure of the existing code, simple factories for the default implementations have been exposed, but not the concrete types in the headers, i.e. for the default renderer implementation:

std::shared_ptr< IRender > NewKeyRenderer(std::shared_ptr< IGetKeyValue > model) {
	return std::make_shared<KeyRenderer>(model);
};

Implementations

Simplified, the sauce solution looks as follows. Unlike in Wallaroo, in sauce, the implementations do not need to derive from a common “dependency” class. Any type can be bound to any derived class. The implementation of a renderer for the sauce example just adds a delegation to the original implementation 2:

class SauceKeyRenderer : public IRender {
public:
	SauceKeyRenderer(std::shared_ptr< IGetKeyValue > m) :
	pimpl ( NewKeyRenderer(m) )
	{ }

public:
	virtual std::string Render() {
		//...
		return pimpl->Render();
	}

private:
 	std::shared_ptr< IRender > pimpl;
};

Modules

Modules are containers of bindings of interfaces to their implementations. The easiest way to define a module is to provide a function with the signature void (* module)(sauce::Binder &).

Here’s the self-explaining module:

void render_module(sauce::Binder& b) {
	b.bind<IRender>().to<SauceKeyRenderer(IGetKeyValue&)>();
}

Once again, obviously, the type doesn’t have to leak outside the module due to inversion of control.

Note that the IGetKeyValue dependency of SauceKeyRenderer is injected via the constructor parameter, enabling automatic dependency resolution at later time.

Injectors

Instances of the bound interfaces are obtainable from injectors, which can be constructed from a collection of modules:

sauce::shared_ptr<Injector> injector = Modules()
	.add(render_module)
	.add(decoder_module)
	.add(model_module)
	.createInjector()
;

Resolving the dependencies

The hello-world example of resolving the dependencies is one simple line:

sauce::shared_ptr<IRender> renderer = injector->get<IRender>();

In this case, SauceKeyRenderer will get resolved and two other dependencies will be automatically instantiated and injected (see test_sauce.cpp).

Mocking and singletons

Sauce allows for different lifetime models of the interface instances. Singletons are possible with the concept of scoped injectors, in which, the instances are shared.

For googlemock getting the resolved instance is crucial, since the expectations are bound to an instance of the mocked class. With automatic dependency resolution and no hacks, the interface IModel would resolve to a new instance in the test. Hence, unless a way to use the shared instance lifetime inside the test is found, the mock is implemented trivially without googlemock.

Summary

This article is once again a short intro into the paradigm of another Dependency Injection library sauce. A more elaborate intro can be read in sauce’s tutorial test suite.

Source: https://github.com/d-led/test-ioc-cpp

More to come…

  1. To do in 2014
  2. Efficiency and overhead are not considered in the first place.