Dependency injection with factory class - c++

We have a request based application where requests are executed by sending a command over serial.
When data is received indicating a request is to be performed the request is created using a factory class by specifying that requests specific ID.
The problem is that each request will have different dependencies depending on the tasks it has to perform and I am looking for the best solution to do this.
What is the best way to inject dependencies to requests when dependencies may differ between requests?
Is passing a reference to the RequestFactory for every possible request dependancy a bad idea? (We currently have around 20-30 different requests that have around 6 or 7 different dependencies in total)
My planned solution is similar to that below, but is there an easier, or better approach?
Thanks.
class Request;
class RequestOne;
class RequestTwo;
class RequestFactory
{
public:
RequestFactory( /* Dependencies for RequestOne and RequestTwo */ )
{
// Keep reference to dependencies
}
std::shared_ptr< Request > create( int id )
{
std::shared_ptr< Request > request;
switch ( id )
{
case 1:
request = std::make_shared< RequestOne >( /* RequestOne Dependencies */ );
break;
case 2:
request = std::make_shared< RequestTwo >( /* RequestTwo Dependencies */ );
break;
}
return request;
}
};
class Request
{
public:
virtual ~Request( );
virtual void process( ) = 0;
};
class RequestOne : public Request
{
public:
RequestOne( /* RequestOne Dependencies */ )
virtual ~RequestOne( );
virtual void process( );
};
class RequestTwo : public Request
{
public:
RequestTwo( /* RequestTwo Dependencies */ );
virtual ~RequestTwo( );
virtual void process( );
};

It sounds like you're primarily concerned about the number of constructor parameters that would need to be supplied to RequestFactory (i.e., the union of the dependencies of all products). You can handle this situation in the same way you handle others in which a class has a large number of dependencies: identify new collaborators for the class.
As a class gathers more and more dependencies/collaborators, patterns tend to emerge between some of those dependencies. These patterns almost always represent some previously-unidentified abstraction(s). If you can place a name on such an abstraction, you can refactor the class to use it in place of the "related" dependencies.
Mark Seemann has referred to this as Refactoring to Aggregate Services.
Your RequestFactory seems like a good candidate for this. Consider how things might look if the RequestFactory class collaborated with two other classes:
class Request;
class RequestOne;
class RequestTwo;
class RequestOneFactory
{
public:
virtual std::shared_ptr< RequestOne > CreateRequest(/* RequestOne Dependencies */) = 0;
};
class RequestTwoFactory
{
public:
virtual std::shared_ptr< RequestTwo > CreateRequest(/* RequestTwo Dependencies */) = 0;
};
class RequestFactory
{
public:
RequestFactory(std::shared_ptr< RequestOneFactory > requestOneFactory, std::shared_ptr< RequestTwoFactory > requestTwoFactory)
{
// Keep reference to collaborating factories
}
std::shared_ptr< Request > create( int id )
{
std::shared_ptr< Request > request;
switch ( id )
{
case 1:
request = requestOneFactory->CreateRequest();
break;
case 2:
request = requestTwoFactory->CreateRequest();
break;
}
return request;
}
};
Looking at things this way, we might start to suspect whether RequestFactory was actually taking on multiple responsibilities:
Determine what type of request to create
Create that type of request
By refactoring the code, RequestFactory maintains the first responsibility while delegating the other to collaborating classes.
Note: Using the above approach, it's possible for the abstract factories to be too heavily influenced by the concrete request classes, which could be a code smell. However, I suspect that RequestOne and RequestTwo may represent distinct abstractions in their own right, which would make the introduction of abstract factories much more logical.

