How to structure a large routine when subtasks have strong interdependence - c++

Dear StackOverflow :)
I am trying to implement a sort of pattern matching routine, that maps tree structures onto other tree structures in a specific way. Unfortunately the routine has to be very flexible, so that this operation is very non-trivial.
I can intuitively divide this large amount of work into smaller portions that can be handled sequentially, but I am having trouble to bring structure into the code I write. These subtasks have a very strong interdependence, so that if I break up the large function into smaller ones I need very much state information to get things right. This adds a lot of extra code and makes things hard to oversee - and, I am afraid, might reduce compiler optimization.
If I however choose to implement everything into a single large function, I am having problems with the "program flow" - I have to use a lot of goto statements (which I can mask away into something more pretty, but the problem still remains).
Now in general: How do you attack such problems that are "large"? Can you give me some hints about what I could look into?

Answering for C++, but the principles should be transferable.
I'd say the solution here is to realise that C++ objects don't have to correspond to "tangible" things. Why not represent the matching task as a class instead of a function?
Basically, create a noncopyable class with a public "driver" function. The subtasks (smaller portions) can be represented as non-public member functions of that class, and they can share data via the class's data members.
Something like this:
bool patternsMatch(Pattern a, Pattern b) {
return PatternMatcher(a, b).match();
}
class PatternMatcher
{
public:
PatternMatcher(Pattern a, Pattern b);
bool match() {
subtask1();
subtask2();
return res;
}
private:
bool res;
Pattern a, b;
int something_subtasks_share;
float more_shared_data;
void subtask1();
void subtask2();
};

Related

Big projects that require very good performance really don't use polymorphism?

