Strategy pattern vs Inheritance - c++

We have some algo to apply over some data, and the algo may get applied multiple times on same data. We have two ways to do this:
Keep data and logic seperate
class Algo{
public:
virtual int execute(data_object) = 0;
};
class AlgoX: public Algo{
public:
int execute(data_object);
};
class AlgoY: public Algo{
public:
int execute(data_object);
};
class Data{
public:
string some_values;
...
void* algo_specific_data; //It will contain some algo specific data (like state of algo)
Algo* algo_ptr; //Reference of Algo
int execute(){
algo_ptr->execute(this);
}
};
some_function(){
Data* data_object = create_data(algo_ptr, algo_specific_data); //A dummy function which creates an object of type data.
data_object->execute();
}
Bind data and logic by inheritance
class Data{
public:
string some_values;
...
virtual int execute() = 0;
};
class DataWithAlgoX : public Data{
public:
AlgoX_Relateddata algo_related_data; //some algo specific data (like state of algo)
int execute();
}
class DataWithAlgoY : public Data{
public:
AlgoY_Relateddata algo_related_data; //some algo specific data (like state of algo)
int execute();
}
some_function(){
Data* data_object = create_data(algo_type); //A dummy function which creates an object of type data.
data_object->execute();
}
Which design is better, if
We can change algo type between the multiple calls of algo->execute() on data
(But switching will not be very frequent, and needed only in some specific scenario).
Some people may point out that switching of algo will make us to recreate the data_object.
We are willing to take that extra burden if architecture 2 is much better than 1.
We will not change algo type ever between the multiple calls of algo->execute() on data .

Mixing Data and Algorithm in the same class in (very) bad practice.
In breaks the Single Resposability Principle.
https://en.wikipedia.org/wiki/Single_responsibility_principle
If you want to combine multiple types of Data with multiple Algorithms
use something like a Mediator. The idea is to define Data and Algorithms separately and define the interaction between them in the mediator.
https://en.wikipedia.org/wiki/Mediator_pattern
In my opinion, design 2 is MUCH worse then 1. And even in the case of design 1, I would remove the reference to the algorithm in the Data class. It only introduces High Coupling, i. e. a dependecy between the classes which make one affected bt the changes in the other:
https://en.wikipedia.org/wiki/Coupling_(computer_programming)
(and google "Low coupling, high cohesion", it is another OOP principle).
The Mediator would solve the coupling problem too.

I would prefer keeping Algo separate from Data always. In general Same data could be used for different Algo and same Algo can be used on different Data. So if you are implementing it as an inheritance chances are high that it will lead to code duplication or combinatorial explosion of subclasses like DataWithAgloA DataWithAlgoB.
More importantly Data provider i.e the system which generates data might not need to know about complex algorithms to be used there. It could be very well dumb system to generate data and there could be researchers who are updating the Algo. Keeping Data and Algo essentially violates Single Responsible Principle. Now your DataWithAlgo class has 2 axis of change (As uncle bob would say) from Algo and from Data.
Keeping Data and Algo separate keeps both the code nimble and easy to change and also satisfy SRP. This reduce coupling in the code, avoids any combinatorial explosion. So I would always go segregating Algo from Data.

Strategy pattern vs Inheritance
Between these two, favor the first over the latter. In inheritance, not only are you inheriting the API contract, you're also inheriting behavior, which may or may not be possible to override. And in your case, since you state that multiple algorithms may be applied to the same class today but not necessarily tomorrow, applying inheritance this way will lead to an explosion of classes and duplicate code, as you've shown.
However,
We have two ways to do this
How come? Have you considered the Decorator Pattern (my favorite)? Depending on how your data nodes are structured, perhaps even the Visitor Pattern is a valid choice.
I would also caution against the blanket "mixing data and algorithm always breaks SRP" advise generally thrown around. You introduce "2 axis of change" only when the use-case actually arises. Ideally, if you have perfect encapsulation, there is no reason why a type can't handle and apply algorithms to its own data. This depends on the domain; in your case, this clearly does not (seem to?) apply.

Related

Should I make a class polymorphic if only one of its methods should behave differently depending on the object's data type?