The solution proposed by #Lilshieste has the same flaw of your original implementation, you have to manually maintain a "switch-heavy" statement, even worst, in #Lilshieste solution you have increase the number of factories given as parameter to the RequestFactory.
Since you don't mentioned any performance issue I'll propose a little slower, but more solid solution.
I do not agree that this need aggregation, the reason is that in your case you just don't have many dependencies, you need polymorphic behaviour, wich does not require aggregation but construction of an appropiate interface to deal with.
Observation 1:
Since you are using C++11, use the new enums instead of "int" for the ID (that will give usefull compile time errors).
Observation 2:
Reverse the problem. Dont let the generic RequestFactory depends on Concrete Factories, instead let ConcreteFactories register themselves in the RequestFactory!
class RequestOneFactory: public virtual AbstractRequestFactory{
//note: no member variables!
public:
RequestOneFactory( std::shared_ptr<RequestFactorySupplier> factory){
factory->register( getptr(),ID);
}
std::shared_ptr< Request> create() const{
std::shared_ptr< Request> request =
std::make_shared< RequestOne>( /* Dependencies*/);
return request;
}
};
Every Factory have the same Interface, since you are doing DI, you probably want the factory to be managed. Just inherit from enable_shared_from_this.
class AbstractRequestFactory: std::enable_shared_from_this< AbstractRequestFactory>{
public:
virtual ~AbstractRequestFactory(){}
virtual std::shared_ptr< Request> create() const = 0;
std::shared_ptr<AbstractRequestFactory> getptr() {
return shared_from_this();
}
};
The RequestFactory has now no constructor dependencies, also note that I broke up its interface in 2 parts so that different users of the factory can do different things.
#include <unordered_map>
#include <RequestFactorySupplier.hpp>
#include <RequestFactoryUser.hpp>
#include <AbstractRequestFactory.hpp>
class RequestFactory: public virtual RequestFactorySupplier
,public virtual RequestFactoryUser{
//associative container.
std::unordered_map< RequestID, std::shared_ptr< AbstractRequestFactory>> map;
public:
RequestFactory()=default;
~RequestFactory()=default;
//IMPLEMENTS: RequestFactorySupplier
virtual void register( std::shared_ptr< AbstractRequestFactory> fac, RequestID id){
if(map.find(id)!=map.end()){
//ID already used.. throw error, assert(false), what you want.
}
map[id] = fac;
}
//IMPLEMENTS: RequestFactoryUser
virtual std::shared_ptr< Request> create(RequestID id){
if(map.find(id)==map.end())
throwSomething(); //No factory for such ID
return map[id]->create();
}
};
If you are using a Dependency Injection framework
now the work to wire up everything is very simple, the following example uses Infectorpp (wich I wrote), you can do similiar things with other frameworks of course.
#include <Infectorpp/InfectorContainer.hpp>
int main(){
Infector::Container ioc;
//register generic factory with 2 interfaces
ioc.bindSingleAs<RequestFactory, RequestFactorySupplier,RequestFactoryUser>();
//for each concrete factory register it
ioc.bindSingleAsNothing<RequestOneFactory>();
ioc.bindSingleAsNothing<RequestTwoFactory>();
//...
//wire the generic factory
ioc.wire<RequestFactory>();
//wire the factories (dependencies injected here)
ioc.wire<RequestOneFactory, RequestFactorySupplier>();
ioc.wire<RequestTwoFactory, RequestFactorySupplier>();
//...
//build the factories (let them register in RequestFactorySupplier)
{
ioc.buildSingle<RequestOneFactory>();
ioc.buildSingle<RequestTwoFactory>();
//you will not have references to them but RequestFactory will: Good!
}
//Your classes can use RequestFactoryUser to create RequestObjects.
//application run!
return 0;
}
Also consider creating objects wrapped around a std::unique_ptr for those factories instead of a std::shared_ptr (if unique_ptr is enough never use std::shared_ptr).

Related

Google Mock for NonVirtual and Private Functions