For quite some time I have been interested in perfomance in C ++.
A lot of things keep coming up, whether in conferences or in books:
Do not use a virtual function, have the data in the cache, the branches etc.
There are many benchmarks with examples of video games to show the differences in performance.
The thing is, the examples are always very simple.
How does that really work in code that is more than 20 lines? in AAA video games, finance etc.
If I have 100 types of objects that have different update, different behavior and other joys, it's easy to set up via polymorphism or function pointers.
Now, by following the advice given to make a powerful code, the above options are not possible.
We will therefore prefer to have 100 arrays that we will update separately.
We will have good access to the cache, the functions will probably be inline etc. in short, the performance will in principle be better.
So, I have 100 arrays and 100 differents functions that i will have to call at each frame.
The tables dynamically change depending on what happens, new players appear, a monster dies etc.
Some array will have 0 elements active, others 10...
I would call functions that will have no work (array without active element) but I have no choice, I have to have a flag or look if elements are active or not in my array.
I end up with something like this:
obj1update ();
obje2update ();
....
obj1behavior ();
obj2behavior ();
....
obj1render ();
obj2render ();
.....
objectxy ();
....
Of course, there will undoubtedly be a function which manages all the update calls on the objects, one for the behavior etc but to simplify it gives as above.
To stay in the video game, if the x action of a player causes the arrival of y monsters, there are several types of monsters which have different functions.
We will therefore put the monsters in our tables and this time the functions dealing with these monsters will have work.
We can use the ECS pattern or a derivative but they will potentially have very different behaviors (an ia that directs them or other), different components and therefore different functions will be needed to process them.
They will be called hard in the code since we don't have polymorphism or function pointers and we will have to check at each frame if they have something to process or not.
Is it really done that way? suppose i have 500 types? 1000 ?
Edit:
Lots of comments so I'll get back to you here.
As Federico said, I want to know if these recommendations are good for books but less so in practice.
Several resources that I have looked at:
https://www.agner.org/optimize/#testp
Great suite of several books
www.youtube.com/watch?v=WDIkqP4JbkE&t
Scott Meyers talk on memory
https://people.freebsd.org/~lstewart/articles/cpumemory.pdf
On memory
www.youtube.com/watch?v=rX0ItVEVjHc&t
Data-oriented programming
https://www.dataorienteddesign.com/dodbook/
data oriented design book
There are also other resources but it already gives you an idea on what I'm basing
No, real programs are not written like that. Real programs are written by noticing that all the monsters have a bunch of things in common, and using the same code to do those things. They all pathfind, but they have different distances they can walk? Great. Add a max_walking_distance variable and call the same function each time.
All your monsters have a 3D model? Then you don't need a virtual render method. You can just render the model.
You don't have to divide up your data according to "sensible" boundaries. You don't have to have a struct monster. You can have a struct monster_pathfinding and a struct monster_position and a struct monster_3d_model. Even if you just put these in parallel arrays (i.e. monster 123 has its pathfinding info in monsters_pathfinding[123] and its position in monster_positions[123]) this can make more efficient use of the data cache, because the pathfinding code doesn't load the 3D model pointers into the cache. You can get cleverer by skipping entries if some monsters don't pathfind or don't render. Essentially it is recommended for performance that you group data together according to how it's used, not according to your mental model of the things in the game. Yes, skipping entries makes it way more difficult to delete monsters. But you tick monsters a lot, and you don't delete monsters very often, right?
Maybe only a few monsters shoot guns at the player (the rest try to eat the player). You can have a struct monster_gun_data {int ammunition; int max_ammunition; int reload_time; monster_position *position;}; and then if you have 200 monsters, but only 10 of them have guns, your monstersShootGunsAtPlayers function only has to iterate over the 10 entries in the monster_gun_data array (and load their positions via pointers). Or, you might profile that and find out that because most monsters in your game have guns, it's slightly faster to iterate over all the monsters and check their MONSTER_HAS_GUN flag instead, than to access the position through a pointer which can't be prefetched as easily.
How do you do different kinds of monster attacks? Well, if they're completely different (melee vs ranged), you probably do them with different functions as you have described. Or you might only check the attack type after you decide the monster wants to attack the player. You seem to suggest monsters use different attack code, but I bet this works for almost all of them:
if(wantsToAttack(monster, player)) {
if((monster->flags & HAS_RANGED_ATTACK) && distance(monster, player) > monster->melee_attack_distance)
startRangedAttack(monster, player);
else
startMeleeAttack(monster, player);
}
And what's really different between a monster with a gun, and a monster with a bow and arrow? The attack speed, the animation, the speed the projectile moves at, the projectile's 3D model, and the amount of damage it does. That's all data. That isn't different code.
Finally, if you have something completely different, you might consider making it a "strategy object" with a virtual function. Or just a plain function pointer, if you can. Note that the Monster object is still not polymorphic, because if it was, we couldn't have an array of them and that would slow down all the common code. Only the specific parts of the monster that we're saying are polymorphic are actually polymorphic.
void SpecialBossTickFunction(Monster *monster) {
// special movement, etc
}
// ...
monster->onTick = &SpecialBossTickFunction;
// monster is still not polymorphic except for this one field
You could also do:
struct SpecialBossTickStrategy : TickStrategy {
void onTick(Monster *monster) override {...}
// then you can also have extra fields if needed
// but you also have more indirection
};
monster->onTick = new SpecialBossTickStrategy;
And don't do stuff unnecessarily. Try to be event-driven instead of doing stuff every tick:
// bad because we're calling this function unnecessarily every tick
void SpecialUndeadMonsterTickFunction(Monster *monster) {
if(monster->isDead) {
// do some special reanimation sequence
}
}
monster->onTick = &SpecialUndeadMonsterTickFunction;
// better (for performance)
void SpecialUndeadMonsterTickWhileDeadFunction(Monster *monster) {
// do some special reanimation sequence
if (finished doing whatever) {
monster->onTick = NULL;
}
}
void SpecialUndeadMonsterDeathFunction(Monster *monster) {
monster->onTick = &SpecialUndeadMonsterTickWhileDeadFunction;
}
// ...
monster->onDead = &SpecialUndeadMonsterDeathFunction;
// Also better (for performance)
void DoUndeadMonsterReanimationSequences() { // not virtual at all, called from the main loop
for(Monster *monster : special_undead_monsters_which_are_currently_dead) {
// do some special reanimation sequence
}
}
// Not great, but perhaps still less bad than the first one!
void DoUndeadMonsterReanimationSequences() { // not virtual at all, called from the main loop
for(Monster &monster : all_monsters) {
if(monster.type == TYPE_SPECIAL_UNDEAD_MONSTER && monster.isDead) {
// do some special reanimation sequence
}
}
}
Note that in the third example you have to keep this array special_undead_monsters_which_are_currently_dead up to date. That's okay, because you only have to change it when a monster spawns, disappears, dies, or un-dies. And those are relatively rare events. You are doing a bit more work in these events, in order to save work every tick.
Finally, keep in mind these are techniques that may or may not improve performance in your actual program. I see DOD as a grab-bag of ideas. It doesn't say you must write your program in exactly a certain way, but it is offering a bunch of unconventional suggestions, the theory to explain why they work, and examples of how other people have managed to use them in their programs. Since DOD usually suggests that you complete reorganize your data structures, you may only want to implement it in the performance-critical areas of your program.
Just to add some more perspective on the top-level question:
Big projects that require very good performance really don't use polymorphism?
You're missing out an entire category of polymorphism.
I often mix all three of the below styles in a project, because not all code has the same performance requirements:
setup and configuration code doesn't generally need to be (very) fast. Use OO style and runtime polymorphism all you want for properties, factories, whatever.
Runtime polymorphism broadly means virtual functions.
steady-state code that does need to be fast can often use compile-time polymorphism. This works well for a statically-known (and ideally small) collection of types with similar interfaces.
Compile-time polymorphism means templates (function templates, type templates, replacing the run-time Strategy pattern with the equivalent Policy, etc.)
the code with the tightest performance requirements may need to be data-oriented (ie, designed around cache friendliness).
This isn't all the code in the project, and probably isn't even all the code that needs to be fast. It's all the code that needs to be fast and where performance is dominated by cache effects.
If you only have one copy of an object, you may well inline as much as possible (and try to fit it into the fewest cache lines possible), but splitting it into four different arrays with only one element each won't achieve much.