I have a class Group containing a vector of objects of another class Entry. Inside the Group I need to frequently access the elements of this vector(either consequently and in random order). The Entry class can represent a data of two different types with the same properties(size, content, creation time etc.). So all of the members and methods of the Entry class are the same for both data types, except for one method, that should behave differently depending on the type of the data. It looks like this:
class Entry
{
public:
// ...
void someMethod();
// ...
private:
TYPE type_;
// ...
};
class Group
{
private:
// ...
std::vector<Entry> entries_;
// ...
};
void Entry::someMethod()
{
if (type_ == certainType)
{
// Do some stuff
}
else if (type_ == anotherType)
{
// Do some different stuff
}
}
Given the abilities of C++ regarding OOP, this approach seems unnatural to me. I am thinking about creation of two distinct classes inherited from the Entry class and overriding only this someMethod() in those classes:
class Entry
{
// ...
virtual void someMethod() = 0;
// ...
};
class EntryType1 : public Entry
{
// override someMethod() here
};
class EntryType2 : public Entry
{
// override someMethod() here
};
But doing so means reducing the efficiency of cache usage, because now inside the Group class I have to replace the vector of Entry objects placed in a contiguous memory area with the vector of pointers to Entry base class objects scattered all over the memory address space.
The question is - is it worth it to make a class polymorphic just because of one only among many other of its methods is needed to behave differently depending on the data type? Is there any better approach?
is it worth it to make a class polymorphic just because of one only among many other of its method is needed to behave differently depending on the data type?
Runtime polymorphism starts to provide undeniable net value when the class hierarchy is deep, or may grow arbitrarily in future. So, if this code is just used in the private implementation of a small library you're writing, start with what's more efficient if you have real reason to care about efficiency (type_ and if), then it's not much work to change it later anyway. If lots of client code may start to depend your choices here though, making it difficult to change later, and there's some prospect of further versions of someMethod() being needed, it's probably better to start with the virtual dispatch approach.
Is there any better approach?
Again - what's "better" takes shape at scale and depends on how the code is depended upon, updated etc.. Other possible approaches include using a std::variant<EntryType1, EntryType2>, or even a std::any object, function pointers....
If you are absolutely sure that there are only two types of Entry, then using an if inside the function's implementation is, to me, a perfectly valid approach. In this case, I would advise you to use if constexpr to further indicate that this is a compile-time behavioral decision and not a runtime one. (As pointed out by Tony Delroy, if constexpr is not viable).
If, however, you are unsure if you are going to need more Entry types in the future, the if approach would only hurt you in the long run. If you need the scalability, I would advise you to make the Entry class hold a std::function internally for only that specific behavior that needs polymorphism: this way you're only paying for indirection when you actually need the functionality.
You could also make two factory functions make_Entry1 and make_Entry2 that construct an Entry passing it the specific std::function that yields the desired behavior.

C++ Model View Design

