Wednesday, June 28, 2017

Generic Factory

One of my most common problems when I write C++ is how you actually go about building an object. We'll get into greater detail about how this is important for Google Mock and unit testing later. Other times, you may have a wide range of classes derived from the same base class and don't know which one you will need until you're already in runtime. Or perhaps you have a bunch of these classes, but dynamically loaded libraries/modules/plugins may provide even more subclasses that would remain unknown to the core program.

With one project, they had assembled a factory system with all sorts of Macros. Macros were already a bit passé a while ago, but with IDEs and their various tools, I have even less desire to see them in our code. While researching some alternatives, I came across this post. It's a little dated so I adapted it some for the modern era. What follows is built around C++14 and some modifications may be needed to adapt to 11, and improvements still exist going up to C++17.

Let's start with the big picture and then break it down some.

Factory

#include <algorithm>
#include <functional>
#include <map>
#include <memory>

template <class Base, typename ClassIDKey=std::string>
class GenericFactory
{
    using BaseCreateFn = std::function<std::unique_ptr<Base>()>;
    using FnRegistry = std::map<ClassIDKey, BaseCreateFn>;

public:
    static GenericFactory& instance(){
        static GenericFactory factory;
        return factory;
    }

    void RegCreateFn(const ClassIDKey& key, const BaseCreateFn& createFunction){
        auto regIt = std::find_if(registry.begin(), registry.end(),
                                  [key](const auto &registryEntry) {
                                      return key == registryEntry.first;
                                  });

        if (registry.end() == regIt) {
            registry.emplace(key, createFunction);
        } else {
            registry.at(key) = createFunction;
        }
        registry.emplace(key, createFunction);
    }

    std::unique_ptr<Base> Create(const ClassIDKey& key) const{
        auto registryIt = registry.find(key);
        if(registry.cend() != registryIt){
            return registryIt->second();
        }
        return nullptr;
    }
private:
    GenericFactory(){}
    
    FnRegistry registry;
};

template <typename Base, 
          typename Derived, 
          typename ClassIDKey=std::string, 
          typename = std::enable_if_t<std::is_base_of<Base, Derived>::value>
class RegisterInFactory
{
public:
    static std::unique_ptr<Base> CreateInstance()
    {
        // if c++ 11, would just use the traditional constructor
        return std::make_unique<Base>();
    }

    RegisterInFactory(const ClassIDKey &id)
    {
        GenericFactory<Base>::instance().RegCreateFn(id, CreateInstance);
    }
};

Factory structure

The core of the Factory is a map of some key to some function that creates a smart pointer to the base class out of some new derived class. We've set up some aliases for readability, but they aren't strictly necessary. Compared to the post on Dobbs' you can see I've updated from the atrocious old function pointers to the new functional objects. We don't, as far as I'm aware, gain tons of advantage technically here, but I might speculate there are some out there. Mostly I did it because the function objects are just so much easier to read.
Skipping down to GenericFactory::Create, this would be the function that actually gets called in a program. A key is passed in, searches through the registry of pseudo-constructors for the right constructor and then returns the result of the call to it. 
Finally, we want our factory to be a singleton. So we require the use of the 'instance' function to get a hold of the factory, and hide our constructor in private.

Factory Registration

The GenericFactory could stand on its own if we wanted, and in some of the advanced techniques we may take advantage of that fact. But, just like the post in Dobbs', we can easily simplify how this factory works by adding this helper class "RegisterInFactory."
The actual construction doesn't particularly need us to go out and define some functor that returns the appropriately wrapped construction of the Derived class, so a static member function will still fulfill the signature for our create function. (the 'CreateInstance Function). As for the class itself, construction will register the function to our factory. We'll see how that happens in...

Using the factory

Base Class

It's not just enough to say what the factory looks like, it helps to actually see it in use. We'll start with some trivial base class
(BaseClass.h)

#include "GenericFactory.h"

class BaseClass
{
public:
    virtual ~BaseClass();
    virtual void print() = 0;
};