Strategy pattern vs Inheritance

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.

Selecting the right strategy based on two object types

I'm not sure how to name this problem, so I'm going to try to explain as good as I can.
I want to be able to switch strategies depending on the types of two different objects. To make this work, I am thinking of flagging the objects with an enum type, and having a 'registry' (arrayish) of these strategies. Ideally, the correct strategy would be accessed with some simple operation like a bitwise operator between the two types.
This pseudocode may make what I'm trying to explain easier to understand:
enum Type { A, B, C }
struct Object {
Type type;
}
class ActionRunner {
vector<Strategy> strategies;
void registerStrategy(type1, type2, strategy) {
strategies[type1 operator type2] = strategy;
}
void runStrategyFor(type1, type2) {
strategies[type1 operator type2].execute();
}
}
This would be easy to solve using a map, but I'd like to use an array or vector because a map seems like an overkill for a problem like this and using an array is probably much faster.
So the problem is I don't know what operator I might be able to use to select the 'position' of the right strategy. I've been thinking of a few combinations but it seems all of them end up causing collisions with the different combinations at some point.
Does anyone have any clues/advice on what I may be able to use for this?
PS: I know premature optimization is bad, but I'm just trying to figure out if this problem can be solved in a simple way.
------- EDIT ------------------------------------------------
In light of the answers, I've been giving the problem some extra thought and I've come to the conclusion what I intended with this question isn't possible the way I'd like it. I'm going to try to re-state the problem I'm trying to solve now using this question.
I'd like to have a class structure in which there's objects of certain type 'BaseClass' and a 'processor' object that takes two objects derived from 'BaseClass' and runs the right strategy for those. Something like this:
class Processor {
void run (DerivedA a, DerivedB b);
}
class BaseClass {}
class DerivedA: public BaseClass {}
class DerivedB: public BaseClass {}
BaseClass a = new DerivedA;
BaseClass b = new DerivedB;
processor.run(a, b)
According to what I understand, this would not work as I'd expect if what is passed as parameters to 'run' are references, which is what I'd rather do. Is there any way to do this without way-too-complicated code? (tripple dispatch!?)
I have in mind something like the double dispatch combined with an slave (processor) object that I think would work, but that seems awfully complex and probably a pain to maintain and extend.
Thanks!
The second sentence of your question rang a bell for me:
I want to be able to switch strategies depending on the types of two different objects.
This sounds like you want to perform a double dispatch. See the question (in particular, the answers to the question ;-)) at Double dispatch/multimethods in C++ for how to implement this in C++.
That's a classic example for using map instead of array. Array is actually a private case of map with key defined as an integer. In your case the key is a tuple so a simple array won't do and you'll end up with collisions (even if you're lucky for your specific input, your code will be extremely non-robust).
You can have an intermediate solution, between simple array and map: 2D array, with your 2 types serving as indices to rows and columns..