I'm attempting to write Mocks for Private / Non Virtual / Static functions and come across a way to do the same.
Here is how it looks like..
Lets assume that I have a class A which needs to be mocked and used inside class UsingA. The definition of both classes looks like
class A
{
friend class UsingA;
int privateFn() {}
public:
int nonVirtual() {}
};
// The UsingA class
class UsingA {
A &a1;
public:
UsingA(A & _a1) : a1(_a1) {}
int CallFn() {
return a1.nonVirtual();
}
int CallFn2() {
return a1.privateFn();
}
};
I know that Mocks are meant for generating the behavior of the class and while creating Mocks, we need to derive from the original class.
However, to Mock the behavior I decided not to derive from the original class, instead comment the class A and generate a Mock class with the same Name i.e class A.
Here is how my mock class looks like
// Original class A is commented / header file removed
class A {
public:
MOCK_METHOD0(nonVirtual, int());
MOCK_METHOD0(privateFn, int());
};
And my tests are usual mock tests
TEST(MyMockTest, NonVirtualTest) {
A mstat;
UsingA ua(mstat);
EXPECT_CALL(mstat, nonVirtual())
.Times(1)
.WillOnce(Return(100));
int retVal = ua.CallFn();
EXPECT_EQ(retVal,100);
}
TEST(MyMockTest, PrivateTest) {
A mstat;
UsingA ua(mstat);
EXPECT_CALL(mstat, privateFn())
.Times(1)
.WillOnce(Return(100));
int retVal = ua.CallFn2();
EXPECT_EQ(retVal,100);
}
And everything works fine and I'm able to test UsingA by this mock.
Question is.
This looks easier and serves the purpose, still I haven't seen this kind of examples while browsing for google mock examples. Is there anything that would go wrong if I do this?
Honestly, I didn't find any.
NOTE: Folks, I'm using friend for demonstration only. My actual use case is totally different. Thanks
The wrong is that you are not testing real code, because of that:
comment the class A
generate a Mock class with the same name
These operations alter the code under test.
An example what can go wrong:
Change return type: long nonVirtual in Mock - previously was int
Test that on, let say, nonVirtual() == 0xFF'FFFF'FFFF (which is bigger than INTMAX) some action is being done
Forget to change in real A - so real UsingA have branch that is tested but never reachable in real code
An example code:
class A {
public:
MOCK_METHOD0(nonVirtual, long()); // change
MOCK_METHOD0(privateFn, int());
};
void UsingA::processA()
{
if (a.nonVirtual() > VERY_BIG_NUMBER)
{
throw runtime_error("oops");
}
}
TEST_F(UsingATest, throwOnVeryBigNumber)
{
EXPECT_CALL(aMock, nonVirtual()).WillOnce(Return(VERY_BIG_NUMBER + 1));
ASSERT_THROW(objectUndertTest.processA());
}
But real A did not change - so we test non reachable code in UsingA class:
class A {
public:
int nonVirtual(); // not changed
...
};
The best solution is (in order):
To test in isolation you have to isolate classes - so to use dependency injection (virtual functions etc, base interfaces, etc...) - this is sometimes called London School of TDD
Test both classes A and UsingA w/o any stubbing - test them together in one testcase - thus you test real code - this is called Detroit Shool of TDD
Separate by template code with good restriction on interface - this approach is most similar to yours:
Regarding 3 - you might use something like this:
template <class T = A>
class UsingA {
T &a1;
public:
UsingA(T & _a1) : a1(_a1) {}
long CallFn() {
using ANonVirtualResult = std::invoke_result_t<&T::nonVirtual>;
static_assert(std::is_same<long, ANonVirtualResult>::value);
return a1.nonVirtual();
}
...
};
And in test:
class UsingATest : public ::testing::Test
{
protected:
StrictMock<AMock> aMock;
using ClassUnderTest = UsingA<AMock>;
ClassUnderTest objectUnderTest{aMock};
};
TEST_F(UsingATest, useNonVirtual)
{
const auto VALUE = 123456;
EXPECT_CALL(aMock, nonVirtual()).WillOnce(Return(VALUE));
ASSERT_EQ(VALUE, objectUnderTest.CallFn());
}
You might note that some assumption about A might be tested during compilation as static_assert or via some SFINAE technics (more complicated).
Actually, there are examples with template code in googlemock as workaround for mocking classes w/o virtual functions.
We use your type of using mocks inside a few of our test projects to check callbacks on a larger class that we pass along using dependency injection. In our case, the methods are declared virtual.
In your case, they are not. Your mock implementation would hide the original implementation - if there was any. So I don't think there's an issue here.

A C++ issue with multiple inheritance, templates and static variables

