Design issues - observer,factory, composition and more - c++

So i need to design something like that :
I have a spreadsheet which can contain numerous sheets (maybe of different kinds).
each sheet has let's say 1A-9Z cells.
in each cell i can have one the above :
String,
Number,
Formula - which means the cell gets an operation like +,-,/,* etc... and cells numbers,
and in the cell i have the result of the operation.
I need to design the classes, so in the future i can add other type of cells (besides string/number/formula) and add also different kind of operation to the formula - all in an easy manner.
how would u design it ?
I though about something like this :
class SpreadSheet
{
private:
vector<Isheet> sheets;
public:
write(Isheet sheet,int CellNum,ICell value);
GetValue(Isheet sheet,int CellNum,ICell value);
AddSheet(ISheet sheet);
};
class Isheet
{
vector<ICell> cells; // can i do something like that ? cause ICell is a template
};
template<class T>
class ICell
{
Vector<Iobserver> observers;
public:
T GetValue() {return m_value;};
SetValue(T val) {m_value=val;};
AddObserver(Iobserver obs);
NotifyAll();
GetPos() {return m_pos;};
private:
T m_value;
int m_pos;
};
class CInt : public ICell<int>
{
};
class CString : public ICell<std:string>
{
};
class CFormula : public ICell<int>, Iobserver
{
};
class Iobserver
{
Update(int pos);
};
anyway, i'm really not sure where should i create the cell Concrete classes (CInt,Cstring,CFormula), should i use some kind of factory ? where to put the factory ? inside ISheet ?
and my main concern, where should i calculate the the right result for a CFormula cell ?
i used the observer pattern to keep the formula cell updated in case of other cell's changes.
any advices would be great

As an engineer to whom 'design pattern' means very little, I recently had the pleasure of working on a project (ongoing) with some computer scientists. I have implemented all of the things they call 'observer patterns', 'factories', 'reactors', etc before, but to be honest I found it a thoroughly unhelpful way to think about design.
What you need is a solution to your problem. Think about: data flow, think about execution paths, think about what needs to cause what.
Don't try to shoe-horn your problem into a textbook solution, likelihood is, it won't fit very well, and you'll end up with far more levels of abstraction than are useful, and which make the code very difficult to understand when you return to it months later.
My two cents, hope this is helpful.

Related

c++ particle system inheritance