Object composition promotes code reuse. (T/F, why)

I'm studying for an exam and am trying to figure this question out. The specific question is "Inheritance and object composition both promote code reuse. (T/F)", but I believe I understand the inheritance portion of the question.
I believe inheritance promotes code reuse because similar methods can be placed in an abstract base class such that the similar methods do not have to be identically implemented within multiple children classes. For example, if you have three kinds of shapes, and each shape's method "getName" simply returns a data member '_name', then why re-implement this method in each of the child classes when it can be implemented once in the abstract base class "shape".
However, my best understanding of object composition is the "has-a" relationship between objects/classes. For example, a student has a school, and a school has a number of students. This can be seen as object composition since they can't really exist without each other (a school without any students isn't exactly a school, is it? etc). But I see no way that these two objects "having" each other as a data member will promote code reuse.
Any help? Thanks!
Object composition can promote code reuse because you can delegate implementation to a different class, and include that class as a member.
Instead of putting all your code in your outermost classes' methods, you can create smaller classes with smaller scopes, and smaller methods, and reuse those classes/methods throughout your code.
class Inner
{
public:
void DoSomething();
};
class Outer1
{
public:
void DoSomethingBig()
{
// We delegate part of the call to inner, allowing us to reuse its code
inner.DoSomething();
// Todo: Do something else interesting here
}
private:
Inner inner;
};
class Outer2
{
public:
void DoSomethingElseThatIsBig()
{
// We used the implementation twice in different classes,
// without copying and pasting the code.
// This is the most basic possible case of reuse
inner.DoSomething();
// Todo: Do something else interesting here
}
private:
Inner inner;
};
As you mentioned in your question, this is one of the two most basic Object Oriented Programming principals, called a "has-a relationship". Inheritance is the other relationship, and is called an "is-a replationship".
You can also combine inheritance and composition in quite useful ways that will often multiply your code (and design) reuse potential. Any real world and well-architected application will constantly combine both of these concepts to gain as much reuse as possible. You'll find out about this when you learn about Design Patterns.
Edit:
Per Mike's request in the comments, a less abstract example:
// Assume the person class exists
#include<list>
class Bus
{
public:
void Board(Person newOccupant);
std::list<Person>& GetOccupants();
private:
std::list<Person> occupants;
};
In this example, instead of re-implementing a linked list structure, you've delegated it to a list class. Every time you use that list class, you're re-using the code that implements the list.
In fact, since list semantics are so common, the C++ standard library gave you std::list, and you just had to reuse it.
1) The student knows about a school, but this is not really a HAS-A relationship; while you would want to keep track of what school the student attends, it would not be logical to describe the school as being part of the student.
2) More people occupy the school than just students. That's where the reuse comes in. You don't have to re-define the things that make up a school each time you describe a new type of school-attendee.
I have to agree with #Karl Knechtel -- this is a pretty poor question. As he said, it's hard to explain why, but I'll give it a shot.
The first problem is that it uses a term without defining it -- and "code reuse" means a lot of different things to different people. To some people, cutting and pasting qualifies as code reuse. As little as I like it, I have to agree with them, to at least some degree. Other people define cod reuse in ways that rule out cutting and pasting as being code reuse (classing another copy of the same code as separate code, not reusing the same code). I can see that viewpoint too, though I tend to think their definition is intended more to serve a specific end than be really meaningful (i.e., "code reuse"->good, "cut-n-paste"->bad, therefore "cut-n-paste"!="code reuse"). Unfortunately, what we're looking at here is right on the border, where you need a very specific definition of what code reuse means before you can answer the question.
The definition used by your professor is likely to depend heavily upon the degree of enthusiasm he has for OOP -- especially during the '90s (or so) when OOP was just becoming mainstream, many people chose to define it in ways that only included the cool new OOP "stuff". To achieve the nirvana of code reuse, you had to not only sign up for their OOP religion, but really believe in it! Something as mundane as composition couldn't possibly qualify -- no matter how strangely they had to twist the language for that to be true.
As a second major point, after decades of use of OOP, a few people have done some fairly careful studies of what code got reused and what didn't. Most that I've seen have reached a fairly simple conclusion: it's quite difficult (i.e., essentially impossible) correlate coding style with reuse. Nearly any rule you attempt to make about what will or won't result in code reuse can and will be violated on a regular basis.
Third, and what I suspect tends to be foremost in many people's minds is the fact that asking the question at all makes it sound as if this is something that can/will affect a typical coder -- that you might want to choose between composition and inheritance (for example) based on which "promotes code reuse" more, or something on that order. The reality is that (just for example) you should choose between composition and inheritance primarily based upon which more accurately models the problem you're trying to solve and which does more to help you solve that problem.
Though I don't have any serious studies to support the contention, I would posit that the chances of that code being reused will depend heavily upon a couple of factors that are rarely even considered in most studies: 1) how similar of a problem somebody else needs to solve, and 2) whether they believe it will be easier to adapt your code to their problem than to write new code.
I should add that in some of the studies I've seen, there were factors found that seemed to affect code reuse. To the best of my recollection, the one that stuck out as being the most important/telling was not the code itself at all, but the documentation available for that code. Being able to use the code without basically reverse engineer it contributes a great deal toward its being reused. The second point was simply the quality of the code -- a number of the studies were done in places/situations where they were trying to promote code reuse. In a fair number of cases, people tried to reuse quite a bit more code than they really did, but had to give up on it simply because the code wasn't good enough -- everything from bugs to clumsy interfaces to poor portability prevented reuse.
Summary: I'll go on record as saying that code reuse has probably been the most overhyped, under-delivered promise in software engineering over at least the last couple of decades. Even at best, code reuse remains a fairly elusive goal. Trying to simplify it to the point of treating it as a true/false question based on two factors is oversimplifying the question to the point that it's not only meaningless, but utterly ridiculous. It appears to trivialize and demean nearly the entire practice of software engineering.
I have an object Car and an object Engine:
class Engine {
int horsepower;
}
class Car {
string make;
Engine cars_engine;
}
A Car has an Engine; this is composition. However, I don't need to redefine Engine to put an engine in a car -- I simply say that a Car has an Engine. Thus, composition does indeed promote code reuse.
Object composition does promote code re-use. Without object composition, if I understand your definition of it properly, every class could have only primitive data members, which would be beyond awful.
Consider the classes
class Vector3
{
double x, y, z;
double vectorNorm;
}
class Object
{
Vector3 position;
Vector3 velocity;
Vector3 acceleration;
}
Without object composition, you would be forced to have something like
class Object
{
double positionX, positionY, positionZ, positionVectorNorm;
double velocityX, velocityY, velocityZ, velocityVectorNorm;
double accelerationX, accelerationY, accelerationZ, accelerationVectorNorm;
}
This is just a very simple example, but I hope you can see how even the most basic object composition promotes code reuse. Now think about what would happen if Vector3 contained 30 data members. Does this answer your question?

