I'm trying to design an API and I'm wondering which approach is better. I have this concept I'll call a Message. This Message is composed of up to five MessageElements. There are about 300 MessageElements the user can add to a Message.
There are two approaches that I've thought of so far on to model this in C++. One, I can have a Message class with a method to add each MessageElement:
class Message
{
public:
void AddMessageElement1();
void AddMessageElement2();
void AddMessageElement3();
...
void AddMessageElement300();
};
(Note: the MessageElements aren't actually called "MessageElement1", "MessageElement2", etc.. They actually have more descriptive names than that. I'm just being generic here.)
Or, I represent each MessageElement by a class that all derive from a MessageElement base class. The Message class would thus have a single "Add()" method like so:
class Message
{
public:
void Add(const MessageElement& element);
};
The advantage to approach 1 is that the class hierarchy is simple. I won't have 300+ classes in the library. Basically just one class. However, that'll be one class with 300+ methods. Plus, any changes to the class's public API (like I have to add an additional MessageElement type) would require a recompile of all users of the class.
The advantage to approach 2 is that the Message class's API becomes really simple. Also, adding additional MessageElement types would not require a recompile of all the users of the Message class. The disadvantage is that I'll have 300+ little classes populating the library's API.
Which approach would be better? I'm kind of leaning towards approach 2. But approach 1 seems easier for user's to grasp.
Go with approach number 2.
Besides the advantages you stated (simple API for Message and modularity), you will have much more testable code with this approach (usually testable code is manageable and reusable code).
Approach 1 creates a monster;
If I went to an interview and the interviewer told me "we have a class with 300 methods in our code base" I would seriously consider not working there at all.
With approach 2 you may be able to centralize some of the the code in MessageElement, into a base class (much more natural than centralizing element-speciffic code into the Message class).
Related
In my simulation I have different objects that can be sensed in three ways: object can be seen and/or heard and/or smelled. For example, Animal can be seen, heard and smelled. And piece of Meat on the ground can be seen and smelled but not heard and Wall can only be seen. Then I have different sensors that gather this information - EyeSensor, EarSensor, NoseSensor.
Before state: brief version gist.github.com link
Before I started implementing NoseSensor I had all three functionality in one class that every object inherited - CanBeSensed because although classes were different they all needed the same getDistanceMethod() and if object implemented any CanBeSensed functionality it needed a senseMask - flags if object can be heard/seen/smelled and I didn't want to use virtual inheritance. I sacrificed having data members inside this class for smell, sounds, EyeInfo because objects that can only be seen do not need smell/sound info.
Objects then were registered in corresponding Sensor.
Now I've noticed that Smell and Sound sensors are the same and only differ in a single line inside a loop - one calls float getSound() and another float getSmell() on a CanBeSensed* object. When I create one of this two sensors I know what it needs to call, but I don't know how to choose that line without a condition and it's inside a tight loop and a virtual function.
So I've decided to make a single base class for these 3 functionality using virtual inheritance for base class with getDistanceMethod().
But now I had to make my SensorBase class a template class because of this method
virtual void sense(std::unordered_map<IdInt, CanBeSensed*>& objectsToSense) = 0;
, and it meant that I need to make SensorySubSystem class(manages sensors and objects in range) a template as well. And it meant that all my SubSystems like VisionSubSystem, HearingSubSystem and SmellSubSystem inherit from a template class, and it broke my SensorySystem class which was managing all SensorySubSystems through a vector of pointers to SensorySubSystem class std::vector<SensorySubSystem*> subSystems;
Please, could you suggest some solution for how to restructure this or how to make compiler decide at compile time(or at least decide once per call//once per object creation) what method to call inside Hearing/Smell Sensors.
Looking at your original design I have a few comments:
The class design in hierarchy.cpp looks quite ok to me.
Unless distance is something specific to sensory information getDistance() doesn't look like a method that belongs into this class. It could be moved either into a Vec2d-class or to a helper function (calculatePositon(vec2d, vec2d)). I do not see, why getDistance() is virtual, if it does something different than calculating the distance between the given position and the objects position, then it should be renamed.
The class CanBeSensed sounds more like a property and should probably be renamed to e.g. SensableObject.
Regarding your new approach:
Inheritance should primarily be used to express concepts (is-a-relations), not to share code. If you want to reuse an algorithm, consider writing an algorithm class or function (favour composition over inheritance).
In summary I propose to keep your original class design cleaning it up a little as described above. You could add virtual functions canBeSmelled/canBeHeard/canBeSeen to CanBeSensed.
Alternatively you could create a class hierachy:
class Object{ getPosition(); }
class ObjectWithSmell : virtual Object
class ObjectWithSound : virtual Object
...
But then you'd have to deal with virtual inheritance without any noticeable benefit.
The shared calculation code could go into an algorithmic class or function.
I quite often find myself creating interfaces that I am using just at the signature to inject a dependency, ending up with class AIface and class AImpl : public AIface. And quite often I never implement any other subclass of class AIface
Is there any advantage of this approach vs using directly the implementation with all public method virtual?
Longer Explanation:
Say we have a zoo with a cleaning service. We do TDD, and we want to be able to test the Zoo with a fake FeedingSvc, so we go for dependency injecton.
What is the difference between:
class FeedingSvcIface{
virtual void performFeeding() = 0;
} ;
class RoboticFeedingSvc: public FeedingSvcIface{
void performFeeding();
};
Class Zoo{
Zoo(FeedingSvcIface&);
//...
};
vs
class RoboticFeedingSvc{
virtual void performFeeding();
};
Class Zoo{
Zoo(RoboticFeedingSvc&);
//...
};
(And if ever needed, extract the interface in the future)
In terms of testing, the former seems easier.
I usually find natural to add interfaces when there is a I speak to a class that "crosses layers" but some times it is just about testing.
I know that in the future I might have to implement other types of FeedingSvcs but why doing the abstraction today if I don't really needed?,
I might split two classes just to encapsulate some logic.
The advantage of sticking to best practices, design patterns or other idioms is that although you make a bit of extra effort now, you gain more in the long run.
Imagine the scenario where you work in a team, with multiple developers, some experienced, some not.
You are the creator of the Zoo mechanism, but you decide, that for the time being, you will implement the Zoo on a KISS principle without adding the extra abstraction . You set yourself a mental note (or a even a nice little comment) stating that "If there shall be multiple distinct behaviors of the RoboticFeedingSvc there shall be Abstraction over the dependency injection !".
Now , because of your really awesome work, you get to go on a vacation and some junior developer will remain to mantain your code.
One of the tasks of the developer will be to introduce a ManualFeeding option and a hybrid option. How many ways to do this can you think about (with disregards to any coding principle) ?
Because you, the creator, didn't enforce the way the mechanism grows, the junior developer will look at your comment, add a "LoL u mad bro :) " comment , and then choose one of the following :
Create a base interface to be derived by other FeedingSvcs (you got lucky here)
Create a dependency injection to the RobotFeedingSvc using a strategy pattern (have some functors to be set in terms of how to feed something)
Make RobotFeedingSvc a composite between Feeder, Feeded, and some Action function
Make the RobotFeedingSvc a singleton factory (because singletons factories are awesome and fancy ) that somehow is used inside the Zoo to return the apropriate feeding technique (important thing here is that he used singleton and factory)
Create a templated version of the Zoo that takes a templated version of RobotFeedingSvc that is partially sepecialized according to given FeedingPolicy and Feeder (because he just bumped into templates, and templates should be used everywhere).
I guess we could sum up the story in fewers lines :
Making the initial effort to properly make the abstractions layer required in your application to make it scalable in terms of functionality will help other developers (including here future you ) to quickly understand the proper way to implement new features using the existing code instead of just hacking through it with some wild ideas.
Forcing your Zoo Class to take an interface instead of a concrete class is pretty much equivalent to leave a comment saying that new functionalities need to implement this interface.
Allowing a concrete class to be passed as parameter might switch focus on how to change the concrete class rather then implement something on top of it.
Another more technical reason would be the following :
He needs to add new functionality , but he's not allowed to change the Zoo implementation. What now ?
I have run into an annoying problem lately, and I am not satisfied with my own workaround: I have a program that maintains a vector of pointers to a base class, and I am storing there all kind of children object-pointers. Now, each child class has methods of their own, and the main program may or not may call these methods, depending on the type of object (note though that they all heavily use common methods of the base class, so this justify inheritance).
I have found useful to have an "object identifier" to check the class type (and then either call the method or not), which is already not very beautiful, but this is not the main inconvenience. The main inconvenience is that, if I want to actually be able to call a derived class method using the base class pointer (or even just store the pointer in the pointer array), then one need to declare the derived methods as virtual in the base class.
Make sense from the C++ coding point of view.. but this is not practical in my case (from the development point of view), because I am planning to create many different children classes in different files, perhaps made by different people, and I don't want to tweak/maintain the base class each time, to add virtual methods!
How to do this? Essentially, what I am asking (I guess) is how to implement something like Objective-C NSArrays - if you send a message to an object that does not implement the method, well, nothing happens.
regards
Instead of this:
// variant A: declare everything in the base class
void DoStuff_A(Base* b) {
if (b->TypeId() == DERIVED_1)
b->DoDerived1Stuff();
else if if (b->TypeId() == DERIVED_2)
b->DoDerived12Stuff();
}
or this:
// variant B: declare nothing in the base class
void DoStuff_B(Base* b) {
if (b->TypeId() == DERIVED_1)
(dynamic_cast<Derived1*>(b))->DoDerived1Stuff();
else if if (b->TypeId() == DERIVED_2)
(dynamic_cast<Derived2*>(b))->DoDerived12Stuff();
}
do this:
// variant C: declare the right thing in the base class
b->DoStuff();
Note there's a single virtual function in the base per stuff that has to be done.
If you find yourself in a situation where you are more comfortable with variants A or B then with variant C, stop and rethink your design. You are coupling components too tightly and in the end it will backfire.
I am planning to create many different children classes in different
files, perhaps made by different people, and I don't want to
tweak/maintain the base class each time, to add virtual methods!
You are OK with tweaking DoStuff each time a derived class is added, but tweaking Base is a no-no. May I ask why?
If your design does not fit in either A, B or C pattern, show what you have, for clairvoyance is a rare feat these days.
You can do what you describe in C++, but not using functions. It is, by the way, kind of horrible but I suppose there might be cases in which it's a legitimate approach.
First way of doing this:
Define a function with a signature something like boost::variant parseMessage(std::string, std::vector<boost::variant>); and perhaps a string of convenience functions with common signatures on the base class and include a message lookup table on the base class which takes functors. In each class constructor add its messages to the message table and the parseMessage function then parcels off each message to the right function on the class.
It's ugly and slow but it should work.
Second way of doing this:
Define the virtual functions further down the hierarchy so if you want to add int foo(bar*); you first add a class that defines it as virtual and then ensure every class that wants to define int foo(bar*); inherit from it. You can then use dynamic_cast to ensure that the pointer you are looking at inherits from this class before trying to call int foo(bar*);. Possible these interface adding classes could be pure virtual so they can be mixed in to various points using multiple inheritance, but that may have its own problems.
This is less flexible than the first way and requires the classes that implement a function to be linked to each other. Oh, and it's still ugly.
But mostly I suggest you try and write C++ code like C++ code not Objective-C code.
This can be solved by adding some sort of introspection capabilities and meta object system. This talk Metadata and reflection in C++ — Jeff Tucker demonstrates how to do this using c++'s template meta programming.
If you don't want to go to the trouble of implementing one yourself, then it would be easier to use an existing one such as Qt's meta object system. Note that this solution does not work with multiple inheritance due to limitations in the meta object compiler: QObject Multiple Inheritance.
With that installed, you can query for the presence of methods and call them. This is quite tedious to do by hand, so the easiest way to call such a methods is using the signal and slot mechanism.
There is also GObject which is quite simmilar and there are others.
If you are planning to create many different children classes in different files, perhaps made by different people, and also I would guess you don't want to change your main code for every child class. Then I think what you need to do in your base class is to define several (not to many) virtual functions (with empty implementation) BUT those functions should be used to mark a time in the logic where they are called like "AfterInseart" or "BeforeSorting", Etc.
Usually there are not to many places in the logic you wish a derived classes to perform there own logic.
I've read the decorator design pattern from Wikipedia, and code example from this site.
I see the point that traditional inheritance follows an 'is-a' pattern whereas decorator follows a 'has-a' pattern. And the calling convention of decorator looks like a 'skin' over 'skin' .. over 'core'. e.g.
I* anXYZ = new Z( new Y( new X( new A ) ) );
as demonstrated in above code example link.
However there are still a couple of questions that I do not understand:
what does wiki mean by 'The decorator pattern can be used to extend (decorate) the functionality of a certain object at run-time'? the 'new ...(new... (new...))' is a run-time call and is good but a 'AwithXYZ anXYZ;' is a inheritance at compile time and is bad?
from the code example link I can see that the number of class definition is almost the same in both implementations. I recall in some other design pattern books like 'Head first design patterns'. They use starbuzz coffee as example and say traditional inheritance will cause a 'class explosion' because for each combination of coffee, you would come up with a class for it.
But isn't it the same for decorator in this case? If a decorator class can take ANY abstract class and decorate it, then I guess it does prevent explosion, but from the code example, you have exact # of class definitions, no less...
Would anyone explain?
Let's take some abstract streams for example and imagine you want to provide encryption and compression services over them.
With decorator you have (pseudo code):
Stream plain = Stream();
Stream encrypted = EncryptedStream(Stream());
Stream zipped = ZippedStream(Stream());
Stream zippedEncrypted = ZippedStream(EncryptedStream(Stream());
Stream encryptedZipped = EncryptedStream(ZippedStream(Stream());
With inheritance, you have:
class Stream() {...}
class EncryptedStream() : Stream {...}
class ZippedStream() : Stream {...}
class ZippedEncryptedStream() : EncryptedStream {...}
class EncryptedZippedStream() : ZippedStream {...}
1) with decorator, you combine the functionality at runtime, depending on your needs. Each class only takes care of one facet of functionality (compression, encryption, ...)
2) in this simple example, we have 3 classes with decorators, and 5 with inheritance. Now let's add some more services, e.g. filtering and clipping. With decorator you need just 2 more classes to support all possible scenarios, e.g. filtering -> clipping -> compression -> encription.
With inheritance, you need to provide a class for each combination so you end up with tens of classes.
In reverse order:
2) With, say, 10 different independent extensions, any combination of which might be needed at run time, 10 decorator classes will do the job. To cover all possibilities by inheritance you'd need 1024 subclasses. And there'd be no way of getting around massive code redundancy.
1) Imagine you had those 1024 subclasses to choose from at run time. Try to sketch out the code that would be needed. Bear in mind that you might not be able to dictate the order in which options are picked or rejected. Also remember that you might have to use an instance for a while before extending it. Go ahead, try. Doing it with decorators is trivial by comparison.
You are correct that they can be very similar at times. The applicability and benefits of either solution will depend on your situation.
Others have beat me to adequate answers to your second question. In short it is that you can combine decorators to achieve more combinations which you cannot do with inheritance.
As such I focus on the first:
You cannot strictly say compile-time is bad and run-time is good, it is just different flexibility. The ability to change things at run-time can be important for some projects because it allows changes without recompilation which can be slow and requires you be in an environment where you can compile.
An example where you cannot use inheritance, is when you want to add functionality to an instantiated object. Suppose you are provided an instance of an object that implements a logging interface:
public interface ILog{
//Writes string to log
public void Write( string message );
}
Now suppose you begin a complicated task that involves many objects and each of them does logging so you pass along the logging object. However you want every message from the task to be prefixed with the task Name and Task Id. You could pass around a function, or pass along the Name and Id and trust every caller to follow the rule of pre-pending that information, or you could decorate the logging object before passing it along and not have to worry about the other objects doing it right
public class PrependLogDecorator : ILog{
ILog decorated;
public PrependLogDecorator( ILog toDecorate, string messagePrefix ){
this.decorated = toDecorate;
this.prefix = messagePrefix;
}
public void Write( string message ){
decorated.Write( prefix + message );
}
}
Sorry about the C# code but I think it will still communicate the ideas to someone who knows C++
To address the second part of your question (which might in turn address your first part), using the decorator method you have access to the same number of combinations, but don't have to write them. If you have 3 layers of decorators with 5 options at each level, you have 5*5*5 possible classes to define using inheritance. Using the decorator method you need 15.
First off, I'm a C# person and haven't dealt with C++ in a while, but hopefully you get where I'm coming from.
A good example that comes to mind is a DbRepository and a CachingDbRepository:
public interface IRepository {
object GetStuff();
}
public class DbRepository : IRepository {
public object GetStuff() {
//do something against the database
}
}
public class CachingDbRepository : IRepository {
public CachingDbRepository(IRepository repo){ }
public object GetStuff() {
//check the cache first
if(its_not_there) {
repo.GetStuff();
}
}
So, if I just used inheritance, I'd have a DbRepository and a CachingDbRepository. The DbRepository would query from a database; the CachingDbRepository would check its cache and if the data wasn't there, it would query a database. So there's a possible duplicate implementation here.
By using the decorator pattern, I still have the same number of classes, but my CachingDbRepository takes in a IRepository and calls its GetStuff() to get the data from the underlying repo if it's not in the cache.
So the number of classes are the same, but the use of the classes are related. CachingDbRepo calls the Repo that was passed into it...so it's more like composition over inheritance.
I find it subjective when to decide when to use just inheritance over decoration.
I hope this helps. Good luck!
My team has written several C++ classes which implement event handling via pure virtual callbacks - for example, when a message is received from another process, the base class which handles IPC messaging calls its own pure virtual function, and a derived class handles the event in an override of that function. The base class knows the event has occurred; the derived class knows what to do with it.
I now want to combine the features provided by these base classes in a higher-level class, so for example when a message arrives from another process, my new class can then forward it on over its network connection using a similar event-driven networking class. It looks like I have two options:
(1) composition: derive classes from each of the event-handling base classes and add objects of those derived classes to my new class as members, or:
(2) multiple inheritance: make my new class a derived class of all of the event-handling base classes.
I've tried both (1) and (2), and I'm not satisfied with my implementation of either.
There's an extra complication: some of the base classes have been written using initialisation and shutdown methods instead of using constructors and destructors, and of course these methods have the same names in each class. So multiple inheritance causes function name ambiguity. Solvable with using declarations and/or explicit scoping, but not the most maintainable-looking thing I've ever seen.
Even without that problem, using multiple inheritance and overriding every pure virtual function from each of several base classes is going to make my new class very big, bordering on "God Object"-ness. As requirements change (read: "as requirements are added") this isn't going to scale well.
On the other hand, using separate derived classes and adding them as members of my new class means I have to write lots of methods on each derived class to exchange information between them. This feels very much like "getters and setters" - not quite as bad, but there's a lot of "get this information from that class and hand it to this one", which has an inefficient feel to it - lots of extra methods, lots of extra reads and writes, and the classes have to know a lot about each other's logic, which feels wrong. I think a full-blown publish-and-subscribe model would be overkill, but I haven't yet found a simple alternative.
There's also a lot of duplication of data if I use composition. For example, if my class's state depends on whether its network connection is up and running, I have to either have a state flag in every class affected by this, or have every class query the networking class for its state every time a decision needs to be made. If I had just one multiply-inherited class, I could just use a flag which any code in my class could access.
So, multiple inheritance, composition, or perhaps something else entirely? Is there a general rule-of-thumb on how best to approach this kind of thing?
From your description I think you've gone for a "template method" style approach where the base does work and then calls a pure virtual that the derived class implements rather than a "callback interface" approach which is pretty much the same except that the pure virtual method is on a completely separate interface that's passed in to the "base" as a parameter to the constructor. I personally prefer the later as I find it considerably more flexible when the time comes to plug objects together and build higher level objects.
I tend to go for composition with the composing class implementing the callback interfaces that the composed objects require and then potentially composing again in a similar style at a higher level.
You can then decide if it's appropriate to compose by having the composing object implement the callback interfaces and pass them in to the "composed" objects in their constructors OR you can implement the callback interface in its own object possibly with a simpler and more precise callback interface that your composing object implements, and compose both the "base object" and the "callback implementation object"...
Personally I wouldn't go with an "abstract event handling" interface as I prefer my code to be explicit and clear even if that leads to it being slightly less generic.
I'm not totally clear on what your new class is trying to achieve, but it sounds like you're effectively having to provide a new implementation somewhere for all of these abstract event classes.
Personally I would plump for composition. Multiple inheritance quickly becomes a nightmare, especially when things have to change, and composition keeps the existing separation of concerns.
You state that each derived object will have to communicate with the network class, but can you try and reduce this to the minimum. For instance, each derived event object is purely responsible for packaging up the event info into some kind of generic packet, and then that packet is passed to the network class to do the guts of sending?
Without knowing exactly what your new class is doing it's hard to comment, or suggest better patterns, but the more I code, the more I am learning to agree with the old adage "favour composition over inheritance"