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)
Related
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.
Background Info
I am writing a graph-drawing program. I have encountered a problem with templates and inheritance, and I do not know how to proceed. I do not know how I should design my code to enable me to do what I am trying to do. (Explanation below.)
Target
I have a template class, which represents "data". It looks something like the following:
template<typename T>
class GraphData
{
std::vector<T> data_x;
std::vector<T> data_y; // x and y should be held in separate vectors
}
This class is part of an inheritance hierarchy involving several classes.
The hierarchy looks something like this... (Sorry this is from my notes, awful diagram.)
Explanation
There is a base class. No real reason to have it right now, but I anticipate using it later.
Base_Legend adds functionality for legend drawing. New members added include a std::string, and Get/Set functions.
Base_Drawable adds a pure abstract = 0 member. void Draw(...). This is to force overloading in all inherited objects which are drawable.
GraphData_Generic adds functionality for adding/removing data points to a set of vectors. These are pure abstract methods, and must be overridden by any data classes which inherit.
GraphData and HistogramData are 2 data types which have implementations of the functions from GraphData_Generic. (No implementation of Draw().)
GraphData_GenericDrawable doesn't do anything. It is to be used as a base class pointer, so that a vector of these objects can be used as data (add/remove data points) and can be draw (using void Draw()). This class also can be used to call the Get()/Set() methods for the std::string to be used in the legend.
Finally, at the bottom are GraphData_Drawable and HistogramData_Drawable which overload the void Draw() function. This code specifies exactly how the data should be drawn, depending on whether we have a Histogram or general set of data points.
Problem
Currently, I am using template types. The type of data for the datapoints / histogram bin values is specified by using a template.
For example, one can have a HistogramData<double, HistogramData_Drawable<double>, HistogramData_Drawable<int>, etc... Similarly, one can have GraphData<double>, GraphData<float>, GraphData_Drawable`, etc...
So hopefully it should be fairly obvious what's going on here without me uploading my ~ 10000 lines of code...
Right, so, in addition I have some class Graph, which contains a std::vector<GraphData_Generic_Drawable*>, hence the use of the base class pointer, as suggested above.
BUT! One has to decide what type of data should be used as the underlying type. I MUST choose either std::vector<GraphData_Generic_Drawable<double>*> or std::vector<GraphData_Generic_Drawable<float>*>.
This isn't useful, for obvious reasons! (I could choose double and force the user to convert all values manually, but that's just an easy way out which creates more work later on.)
A (very) ugly solution would be to have a std::vector<> for each possible type... int long unsigned long long double float unsigned char... etc...
Obviously this is going to be hideous and essentially repeat loads of code..
So, I intend to implement an AddData method which adds data to that vector, and I also currently have the following method:
// In class Graph
void DrawAll()
{
for(std::vector<GraphData_Drawable*>::iterator it = m_data.begin(); it != m_data.end(); ++ it)
(*iterator)->Draw(arguments);
} // Draw function takes arguments including a canvas to draw to, but this isn't directly relevant to the question
Which iterates over the vector and calls Draw for each set of data in there.
How to fix it?
My current thoughts are something along the lines of; I need to implement some sort of interface for an underlying data class, which retrieves values independent of the underlying type. But this is only a very vague initial idea and I'm not really sure how I would go about implementing this, hence the question... I'm not sure this is even what I should be doing...
If this isn't clear ask me a question and I'll update this with more details.
I have tried to read carefully all the advice given in the C++FAQ on this subject. I have implemented my system according to item 36.8 and now after few months (with a lot of data serialized), I want to make changes in both public interface of some of the classes and the inheritance structure itself.
class Base
{
public:
Vector field1() const;
Vector field2() const;
Vector field3() const;
std::string name() const {return "Base";}
};
class Derived : public Base
{
public:
std::string name() const {return "Derived";}
};
I would like to know how to make changes such as:
Split Derived into Derived1 and Derived2, while mapping the original Derived into Derived1 for existing data.
Split Base::field1() into Base::field1a() and Base::field1b() while mapping field1 to field1a and having field1b empty for existing data.
I will have to
deserialize all the gigabytes of my old data
convert them to the new inheritance structure
reserialize them in a new and more flexible way.
I would like to know how to make the serialization more flexible, so that when I decide to make some change in the future, I would not be facing conversion hell like now.
I thought of making a system that would use numbers instead of names to serialize my objects. That is for example Base = 1, Derived1 = 2, ... and a separate number-to-name system that would convert numbers to names, so that when I want to change the name of some class, I would do it only in this separate number-to-name system, without changing the data.
The problems with this approach are:
The system would be brittle. That is changing anything in the number-to-name system would possibly change the meaning of gigabytes of data.
The serialized data would lose some of its human readability, since in the serialized data, there would be numbers instead of names.
I am sorry for putting so many issues into one question, but I am inexperienced at programming and the problem I am facing seems so overwhelming that I just do not know where to start.
Any general materials, tutorials, idioms or literature on flexible serialization is most welcomed!
It's probably a bit late for that now, but whenever designing
a serialization format, you should provide for versionning.
This can be mangled into the type information in the stream, or
treated as a separate (integer) field. When writing the class
out, you always write the latest version. When reading, you
have to read both the type and the version before you can
construct; if you're using the static map suggested in the FAQ,
then the key would be:
struct DeserializeKey
{
std::string type;
int version;
};
Given the situation you are in now, the solution is probably to
mangle the version into the type name in a clearly recognizable
way, say something along the lines of
type_name__version; if the
type_name isn't followed by two underscore,
then use 0. This isn't the most efficient method, but it's
usually acceptable, and will solve the problem with backwards
compatibility, while providing for evolution in the future.
For your precise questions:
In this case, Derived is just a previous version of
Derived1. You can insert the necessary factory function into
the map under the appropriate key.
This is just classical versionning. Version 0 of Base has
a field1 attribute, and when you deserialize, you use it to
initialize field1a, and you initialize field1b empty.
Version 2 of Base has both.
If you mangle the version into the type name, as I suggest
above, you shouldn't have to convert any existing data. Long
term, of course, either some of the older versions simply
disappear from your data sets, so that you can remove the
support for them, or your program keeps getting bigger, with
support for lots of older versions. In practice, I've usually
seen the latter.
maybe Thrift Can help you do it.
This is a basic OO design question. I'm writing classes in C++ to represent items in a flow chart according to an input C file that have been parsed.
Simply we have 2 types of items (classes) : FlowChartActionItem and FlowChartConditionItem.
These represent Actions and Decision/Condition elements of a flowchart respectively. And they also represent Statements and If-conditions respectively, that existed in the input C file. Both classes inherit FlowChartItem.
Each sub-classes has a number of pointers to the items that comes after them; yes, we have a graph, with nodes(items) and links(pointers). But the FlowChartActionItem has only one outward pointer while the FlowChartConditionItem has 3 outward pointers (for the then-statements branch, the else-statements branch and a pointer to whatever comes after the both branches of the if-condition.
My problem is writing a neat setter for the outward pointers (nextItems). Take a look at the classes :
class FlowChartItem
{
public:
//I **need** this setter to stay in the parent class FlowChartItem
virtual void SetNextItem(FlowChartItem* nextItem, char index) = NULL;
};
-
class FlowChartActionItem:public FlowChartItem
{
public:
FlowChartItem* nextItem; //Only 1 next item
public:
void SetNextItem(FlowChartItem* nextItem, char index);
};
-
class FlowChartConditionItem: public FlowChartItem
{
public:
FlowChartItem* nextItem;
FlowChartItem* trueBranchItem;
FlowChartItem* falseBranchItem; //we have 3 next items here
public:
void SetNextItem(FlowChartItem* nextItem, char index);
};
I needed a generic setter that doesn't depend on the number of pointers the sub-class is having.
As you see I've used char index to tell the setter which pointer is to be set. But I don't like this and I need to make things neater. Because code won't be readable e.g :
item1.setNextItem(item2,1);
we don't remember what the 1 means? the then-branch ? the else ? ??
The obvious answer is to define an enum in FlowCharItem, but then we'll have one of two problems :
1- Enum values will be defined Now and will thus be tailored for the current sub-classes FlowChartActioItem and FlowChartConditionItem, so calls to SetNextItem on future sub-classes will have very bad readability. And even worse, they cannot have more than 3 outward pointers!
2- Solve the 1st problem by making developers of the future sub-classes edit the header file of FlowChartItem and add whatever values in the enum ! of course not acceptable!
What solution do I have in order to keep
-good readability
-neat extensibility of my classes ??
This is a form of a common architecture dilemma. Different child classes have a shared behavior that differs slightly and you need to somehow extract the common essence to the base class in a way that makes sense. A trap that you will typically regret is to let the child class functionality bleed into the parent class. For instance I would not recommend a set of potential enum names for types of output connections defined in FlowChartItem. Those names would only make sense in the individual child nodes that use them. It would be similarly bad to complicate each of your sub classes to accommodate the design of their siblings. Above all things, KIS! Keep. It. Simple.
In this case, it feels like you're overthinking it. Design your parent class around the abstract concept of what it represents and how it will be used by other code, not how it's inheritors will specialize it.
The name SetNextItem could just be changed to make it more clear what both of the parameters do. It's only the "next" item in the sense of your entire chart, not in the context of a single FlowChartItem. A flow chart is a directed graph and each node would typically only know about itself and it's connections. (Also, you're not writing visual basic, so containers index starting from 0! :-) )
virtual void SetOutConnectionByIndex(FlowChartItem* nextItem, char index);
Or if you prefer shorter names, then you could set the "N'th" output item: SetNthOutItem.
Since it not valid to set a child using an out-of-range index, then you probably want to have another pure virtual function in FlowChartItem that returns the maximum number of supported children and make SetChildByIndex return a success/failure code (or if you're one of those people, throw an exception) if the index is out of range.
virtual bool SetChildByIndex(FlowChartItem* item, char index);
Now... having written all that, I start to wonder about the code you have that will call this function. Does it really only know about each node as a FlowChartItem, but still needs to set it's children in a particular order which it doesn't know the significance of? This might be valid if you have other code which is aware of the real item types and the meaning of their child orderings and that code is providing the item pointers and their index numbers to the code that does the setting. Maybe de-serialization code, but this is not the right way to handle serialization. Is FlowChartItem exposed through a strict API and the chart is built up by code that knows of the different types of flow chart items but does not have access to the actual classes? Maybe valid in that case, but I'm speculating now well beyond the details you've provided.
But if this function is only going to be called by code that knows the real item type, has access to the actual class, and knows what the index means, then this probably shouldn't be in the base class at all.
I can, however, imagine lots of types of code that would need to fetch a FlowChartItem's children in order, without knowing the significance of that order. Code to draw your flow chart, code to execute your flow-chart, whatever. If you cut your question down for brevity and are also thinking about similar getter method, then the above advice would apply (though you could also consider an iterator pattern).
I'm sidestepping your dubious need for a "generic" SetNextItem in the base class, and will propose a way you can implement your idea.
You could store FlowChartItem* items in a std::map<std::string, FlowChartItems*> (what I call an adjacency map), and set the items by name. This way, subclasses can have as many adjacencies as they want and there's no need to maintain a central enum of adjacency types.
class FlowChartItem
{
public:
virtual void SetAdjacency(FlowChartItem* item, const std::string &type)
{
// Enforce the use of a valid adjacency name
assert(NameSet().count(type) != 0);
adjacencyMap_[name] = nextItem
}
protected:
// Subclasses must override this and return a set of valid adjacency names
const std::set<std::string>& NameSet() = 0;
std::map<std::string, FlowChartItem*> adjacencyMap_;
};
class FlowChartActionItem : public FlowChartItem
{
public:
// Convenience member function for when we're dealing directly
// with a FlowChartActionItem.
void SetNextItem(FlowChartItem* item) {SetAdjacency(item, "next");}
protected:
const std::set<std::string>& NameSet()
{
// Initialize static nameSet_ if emtpy
return nameSet_;
}
private:
// One set for the whole class (static).
const static std::set<std::string> nameSet_;
static std::set<std::string> MakeNameSet()
{
std::set<std::string> names;
names.insert("next");
return names;
}
}
// Initialize static member
const std::set<std::string> FlowChartActionItem::nameSet_ =
FlowChartActionItem::MakeNameSet();
Usage:
item1.SetAdjacency(&item2, "next");
I needed a generic setter that doesn't depend on the number of
pointers the sub-class is having.
The only way to have a mutable structure like this is to allow the client to access a data structure, say, std::vector<FlowChartItem*> or std::unordered_map<unsigned int, FlowChartItem*> or whatever. They can read it and set the values.
Fundamentally, as long as you're trying to dynamically set static items, you're going to have a mess. You're trying to implement your own, highly primitive, reflection system.
You need to have dynamic items if you want them to be dynamically set without a language-built-in reflection system or endlessly wasting your life jerking around trying to make it work.
As a bonus, if you have something like that, the use case for your derived classes just got a lot lower, and you could maybe even get rid of them. WinRARâ„¢.
Before anything, thanks for reading!
I'm developing an application in C++ and I want an advice about a design issue. Let me explain:
The main class of my application has some collections, but other classes eventually need to get a value from one of those collections. Something like this:
class MainClass {
private:
// Collections are internally implemented as QHash
Collection<Type1> col1;
Collection<Type2> col2;
};
class RosterUnit {
public:
RosterUnit() {
/* This method needs to get a specific value from col1 and
initialize this class with that data */
}
};
class ObjectAction {
public:
virtual void doAction() = 0;
};
class Action1 : public ObjectAction {
public:
void doAction() {
// This needs a specific value from col2
}
};
class Action2 : public ObjectAction {
public:
void doAction() {
// This needs a specific value from col1
}
};
My first approach was passing the whole collection as parameter when needed, but it is not so good for ObjectAction subclasses, because I would have to pass the two collections and if I later create another subclass of ObjectAction and it needs to get an element from other collection (suppose col3), I would have to modify the doAction() signature of every ObjectAction subclass, and I think that is not too flexible. Also, suppose I have a Dialog and want to create a RosterUnit from there. I would have to pass the collection to the dialog just to create the RosterUnit.
Next I decided to use static variables in RosterUnit and ObjectAction that pointed to the collections, but I'm not very happy with that solution. I think it is not flexible enough.
I have been reading about design patterns and I first thought a Singleton with get functions could be a good choice, but after some more investigation I think it isn't a proper design for my case. It would be easier and more or less the same if I use global variables, which don't seem to be the right way.
So, could you give some advices, please?
Thank you very much!
As mentioned previously, Iterators are good for abstracting away the details of the Collection. But going this route implies that the objects that use the Iterators will need to know about what's inside the Collection. Meaning they will need to know how to decide which object in the Collection they need, thus increasing the coupling. (more details below in the Factory paragraph) This is something you need to consider.
Another approach would be to create accessor methods on the MainClass that take some sort of key and return an object from the Collection (findObject(key)). Internally the MainClass methods would search through the container(s) and return the appropriate object. To use this approach, you will however need access to the MainClass, either by dependancy injection as mentioned before, or possibly making it a Singleton (not recomended in this scenario, though).
With the info provided so far, it may even be better for your ObjectAction Factory to have a reference to the MainClass, and as a part of the ObjectAction creation logic, call the appropriate MainClass accessor and pass the result into the ObjectAction, thus decoupling the ObjectAction Objects from the MainClass.
You probably want to use iterators, they exist exactly for the purpose of abstracting away sequences from specific containers.
If your issue is how to pass the iterators to the code that needs them in the first place, do not give in to the temptation to use globals. It may look more convoluted if you have to pass parameters in, but your code is that much more decoupled for it. "Dependency Injection" is a good keyword if you want to read more about this topic.
I would also advise you to check out std::function or boost::function instead of inheriting from ObjectAction. Functional style is getting more common in modern C++, as opposed to how it's usually done in languages like Java.
There's not enough information here of what you are trying to do. You make it sound like 'at some point in the future, this statically created action needs this data that was left behind.' How does that make any sense? I would say either construct the actions with the data, as you would for instance with a Future or Callable), or have the command ask for the next piece of data, in which case you are just implementing a Work queue.
Sounds like you are trying to do something like a thread pool. If these actions are in any way related, then you should have then in some composing object, implementing something like the Template Method pattern, e.g. execute() is abstract and calls a few other methods in a fixed sequence and that cannot be overridden, the other methods must be (protocol enforcement).