I have a code similar to the following:
template<class ObjType>
class jsonable
{
private:
static map<string, jsonElem> config;
protected:
virtual void setConfig() = 0;
//other fields and methods in public/private
}
class user : public jsonable<user>
{
protected:
virtual void setConfig();
//other fields and methods in public/private
}
class client : user
{
protected:
virtual void setConfig() {user::setConfig(); /* more config */}
//other fields and methods in public/private
}
The main idea of this code is to save in static variables data related to the class referenced in the template. The problem comes when I want to inherit from the user class: the static variable is shared between user and client classes, instead of one static variable for each class.
I've tried to do something like:
class client : user, jsonable<client>
But a bunch of problems appeared (many methods with same name, and some other related to inherit 2 times the same class). I don't know if there is an elegant way of do this, or even if there is a way at all. (I'm a bit newbie in c++)
Any idea would be welcome! :). And of course, I can "copy" all the contents of user into client but... I would like to do not do that until there are no more options.
Edit:
In order to add context and details to the question, I'm going to explain a bit what I'm doing (or want to do).
Jsonable is a class that provides the ability to serialize into Json another class (helped by https://github.com/nlohmann/json).
To achive this, it uses a static map to store each jsonable-field name and its info (type and position relative to the start of the class in memory, so it can be serialized and deserialized).
The problem comes if a class inherits from another class that inherits from jsonable. Both shares that map, so only the baseclass data is consider when serializing/deserializing. Hope this explanation helps to understand...
Edit2: Giving a full code in a question seems very overkilling to me. If someone wants something to compile, I've uploaded a git repo: https://github.com/HandBe/jsontests
Really thanks to all the people who have put interest on this question!.
A possible solution can be derive client from both user (because it is a user) and jsonable<client> as (private/public apart)
class user : public jsonable<user>
{
protected:
virtual void setConfig();
//other fields and methods in public/private
};
class client: public user, public jsonable<client>
{
virtual void setConfig()
{
user::setConfig();
// more config, referred to jsonable<client>::map
}
}
because it has to implement jsonable for itself (regardless of user).
This is the so-called "stacked parallelogram" inhertiance pattern very common in multiple interface implementations as modular behavior.
Now user and client have each their own configuration
If I understand your problem correctly: you want client to be a user, but also have all the per-class statics defined in jsonable?
Have you considered composition over inheritance? This could work either way:
1) make user a component of client
class client : public jsonable<client>
{
user parent; // could also be a pointer
void setConfig() {parent.setConfig(); /* more config */}
/* ... */
}
2) make jsonable a component:
class user
{
jsonable<user> userjson; // public, private, whatever is appropriate for your design
/* ... */
}
class client : public user
{
jsonable<client> clientjson;
/* ... */
}

Best approach to extend this C++ factory implementation?