Alternatives to passing a flag into a method?

Sometimes when fixing a defect in an existing code base I might (often out of laziness) decide to change a method from:
void
MyClass::foo(uint32_t aBar)
{
// Do something with aBar...
}
to:
void
MyClass::foo(uint32_t aBar, bool aSomeCondition)
{
if (aSomeCondition)
{
// Do something with aBar...
}
}
During a code review a colleague mentioned that a better approach would be to sub-class MyClass to provide this specialized functionality.
However, I would argue that as long as aSomeCondition doesn't violate the purpose or cohesion of MyClass it is an acceptable pattern to use. Only if the code became infiltrated with flags and if statements would inheritance be a better option, otherwise we would be potentially be entering architecture astronaut territory.
What's the tipping point here?
Note: I just saw this related answer which suggests that an enum may be a better
choice than a bool, but I think my question still applies in this case.
There is not only one solution for this kind of problem.
Boolean has a very low semantic. If you want to add in the future a new condition you will have to add a new parameter...
After four years of maintenance your method may have half a dozen of parameters, if these parameters are all boolean it is very nice trap for maintainers.
Enum is a good choice if cases are exclusive.
Enums can be easily migrated to a bit-mask or a context object.
Bit mask : C++ includes C language, you can use some plain old practices. Sometime a bit mask on an unsigned int is a good choice (but you loose type checking) and you can pass by mistake an incorrect mask. It is a convenient way to move smoothly from a boolean or an enum argument to this kind of pattern.
Bit mask can be migrated with some effort to a context-object. You may have to implement some kind of bitwise arithmetics such as operator | and operator & if you have to keep a buildtime compatibility.
Inheritence is sometime a good choice if the split of behavior is big and this behavior IS RELATED to the lifecycle of the instance. Note that you also have to use polymorphism and this is may slow down the method if this method is heavily used.
And finally inheritence induce change in all your factory code... And what will you do if you have several methods to change in an exclusive fashion ? You will clutter your code of specific classes...
In fact, I think that this generally not a very good idea.
Method split : Another solution is sometime to split the method in several private and provide two or more public methods.
Context object : C++ and C lack of named parameter can be bypassed by adding a context parameter. I use this pattern very often, especially when I have to pass many data across level of a complex framework.
class Context{
public:
// usually not a good idea to add public data member but to my opinion this is an exception
bool setup:1;
bool foo:1;
bool bar:1;
...
Context() : setup(0), foo(0), bar(0) ... {}
};
...
Context ctx;
ctx.setup = true; ...
MyObj.foo(ctx);
Note:
That this is also useful to minimize access (or use) of static data or query to singleton object, TLS ...
Context object can contain a lot more of caching data related to an algorithm.
...
I let your imagination run free...
Anti patterns
I add here several anti pattern (to prevent some change of signature):
*NEVER DO THIS *
*NEVER DO THIS * use a static int/bool for argument passing (some people that do that, and this is a nightmare to remove this kind of stuff). Break at least multithreading...
*NEVER DO THIS * add a data member to pass parameter to method.
Unfortunately, I don't think there is a clear answer to the problem (and it's one I encounter quite frequently in my own code). With the boolean:
foo( x, true );
the call is hard to understand .
With an enum:
foo( x, UseHigherAccuracy );
it is easy to understand but you tend to end up with code like this:
foo( x, something == someval ? UseHigherAccuracy : UseLowerAccuracy );
which is hardly an improvement. And with multiple functions:
if ( something == someval ) {
AccurateFoo( x );
}
else {
InaccurateFoo( x );
}
you end up with a lot more code. But I guess this is the easiest to read, and what I'd tend to use, but I still don't completely like it :-(
One thing I definitely would NOT do however, is subclass. Inheritance should be the last tool you ever reach for.
The primary question is if the flag affects the behaviour of the class, or of that one function. Function-local changes should be parameters, not subclasses. Run-time inheritance should be one of the last tools reached for.
The general guideline I use is: if aSomeCondition changes the nature of the function in a major way, then I consider subclassing.
Subclassing is a relatively large effort compared to adding a flag that has only a minor effect.
Some examples:
if it's a flag that changes the direction in which a sorted collection is returned to the caller, that's a minor change in nature (flag).
if it's a one-shot flag (something that affects the current call rather than a persistent change to the object), it should probably not be a subclass (since going down that track is likely to lead to a massive number of classes).
if it's a enumeration that changes the underlying data structure of your class from array to linked list or balanced tree, that's a complex change (subclass).
Of course, that last one may be better handled by totally hiding the underlying data structure but I'm assuming here that you want to be able to select one of many, for reasons such as performance.
IMHO, aSomeCondition flag changes or depends on the state of current instance, therefore, under certain conditions this class should change its state and handle mentioned operation differently. In this case, I can suggest the usage of State Pattern. Hope it helps.
I would just change code:
void MyClass::foo(uint32_t aBar, bool aSomeCondition)
{
if (aSomeCondition)
{
// Do something with aBar...
}
}
to:
void MyClass::foo(uint32_t aBar)
{
if (this->aSomeCondition)
{
// Do something with aBar...
}
}
I always omit bool as function parameter and prefer to put into struct, even if I would have to call
myClass->enableCondition();