using BaseFactory = GenericFactory<BaseClass>;

Now, the base class could be an actual class and not just a pure virtual, but I rather like this pattern as a means to make interfaces a bit more useable. If, perhaps you'd like to have default implementations of the functions, but still disallow construction of the Base class, you can do the usual and define the constructor as a protected function.

We don't technically need to do pretty much anything here, technically. However, I find that having the factory included here is simpler than including it through all the subclasses. Especially since we're hoping that users of this will use our factory to construct them rather than doing so directly. Including it here also allows us to throw in an alias to this Generic Factory as opposed to some other one. (The point of defining it Generically is that you could use that one factory template to produce many kinds of factories for many different base classes).

Nothing at all needs to be done in the source file (.cpp), but if your Base class is a useful one, you may want to have your factory produce a base pointer to the base class. In which case you'll follow the same pattern as the...

Derived Class

While BaseClass had its action in the header, Derived only needs a modification to the source file
(Derived_1.cpp)
#include "Derived_1.h"

#include <iostream>

namespace  {
RegisterInFactory<BaseClass, Derived_1> registerMe{"Derived 1"};
} // anonymous namespace

Derived_1::Derived_1() : BaseClass()
{

}

void Derived_1::print()
{
    std::cout << "Printing from Derived class 1" << std::endl;
}

Here all we need to note is the use of the 'RegisterInFactory' class. The template signature following RegisterInFactory tells us which type to register to which factory. While we never use the global object created by it, the act of making that object registers the class to the factory. You could do this with static objects, but I like anonymous namespaces here, especially since we're explicitly not using this object, the object created is constrained to this source file.

User of factory

(UserOfBases.cpp)

#include "UserOfBases.h"

#include "BaseClass.h"

void UserOfBases::printFromDerived(const std::string& derivedType)
{
    std::unique_ptr<BaseClass> object =BaseFactory::instance().Create(derivedType);
    object->print();
}

Here we see some example of how all of this comes together. It's so simple I can't really think of what else to say about it. Certainly outside of a little toy program there would be a lot more going on with our created object, but this illustrates the use nicely.

Example code here

Coming up next: What do you do when your class needs to be initialized as part of the constructor? Generic Factories with Initializers!

Tuesday, June 27, 2017

Introduction

When I was choosing an advisor for my doctoral work in physics, he asked whether I'd ever programmed before. I'd had one C++ class my first semester of undergrad, about 5 years prior. To him, this was good enough, you either knew how to program or not. That philosophy is just as bad as it sounds.

As scientists, we maybe wrote code like scientists. We would write up some analysis suite; run it through a simulation; see if the results matched what we predicted. The code was unorganized and full of random hacks here and there. The whole team's software probably reinvented the wheel several times.

I didn't finish my research work. What work I had done had been circling around not very good results, and some (at that time) undiagnosed mental health issues had left me particularly unmotivated to do more. I would accept a master's, and in my last semester took a few courses in software design and development. (which eventually succumbed to the lack of motivation into audited courses).

I give my little bit of history here because with my first position out of grad school, I learned a ton of actually useful development techniques. Stuff that I've come to find isn't often taught to CS majors even. How to organize libraries. How to write unit tests. Why to write unit tests. How to use good version control software. How to handle continuous integration within a large team. Agile Development techniques and so on.

My blog here is to recount some of these useful lessons. Some will be aimed at these broader lessons, some will be specific patterns and techniques I've adopted in my unconventional path to development.

Finally, a note about the name of the blog. C++ was originally named "C with Classes." I feel like with the contemporary wordplay/pun app naming scheme, one might now call it "classC," pronounced "classy." Or the other read of 'classic' perhaps might be used if you hadn't heard it pronounced before. My main language is C++, generally in the 11/14 standard, sometimes with Qt (5, but 4 maybe), built using CMake mostly, and tested with Google Mock/Test. Usually I develop in Linux and cross compile to other platforms. I like CLion and Qt Creator as IDEs, but whatever IDE works for you is better than no IDE in my book.