I would like to extend an existing piece of code, and I'm not sure about the cleanest design approach to do so. I'm wondering if the existing design really supports the kind of extension that I'm thinking of.
There is a factory which looks like this:
class XYZFactory
{
public:
static XYZFactory& getDefaultInstance() // so this is a singleton!
// ... some create methods
// std::unique_ptr<ABC> createABC();
private:
std::unique_ptr<XYZFactoryImpl> m_impl;
}
---
XYZFactory::XYZFactory() : m_impl(std::make_unique<XYZImpl>;
Now the problem is that I would like to extend the functionality of XYZImpl by deriving from it. I would like to avoid to expose that implementation detail however in the factory class, like adding a separate XYZFactory constructor with a ExtendedXYZImpl as an argument to inject that extension.
ADDED/EDITED for clarifaction: I should have called XYZImpl XYZFactoryImpl. It does the actual object creation. XYZFactory passes the createWhatever() calls to it. There is only one instance of XYZImpl which is held in m_Impl.
The thing that I actually want to be able to dynamically change is a member of XYZImpl m_ABC (instance of ABC) which is used for the object creation. I would like to derive from ABC.
Would killing the singleton design and subclassing from XYZFactory help?
Any ideas?
Thank you!
Mark
XYZFactory currently has a dependency on XYZFactoryImpl so clearly there is no way of injecting a dependency on ExtendedXYZImpl without exposing that functionality on XYZFactory. If that is unacceptable, the only alternative is to abandon the current design of XYZFactory.
There are not a great deal of constraints left in your question for us to use to form an answer but I suggest you start by making XYZFactory an abstract factory:
class XYZFactory {
public:
virtual ~XYZFactory(){}
virtual std::unique_ptr<ABC> createABC() const = 0;
}
With two implementations:
class XYZFactoryImpl : public XYZFactory {
public:
std::unique_ptr<ABC> createABC() const override {
return std::make_unique<ABC>();
}
};
class ExtendedXYZFactoryImpl : public XYZFactory {
public:
std::unique_ptr<ABC> createABC() const override {
return std::make_unique<DerivedABC>();
}
};
You can then provide a function to get a singleton instance and a way of reseating with a different singleton instance. e.g:
namespace details {
// Or this could be hidden in an anonymous namespace in a .cpp file
std::unique_ptr<XYZFactory>& getXYZFactoryInstanceMutable() {
static std::unique_ptr<XYZFactory> singleton = std::make_unique<XYZFactoryImpl>();
return singleton;
}
}
const XYZFactory& getXYZFactoryInstance() {
auto& singleton = details::getXYZFactoryInstanceMutable();
if (!singleton)
throw std::runtime_error("No XYZFactory registered");
return *singleton;
}
void setXYZFactoryInstance(std::unique_ptr<XYZFactory> new_factory) {
details::getXYZFactoryInstanceMutable() = std::move(new_factory);
}
Then to inject in your ExtendedXYZFactoryImpl you could do:
setXYZFactoryInstance(std::make_unique<ExtendedXYZFactoryImpl>());
auto abc = getXYZFactoryInstance().createABC();
Live demo.

How to make class addable to fabric via preprocessor defenitions?

Say we have a base fabric element interface:
class BaseFabricElenent {
public:
BaseFabricElenent(){}
virtual ~BaseFabricElenent(){}
virtual void action(){}
};
We have an enumeration:
enum TypeCode {
TypeCodeLive = 10,
TypeCodeDie = 100
};
And we have implementations for our TypeCodes.
We want to get a fabric that would return desired type by TypeCode as BaseFabricElenent* as normal fabric would do.
How to add types to fabric via preprocessor define?
say:
class LiveFabricElenent: pulic BaseFabricElenent {
public:
LiveFabricElenent() :
BaseFabricElenent(){}
virtual ~LiveFabricElenent(){}
virtual void action(){}
};
ADD_TO_FABRIC(LiveFabricElenent);
Update:
Found this helpfull article on registration of types into factory on global initialization phase
. Creating a Define that would generate stub classes for types registring is all that left.
I think you don't need a macro to achieve your purpose. If you must use the enum, do something like this:
class Fabric {
public:
BaseFabricElement* createElement(TypeCode typeCode) {
switch (typeCode) {
case TypeCodeLive: return new LiveFabricElement();
case TypeCodeDead: return new DeadFabricElement();
// ... other cases ...
default: return NULL;
}
}
};
If the creation process does not depend on Fabric state, then the createElement method can be static. I would also consider returning a smart pointer instead of a raw one, and renaming Fabric to Factory.

Can I avoid multiple inheritance here?

I am in a situation where I'm going to do a multiple inheritance (and the diamond of dread kind of). I'd like to avoid that, so hopefully someone has an idea to do it another way.
I want to make a library that handle network connections. I have an abstract factory with method to create a tcpServer, tcpClient, udp, and a last method that create an entry from a directory (config file is given to the init method of the factory). So I've created classes (actually interfaces) to this kind of connections. Entry is the base interface. To simplify, let's just say that it has methods to set data and status callback. All other classes (tcpClient ...) inherits from this one.
I want to do an implementation of this factory using boost, so I have to implement all the classes (tcpServer, …). The problem is that all class implementations require a common base. Here is what I'm going to do, but I'm not sure that's the right way to do it:
Here is the abstract part:
// The abstract factory:
class Factory
{
virtual IO::TcpServer* createTcpServer() = 0;
virtual IO::TcpClient* createTcpClient() = 0;
virtual IO::Entry* createFromConf() = 0;
};
// The Entry interface:
class Entry {
virtual bool isChild() const = 0;
// ...
virtual void setDataCbk() = 0;
virtual void setStateCbk() = 0;
};
// TcpClient interface
class TcpClient : public IO::Entry {
/* Nothing yet but stuff will come */
};
Here is the boost implementation (Class names are same but in different namespaces; I don't show the factory implementation):
// Entry first step of implementation (still abstract)
class Entry : public IO::Entry
{
virtual void setDataCbk();
virtual void setStateCbk();
};
// Flat entry : entry that can't have child (like tcp client, udp ...)
class FlatEntry : public IO::Boost::Entry
{
virtual bool isChild() const; // Will always return false
// ...
};
// The final TcpClient implementation
class TcpClient : public IO::TcpClient
, public IO::Boost::FlatEntry
{
// ...
};
So I'm worried about this multiple inheritance thing. On the other hand, super classe is a pure interface (no data, only pure virtual methods). Any ideas?