I am currently struggling with the design of an application of the visualization and manipulation of sensor data. I have a database that contains several STL-containers with measured data in it.
std::unordered_map<std::string, std::array<uint16_t, 3366>> data1;
std::unordered_map<std::string, QImage> data2;
std::unordered_map<std::string, std::vector<Point3D>> data3;
I also have different Views (mostly Qt-based) and each view should be associated with a model which is specific to one of the data sets. So data1 is supposed to be processed and manipulated in a class called model1 which is then displayed by means of a class view1 and so forth.
But I cant seem to find a suitable design structure to incorporate this idea. the models grant access to their processed data, but that data is contained in different container structures as given above. That makes it unfeasible to use inheritance with a pure virtual function in the base class like
std::map<...,...> getModelData() = 0;
The initial idea of this inheritance was to avoid code duplication but that doesnt seem to be the right solution here. I know that Qt in their "Model-View" concepts makes use of their QVariant class to have maximum flexibility in terms of types being returned. However, I am wondering, what is the best solution with standard C++ here? I read a lot about striving for loose-coupling, code reuseability, Dependendy Inversion and how to favour composition over inheritance but I do have problems putting these theoretical advise into practice and end up with code bloat and repetitive code most of the times. Can you help me?
Maybe you can give more code but so far, I can give a few hints:
-Can you use QMap instead of std::unordered_map ? It is more agile if you need to tangle with a UI
-Maybe make your second argument of the list a common base type like (code not tested, treat as pseudo code)
class BaseDataClass
{
public:
int getType();
QImage* getImageData();
std::array<uint16_t, 3366>>& getArray();
std::vector<Point3D>>& getVector();
private:
int mType;
BaseDataClass(); //hide ctor or make abstract, as you wish
}
You can avoid code duplicating with this. Make three new classes that each inherit from BaseDataClass. You can then make a method that iterates over all BaseDataClass, checks the type (e.g. 1=QImage; 2 = array ; 3 = vector), and exectues the right method according to the type (get QImage from all type 1`s ...). You also can cast the pointer to the right type then. Which makes it even better if your derived classes gain more and more functionality (like sorting or validating data)

OOP design issue: inheritance vs. interface discovery

Sorry for the lack of a better title; I couldn't think of a better one.
I have a class hierarchy like the following:
class Simulator
{
public:
virtual void simulate(unsigned int num_steps);
};
class SpecializedSimulator1 : public Simulator
{
Heap state1; Tree state2; // whatever
public:
double speed() const;
void simulate(unsigned int num_steps) override;
};
class SpecializedSimulator2 : public Simulator
{
Stack state1; Graph state2; // whatever
public:
double step_size() const;
void simulate(unsigned int num_steps) override;
};
class SpecializedSubSimulator2 : public SpecializedSimulator2
{
// more state...
public:
// more parameters...
void simulate(unsigned int num_steps) override;
};
class Component
{
public:
virtual void receive(int port, string data);
virtual void react(Simulator &sim);
};
So far, so good.
Now it gets more complicated.
Components can support one or more types of simulation. (For example, a component that negates its input may support Boolean circuits as well as continuous-time simulation.) Every component "knows" what kinds of simulations it supports, and given a particular kind of simulator, it queries the simulator (via dynamic_cast or double dispatch or whatever means are appropriate) to find out how it needs to react.
Here's where it gets tricky:
Some Components (say, imagine a SimulatorComponent class) themselves need to run sub-simulations inside of them. Part of this involves inheriting some properties of outer simulations, but potentially changing a few of them. For example, a continuous-time sub-simulator might want to lower its step size for its internal components in order to get better accuracy, but otherwise keep everything else the same.
Ideally, SimulatorComponent would be able to inherit from a class (say, SpecializedSimulator2) and override some subset of its properties as desired. The trouble, though, is that it has no idea whether the outer simulator's most-derived type is a SpecializedSimulator2 -- it may very well be the case that SimulatorComponent is running inside a more specialized simulator than that, like a SpecializedSubSimulator2! In that case, sub-components of SimulatorComponent would need to be able to somehow get access to the properties of SpecializedSubSimulator2 that they might need to access, but SimulatorComponent itself would not (and should not) be aware of these properties.
So, we see we can't use inheritance here.
Since the only means in C++ for "discovering" sub-interfaces like this is dynamic_cast, that means the sub-components must be able to directly access the outer simulator themselves, in order to run dynamic_cast on them. But if they do this, then SimulatorComponent can't intercept any of the calls.
At this point, I'm not sure what to do. The problem isn't impossible to solve, obviously -- I can think of some solutions (e.g. hierarchical key/value dictionary maintained at run-time) -- but the solutions involves some massive tradeoffs (e.g. less compile-time checking, performance loss, etc.) and make me wonder what I should be doing.
So, basically: how should I approach this problem? Is there a flaw in my design? Should I be solving this problem differently? Is there a design pattern for this that I'm just not aware of? Any tips?
I'll try to give a partial advice. For the situation in which you need to use a simulator inheriting properties from some parent then a cloning function could be the solution. This way you can ignore what actually the original simulation was, but anyway you end up with a new one with the same props.
It may just require some basic properties (like the simulation time step) which means you need to dynamic_cast to some intermediate class in your simulator hierarcy, but not exactly spot the right one.

Pattern for choosing behaviour based on the types present in a collection derived objects

I have an collection of objects which represents a model of a system. Each of these objects derives from a base class which represents the abstract "component". I would like to be able to look at the system and choose certain behaviours based on what components are present and in what order.
For the sake of argument, let's call the base class Component and the actual components InputFilter, OutputFilter and Processor. Systems that we can deal with are ones with a Processor and one or both filters. The actual system has more types and more complex interaction between them, but I think this will do for now.
I can see two "simple" ways to handle this situation with a marshalComponentSettings() function which takes one of the collections and works out how to most efficiently set up each node. This may require modifying inputs in certain ways or splitting them up differently, so it's not quite as simple as just implementing a virtual handleSettings() function per component.
The first is to report a enumerated type from each class using a pure virtual function and use those to work out what to do, dynamic_cast'ing where needed to access component specific options.
enum CompType {
INPUT_FILTER,
OUTPUT_FILTER,
PROCESSOR
}
void marshal(Settings& stg)
{
if (comps[0].type() == INPUT_FILTER)
setUpInputFilter(stg); //maybe modified the stg, or provides other feedback of what was done
// something similar for outputs
setUpProcessor(stg);
}
The second is to dynamic_cast to anything that might be an option in this function and use the success of that or not (as well as maybe the cast object if needed) to determine what to do.
void marshal(Settings& stg)
{
if (InputFilter* filter = dynamic_cast<InputFilter*>(comp[0]))
setUpInputFilter(stg); //maybe modified the stg, or provides other feedback of what was done
// something similar for outputs
setUpProcessor(stg);
}
It seems that the first is the most efficient way (don't need to speculatively test each object to find out what it is), but even that doesn't quite seem right (maybe due to the annoying details of how those devices affect each other leaking into the general marshaling code).
Is there a more elegant way to handle this situation than a nest of conditionals determining behaviour? Or even a name for the situation or pattern?
Your scenario seems an ideal candidate for the visitor design pattern, with the following roles (see UML schema in the link):
objectStructure: your model, aka collection of Component
element: your Component base class
concreteElementX: your actual components (InputFilter, OutputFilter, Processor, ...)
visitor: the abstract family of algorithms that has to manage your model as a consistent set of elements.
concreteVisitorA: your configuration process.
Main advantages:
Your configuration/set-up corresponds to the design pattern's intent: an operation to be performed on the elements of an object structure. Conversely, this pattern allows you to take into consideration the order and kind of elements encountered during the traversal, as visitors can be stateful.
One positive side effect is that the visitor pattern will give your desing the flexibility to easily add new processes/algortihms with similar traversals but different purpose (for example: pricing of the system, material planning, etc...)
class Visitor;
class Component {
public:
virtual void accept(class Visitor &v) = 0;
};
class InputFilter: public Component {
public:
void accept(Visitor &v) override; // calls the right visitor function
};
...
class Visitor
{
public:
virtual void visit(InputFilters *c) = 0; // one virtual funct for each derived component.
virtual void visit(Processor *c) = 0;
...
};
void InputFilter::accept(Visitor &v)
{ v.visit(this); }
...
class SetUp : public Visitor {
private:
bool hasProcessor;
int impedenceFilter;
int circuitResistance;
public:
void visit(InputFilters *c) override;
void visit(Processor *c) override;
...
};
Challenge:
The main challenge you'll have for the visitor, but with other alternatives as well, is that the setup can change the configuration itself (replacing component ? change of order), so that you have to take care of keeping a consitent iterator on the container while making sure not to process items several time.
The best approach depends on the type of the container, and on the kind of changes that your setup is doing. But you'll certainly need some flags to see which element was already processed, or a temporary container (either elements processed or elements remaining to be processed).
In any case, as the visitor is a class, it can also encapsulate any such state data in private members.

Inheritance vs specific types in Financial Modelling for cashflows

I have to program some financial applications where I have to represent a schedule of flows. The flows can be of 3 types:
fee flow (just a lump payment at some date)
floating rate flow (the flow is dependant of an interest rate to be determined at a later date)
fixed rate flow (the flow is dependant of an interest rate determined when the deal is done)
I need to keep the whole information and I need to represent a schedule of these flows.
Originally I wanted to use inheritance and create three classes FeeFlow, FloatingFlow, FixedFlow all inheriting from ICashFlow and implement some method GetFlowType() returning an enum then I could dynamic_cast the object to the correct type.
That would allow me to have only one vector<IFlow> to represent my schedule.
What do you think of this design, should I rather use three vectors vector<FeeFlow>, vector<FloatingFlow> and vector<FixedFlow> to avoid the dynamic casts ?
Why do you actually need the dynamic casts? Make your flow subclasses implement the same interface polymorphically, then there is no need to cast anything.
If they need very different inputs, you could try passing the different inputs as constructor parameters, thus clearing up the common interface. However, if you really can't define a common interface for them, maybe they are better implemented as independent classes.
If all the operations you need to do with the different types of the flow differ only by the underlying data, i would suggest extending the ICashFlow with such operations - then no dynamic casting is needed. If however this is not possible, then both options are ok i think. I personally would choose the one with the three vectors, if there is no other hidden need for one vector of base classes.
I think the strategy pattern would suit you best.
You implement a CashFlow class that contains a CashFlowStrategy property which does the processing.
I do not fully understand the requirements and the differences between the flows but something like this might work (meta-c++, not valid code):
class CashFlowStrategy {
public:
virtual void ProcessFlow(Account from, Account to);
}
class FixedRateCashFlowStrategy : public CashFlowStrategy {
public:
void ProcessFlow(Account from, Account to) { ... }
}
class CashFlow {
private:
CashFlowStrategy strategy;
public:
CashFlow(CashFlowStrategy &strategy) { this->strategy = strategy; }
void Process() { this->strategy->ProcessFlow(this->from, this->to); }
}
You only need the std::vector<CashFlow>, the decision of how to do the processing is hidden in the strategy so you shouldn't have to care about it.
It sounds like you have various schedules and various types of deposits, which collectively make up a financial flow. The solution sounds as if a strategy pattern may work for both schedule and deposit behavior. Although, if you have room, it might be worth considering a functional approach. A lambda expression would give you the same logic with a tenth of the code ...