i'm creating particle system and i want to have possibility to choose what kind of object will be showing on the screen (like simply pixels, or circle shapes). I have one class in which all parameters are stored (ParticleSettings), but without those entities that stores points, or circle shapes, etc. I thought that i may create pure virtual class (ParticlesInterface) as a base class, and its derived classes like ParticlesVertex, or ParticlesCircles for storing those drawable objects. It is something like that:
class ParticlesInterface
{
protected:
std::vector<ParticleSettings> m_particleAttributes;
public:
ParticlesInterface(long int amount = 100, sf::Vector2f position = { 0.0,0.0 });
const std::vector<ParticleSettings>& getParticleAttributes() { return m_particleAttributes; }
...
}
and :
class ParticlesVertex : public ParticlesInterface
{
private:
std::vector<sf::Vertex> m_particleVertex;
public:
ParticlesVertex(long int amount = 100, sf::Vector2f position = { 0.0,0.0 });
std::vector<sf::Vertex>& getParticleVertex() { return m_particleVertex; }
...
}
So... I know that i do not have access to getParticleVertex() method by using polimorphism. And I really want to have that access. I want to ask if there is any better solution for that. I have really bad times with decide how to connect all that together. I mean i was thinking also about using template classes but i need it to be dynamic binding not static. I thought that this idea of polimorphism will be okay, but i'm really need to have access to that method in that option. Can you please help me how it should be done? I want to know what is the best approach here, and also if there is any good answer to that problem i have if i decide to make that this way that i show you above.
From the sounds of it, the ParticlesInterface abstract class doesn't just have a virtual getParticleVertex because that doesn't make sense in general, only for the specific type ParticlesVertex, or maybe a group of related types.
The recommended approach here is: Any time you need code that does different things depending on the actual concrete type, make those "different things" a virtual function in the interface.
So starting from:
void GraphicsDriver::drawUpdate(ParticlesInterface &particles) {
if (auto* vparticles = dynamic_cast<ParticlesVertex*>(&particles)) {
for (sf::Vertex v : vparticles->getParticleVertex()) {
draw_one_vertex(v, getCanvas());
}
} else if (auto* cparticles = dynamic_cast<ParticlesCircle*>(&particles)) {
for (CircleWidget& c : cparticles->getParticleCircles()) {
draw_one_circle(c, getCanvas());
}
}
// else ... ?
}
(CircleWidget is made up. I'm not familiar with sf, but that's not the point here.)
Since getParticleVertex doesn't make sense for every kind of ParticleInterface, any code that would use it from the interface will necessarily have some sort of if-like check, and a dynamic_cast to get the actual data. The drawUpdate above also isn't extensible if more types are ever needed. Even if there's a generic else which "should" handle everything else, the fact one type needed something custom hints that some other future type or a change to an existing type might want its own custom behavior at that point too. Instead, change from a thing code does with the interface to a thing the interface can be asked to do:
class ParticlesInterface {
// ...
public:
virtual void drawUpdate(CanvasWidget& canvas) = 0;
// ...
};
class ParticlesVertex {
// ...
void drawUpdate(CanvasWidget& canvas) override;
// ...
};
class ParticlesCircle {
// ...
void drawUpdate(CanvasWidget& canvas) override;
// ...
};
Now the particles classes are more "alive" - they actively do things, rather than just being acted on.
For another example, say you find ParticlesCircle, but not ParticlesVertex, needs to make some member data updates whenever the coordinates are changed. You could add a virtual void coordChangeCB() {} to ParticlesInterface and call it after each motion model tick or whenever. With the {} empty definition in the interface class, any class like ParticlesVertex that doesn't care about that callback doesn't need to override it.
Do try to keep the interface's virtual functions simple in intent, following the Single Responsibility Principle. If you can't write in a sentence or two what the purpose or expected behavior of the function is in general, it might be too complicated, and maybe it could more easily be thought of in smaller steps. Or if you find the virtual overrides in multiple classes have similar patterns, maybe some smaller pieces within those implementations could be meaningful virtual functions; and the larger function might or might not stay virtual, depending on whether what remains can be considered really universal for the interface.
(Programming best practices are advice, backed by good reasons, but not absolute laws: I'm not going to say "NEVER use dynamic_cast". Sometimes for various reasons it can make sense to break the rules.)

C++ Help on refactoring a monster class

I have a C background and am a newb on C++. I have a basic design question. I have a class (I'll call it "chef" b/c the problem I have seems very analogous to this, both in terms of complexity and issues) that basically works like this
class chef
{
public:
void prep();
void cook();
void plate();
private:
char name;
char dish_responsible_for;
int shift_working;
etc...
}
in pseudo code, this gets implemented along the lines of:
int main{
chef my_chef;
kitchen_class kitchen;
for (day=0; day < 365; day++)
{
kitchen.opens();
....
my_chef.prep();
my_chef.cook();
my_chef.plate();
....
kitchen.closes();
}
}
The chef class here seems to be a monster class, and has the potential of becoming one. chef also seems to violate the single responsibility principle, so instead we should have something like:
class employee
{
protected:
char name;
int shift_working;
}
class kitchen_worker : employee
{
protected:
dish_responsible_for;
}
class cook_food : kitchen_worker
{
public:
void cook();
etc...
}
class prep_food : kitchen_worker
{
public:
void prep();
etc...
}
and
class plater : kitchen_worker
{
public:
void plate();
}
etc...
I'm admittedly still struggling with how to implement it at run time so that, if for example plater (or "chef in his capacity as plater") decides to go home midway through dinner service, then the chef has to work a new shift.
This seems to be related to a broader question I have that if the same person invariably does the prepping, cooking and plating in this example, what is the real practical advantage of having this hierarchy of classes to model what a single chef does? I guess that runs into the "fear of adding classes" thing, but at the same time, right now or in the foreseeable future I don't think maintaining the chef class in its entirety is terribly cumbersome. I also think that it's in a very real sense easier for a naive reader of the code to see the three different methods in the chef object and move on.
I understand it might threaten to become unwieldy when/if we add methods like "cut_onions()", "cut_carrots()", etc..., perhaps each with their own data, but it seems those can be dealt with by having making the prep() function, say, more modular. Moreover, it seems that the SRP taken to its logical conclusion would create a class "onion_cutters" "carrot_cutters" etc... and I still have a hard time seeing the value of that, given that somehow the program has to make sure that the same employee cuts the onions and the carrots which helps with keeping the state variable the same across methods (e.g., if the employee cuts his finger cutting onions he is no longer eligible to cut carrots), whereas in the monster object chef class it seems that all that gets taken care of.
Of course, I understand that this then becomes less about having a meaningful "object oriented design", but it seems to me that if we have to have separate objects for each of the chef's tasks (which seems unnatural, given that the same person is doing all three function) then that seems to prioritize software design over the conceptual model. I feel an object oriented design is helpful here if we want to have, say, "meat_chef" "sous_chef" "three_star_chef" that are likely different people. Moreover, related to the runtime problem is that there is an overhead in complexity it seems, under the strict application of the single responsibility principle, that has to make sure the underlying data that make up the base class employee get changed and that this change is reflected in subsequent time steps.
I'm therefore rather tempted to leave it more or less as is. If somebody could clarify why this would be a bad idea (and if you have suggestions on how best to proceed) I'd be most obliged.
To avoid abusing class heirarchies now and in future, you should really only use it when an is relationship is present. As yourself, "is cook_food a kitchen_worker". It obviously doesn't make sense in real life, and doesn't in code either. "cook_food" is an action, so it might make sense to create an action class, and subclass that instead.
Having a new class just to add new methods like cook() and prep() isn't really an improvement on the original problem anyway - since all you've done is wrapped the method inside a class. What you really wanted was to make an abstraction to do any of these actions - so back to the action class.
class action {
public:
virtual void perform_action()=0;
}
class cook_food : public action {
public:
virtual void perform_action() {
//do cooking;
}
}
A chef can then be given a list of actions to perform in the order you specify. Say for example, a queue.
class chef {
...
perform_actions(queue<action>& actions) {
for (action &a : actions) {
a.perform_action();
}
}
...
}
This is more commonly known as the Strategy Pattern. It promotes the open/closed principle, by allowing you to add new actions without modifying your existing classes.
An alternative approach you could use is a Template Method, where you specify a sequence of abstract steps, and use subclasses to implement the specific behaviour for each one.
class dish_maker {
protected:
virtual void prep() = 0;
virtual void cook() = 0;
virtual void plate() = 0;
public:
void make_dish() {
prep();
cook();
plate();
}
}
class onion_soup_dish_maker : public dish_maker {
protected:
virtual void prep() { ... }
virtual void cook() { ... }
virtual void plate() { ... }
}
Another closely related pattern which might be suitable for this is the Builder Pattern
These patterns can also reduce of the Sequential Coupling anti-pattern, as it's all too easy to forget to call some methods, or call them in the right order, particularly if you're doing it multiple times. You could also consider putting your kitchen.opens() and closes() into a similar template method, than you don't need to worry about closes() being called.
On creating individual classes for onion_cutter and carrot_cutter, this isn't really the logical conclusion of the SRP, but in fact a violation of it - because you're making classes which are responsible for cutting, and holding some information about what they're cutting. Both cutting onions and carrots can be abstracted into a single cutting action - and you can specify which object to cut, and add a redirection to each individual class if you need specific code for each object.
One step would be to create an abstraction to say something is cuttable. The is relationship for subclassing is candidate, since a carrot is cuttable.
class cuttable {
public:
virtual void cut()=0;
}
class carrot : public cuttable {
public:
virtual void cut() {
//specific code for cutting a carrot;
}
}
The cutting action can take a cuttable object and perform any common cutting action that's applicable to all cuttables, and can also apply the specific cut behaviour of each object.
class cutting_action : public action {
private:
cuttable* object;
public:
cutting_action(cuttable* obj) : object(obj) { }
virtual void perform_action() {
//common cutting code
object->cut(); //specific cutting code
}
}

multiple classes, same public interface

ok, after last night I've decided to rephrase my question for easier reading.
I have 2 classes, Army and Battle groups. heres the classes below, albeit with some parts missing:
class Battlegroups
{
private: battlegroup battlegroupobject[100];
public:
void AddBattleGroup(); //add a battlegroup object to the array
void removebattlegroup(); //remove a battle group objects from the array
};
class Army
{
private: battlegroups battlegroupsobject;
public:
void formbattlegroup()
{
battlegroupsobject.AddBattleGroup();
}
void disbandbattlegroup()
{
battlegroupsobject.removebattlegroup();
}
};
See, the problem is the formbattlegroup() and the disbandbattlegroup(), which seems like its adding a pointless interface.
if there is a way for me to access the Addbattlegroup and removebattlegroup() methods without doing the above, please tell me.
or, tell me if this is the way you do it, but to me, it seems like adding code, for the sake of code.
If Battlegroups is used only for containing objects, you may use battlegroup battlegroupobject[100] right in the Army instead. Or use std::vector<battlegroup> instead of battlegroups. If not (and anyway), your decision seems quite correct, because there are different responsibilities of these objects.
not very sure about your design, but here is my guess: you want to have Army, Navy etc. Then you may want to inherit Army, Navy from Battlegroups, such that you don't need to write AddBattleGroup and RemoveBattleGroup for every classes for Army, Navy etc . Like the following:
class Battlegroups
{
// side-note: you may want to replaced below by std::vector<battlegroup>
private: battlegroup battlegroupobject[100];
public:
void AddBattleGroup();
void RemoveBattleGroup();
};
class Army
: public Battlegroups
{
// other specific implementations
};
class Navy
: public Battlegroups
{
// other specific implementations
};
// usage
Army army1;
army1.AddBattleGroup();
Navy navy1;
navy1.AddBattleGroup();
If this is not what you want, you may want to consider Dmitry's answer.

Front-end/Back-end design: how to absolutely dissociate the back-end from the front-end?

My question is: (is the above|what is) the right way to create a non intrusive front-end?
I am explaining my problem with a simplified example.
I have a back-end implementing a binary tree:
// Back-end
struct Node
{
Label label;
Node* r, l;
};
I would like now to implement the front-end to print the tree graphically. So my idea is to extend the back-end with graphical properties by wrapping it :
// Front-end
struct Drawable
{
uint x, y;
};
class Visitor;
template <class T> struct GNode : public Drawable
{
T* wrapped;
template <class V> void accept(V& v); // v.visit(*this);
}
There is a problem now to create a visitor printing the binary tree:
struct Visitor
{
void visit(GNode<Node>& n)
{
// print the label and a circle around it: ok.
if (n.wrapped.l) // l is a Node, not a GNode, I can't use the visitor on it
// Problem: how to call this visitor on the node's left child?
// the same with n.wrapped.r
};
};
As explained in comments, the back-end does not use my extended class.
Writing GNode "is-a" Node is not a solution neither since I would have to put the accept() method in the Node class as virtual and override it in GNode but I can't modify the back-end. Then, someone could say too that there is no need to declare accept() in the back-end, downcasting Node* to GNode* would work. Yes it works, but it downcasts...
In my case, I have ~10 kinds of nodes (it is a graph), so I am looking for something elegant, flexible, with as few lines of code as possible (hence the wrapper template idea) :)
Thank you very much.
To absolutely disassociate code is impossible. They have to talk. If you really want to enforce decoupling to the maximal extent, some sort of IPC/RPC mechanism should be used and have two different programs.
That said -- I don't like visitor patterns.
You have a Graphical object, which is linked against a Behaving object. Maybe there are rules between behavior and the graphics, e.g., boundaries can't overlap.
You can do your entity relationship whatevers between the Graphicals and the Behaves, that's a biz logic question...
You will need some thungus that holds your drawing context (img, screen, buffer).
class DrawingThungus {
void queue_for_render(Graphical*);
void render();
};
Your Graphical will have either an inheritance or a composition relationship with behaves.
At any rate, they will have the interface needed to do Drawing.
//abstract base class class Graphical {
get_x();
get_y();
get_icon();
get_whatever();
};
If you are finding that your Render is becoming case-based depending on the kind of Graphical, I suggest pushing the cases over to the Graphical, and refactoring to have a get_primitives_list(), wherein the needed primitives are returned for Graphical to return (I am presuming that at some level, you have core primitives, lines, circles, arcs, labels, etc).
I have always found that OO analysis lends itself to wasting mental energy and should be done only enough for the task at hand. YAGNI is a tremendous principle.
If your wrapper class (GNode) didn't have to maintain any state across visits (i.e., it only had one field - the wrapped Node object), you could use a pointer or a reference to the wrapped object instead of a copy, and then you would be able to wrap any node at runtime.
But even if you do maintain state (the x,y coordinates), don't you really just infer it from the wrapped object? In that case, wouldn't it be better to separate your visited class from the inferred data? For instance, consider this implementation:
// This is an adapter pattern, so you might want to call it VisitorAdapter if you
// like naming classes after patterns.
template typename<T>
class VisitorAcceptor
{
private:
T& wrapped;
public:
VisitorAcceptor(T& obj)
{
wrapped = obj;
}
template <typename VisitorT>
void accept(VisitorT& v)
{
v.visit(wrapped);
}
};
struct GNode
{
uint x, y;
shared_ptr<GNode> l,r; // use your favourite smart pointer here
template <typename VisitorT>
void accept(VisitorT& v)
}
// You don't have to call a visitor implementation 'Visitor'. It's better to name
// it according to its function, which is, I guess, calculating X,Y coordinates.
{
shared_ptr<GNode> visit(Node& n)
{
shared_ptr<GNode> gnode = new GNode;
// calculate x,y
gnode->x = ...
gnode->y = ...
if (n.l)
gnode->l = VisitorAdapter(n.r).accept(*this);
if (n.r)
gnode->r = VisitorAdapter(n.l).accept(*this);
};
};
Now you can have a different visitor for drawing:
struct GNodeDrawer
{
void visit(GNode& gnode)
{
// print the label and a circle around it: ok.
if (n.r)
visit(n.l);
if (n.r)
visit(n.r);
};
};
Of course, if you don't need all the extensibility the visitor pattern offers, you can throw it away altogether and just walk the the tree recursively with XYCalculator.visit calling itself.
Personally, I would make a drawing class with overloaded functions (one for each node type) rather than trying to hook into the existing structure with some sort of complicated inheritance solution.
I finally found an "elegant" solution with the decorator design pattern.
This pattern is used to extend an object without changing its interface.
GNode decorates/extends Node:
template <class T> struct GNode : public T, public Drawable
{
virtual void accept(Visitor& v); // override Node::accept()
}
As you can see, it requires a little change in the back-end structure:
struct Node
{
Label label;
Node* r, l;
virtual void accept(Visitor& v);
};
That's it ! GNode is-a Node. We can now create a binary tree of GNodes and visit it thanks to the virtual method accept() in the back-end structure.
In the case when we absolutely follow my question, i.e. we can't modify the back-end and it doesn't have the virtual entry point presented above, we can add features to GNode mapping the Node it wraps to itself. So that a visitor visiting GNodes (that can only have access to its sons) can find the GNodes of its sons. Yes, this is the virtual keyword job with the above solution! But we never know if someone would be in this case for real.
As a conclusion to all this: the way you express a problem always influences the way to resolve it.

supplying dependency through base class

I have a list of Parts and some of them need a pointer to an Engine, lets call them EngineParts. What I want is to find these EngineParts using RTTI and then give them the Engine.
The problem is how to design the EnginePart. I have two options here, described below, and I don't know which one to choose.
Option 1 is faster because it does not have a virtual function.
Option 2 is easier if I want to Clone() the object because without data it does not need a Clone() function.
Any thoughts? Maybe there is a third option?
Option 1:
class Part;
class EnginePart : public Part {
protected: Engine *engine
public: void SetEngine(Engine *e) {engine = e}
};
class Clutch : public EnginePart {
// code that uses this->engine
}
Option 2:
class Part;
class EnginePart : public Part {
public: virtual void SetEngine(Engine *e)=0;
};
class Clutch : public EnginePart {
private: Engine *engine;
public: void SetEngine(Engine *e) { engine = e; }
// code that uses this->engine
}
(Note that the actual situation is a bit more involved, I can't use a simple solution like creating a separate list for EngineParts)
Thanks
Virtual functions in modern compilers (from about the last 10 years) are very fast, especially for desktop machine targets, and that speed should not affect your design.
You still need a clone method regardless, if you want to copy from a pointer-/reference-to-base, as you must allow for (unknown at this time) derived classes to copy themselves, including implementation details like vtable pointers. (Though if you stick to one compiler/implementation, you can take shortcuts based on it, and just re-evaluate those every time you want to use another compiler or want to upgrade your compiler.)
That gets rid of all the criteria you've listed, so you're back to not knowing how to choose. But that's easy: choose the one that's simplest for you to do. (Which that is, I can't say based of this made-up example, but I suspect it's the first.)
Too bad that the reply stating that 'a part cannot hold the engine' is deleted because that was actually the solution.
Since not the complete Engine is needed, I found a third way:
class Part;
class EngineSettings {
private:
Engine *engine
friend class Engine;
void SetEngine(Engine *e) {engine = e}
public:
Value* GetSomeValue(params) { return engine->GetSomeValue(params); }
};
class Clutch : public Part, public EngineSettings {
// code that uses GetSomeValue(params) instead of engine->GetSomeValue(params)
}
Because GetSomeValue() needs a few params which Engine cannot know, there is no way it could "inject" this value like the engine pointer was injected in option 1 and 2. (Well.. unless I also provide a virtual GetParams()).
This hides the engine from the Clutch and gives me pretty much only one way to code it.