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

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.

Related

C++ member variable change listeners (100+ classes)

I am trying to make an architecture for a MMO game and I can't figure out how I can store as many variables as I need in GameObjects without having a lot of calls to send them on a wire at the same time I update them.
What I have now is:
Game::ChangePosition(Vector3 newPos) {
gameobject.ChangePosition(newPos);
SendOnWireNEWPOSITION(gameobject.id, newPos);
}
It makes the code rubbish, hard to maintain, understand, extend. So think of a Champion example:
I would have to make a lot of functions for each variable. And this is just the generalisation for this Champion, I might have have 1-2 other member variable for each Champion type/"class".
It would be perfect if I would be able to have OnPropertyChange from .NET or something similar. The architecture I am trying to guess would work nicely is if I had something similar to:
For HP: when I update it, automatically call SendFloatOnWire("HP", hp);
For Position: when I update it, automatically call SendVector3OnWire("Position", Position)
For Name: when I update it, automatically call SendSOnWire("Name", Name);
What are exactly SendFloatOnWire, SendVector3OnWire, SendSOnWire ? Functions that serialize those types in a char buffer.
OR METHOD 2 (Preffered), but might be expensive
Update Hp, Position normally and then every Network Thread tick scan all GameObject instances on the server for the changed variables and send those.
How would that be implemented on a high scale game server and what are my options? Any useful book for such cases?
Would macros turn out to be useful? I think I was explosed to some source code of something similar and I think it used macros.
Thank you in advance.
EDIT: I think I've found a solution, but I don't know how robust it actually is. I am going to have a go at it and see where I stand afterwards. https://developer.valvesoftware.com/wiki/Networking_Entities
On method 1:
Such an approach could be relatively "easy" to implement using a maps, that are accessed via getters/setters. The general idea would be something like:
class GameCharacter {
map<string, int> myints;
// same for doubles, floats, strings
public:
GameCharacter() {
myints["HP"]=100;
myints["FP"]=50;
}
int getInt(string fld) { return myints[fld]; };
void setInt(string fld, int val) { myints[fld]=val; sendIntOnWire(fld,val); }
};
Online demo
If you prefer to keep the properties in your class, you'd go for a map to pointers or member pointers instead of values. At construction you'd then initialize the map with the relevant pointers. If you decide to change the member variable you should however always go via the setter.
You could even go further and abstract your Champion by making it just a collection of properties and behaviors, that would be accessed via the map. This component architecture is exposed by Mike McShaffry in Game Coding Complete (a must read book for any game developer). There's a community site for the book with some source code to download. You may have a look at the actor.h and actor.cpp file. Nevertheless, I really recommend to read the full explanations in the book.
The advantage of componentization is that you could embed your network forwarding logic in the base class of all properties: this could simplify your code by an order of magnitude.
On method 2:
I think the base idea is perfectly suitable, except that a complete analysis (or worse, transmission) of all objects would be an overkill.
A nice alternative would be have a marker that is set when a change is done and is reset when the change is transmitted. If you transmit marked objects (and perhaps only marked properties of those), you would minimize workload of your synchronization thread, and reduce network overhead by pooling transmission of several changes affecting the same object.
Overall conclusion I arrived at: Having another call after I update the position, is not that bad. It is a line of code longer, but it is better for different motives:
It is explicit. You know exactly what's happening.
You don't slow down the code by making all kinds of hacks to get it working.
You don't use extra memory.
Methods I've tried:
Having maps for each type, as suggest by #Christophe. The major drawback of it was that it wasn't error prone. You could've had HP and Hp declared in the same map and it could've added another layer of problems and frustrations, such as declaring maps for each type and then preceding every variable with the mapname.
Using something SIMILAR to valve's engine: It created a separate class for each networking variable you wanted. Then, it used a template to wrap up the basic types you declared (int, float, bool) and also extended operators for that template. It used way too much memory and extra calls for basic functionality.
Using a data mapper that added pointers for each variable in the constructor, and then sent them with an offset. I left the project prematurely when I realised the code started to be confusing and hard to maintain.
Using a struct that is sent every time something changes, manually. This is easily done by using protobuf. Extending structs is also easy.
Every tick, generate a new struct with the data for the classes and send it. This keeps very important stuff always up to date, but eats a lot of bandwidth.
Use reflection with help from boost. It wasn't a great solution.
After all, I went with using a mix of 4, and 5. And now I am implementing it in my game. One huge advantage of protobuf is the capability of generating structs from a .proto file, while also offering serialisation for the struct for you. It is blazingly fast.
For those special named variables that appear in subclasses, I have another struct made. Alternatively, with help from protobuf I could have an array of properties that are as simple as: ENUM_KEY_BYTE VALUE. Where ENUM_KEY_BYTE is just a byte that references a enum to properties such as IS_FLYING, IS_UP, IS_POISONED, and VALUE is a string.
The most important thing I've learned from this is to have as much serialization as possible. It is better to use more CPU on both ends than to have more Input&Output.
If anyone has any questions, comment and I will do my best helping you out.
ioanb7

Using getter/setter vs "tell, don't ask"?

Tell, don't ask principle here is often pasted to me when I use getters or setters, and people tell me not to use them.
The site clearly explains what I should and what I shouldn't do, but it doesn't really explain WHY I should tell, instead of asking.
I find using getters and setters much more efficient, and I can do more with them.
Imagine a class Warrior with attributes health and armor:
class Warrior {
unsigned int m_health;
unsigned int m_armor;
};
Now someone attacks my warrior with a special attack that reduces his armor for 5 seconds. Using setter's it would be like this:
void Attacker::attack(Warrior *target)
{
target->setHealth(target->getHealth() - m_damage);
target->setArmor(target->getArmor() - 20);
// wait 5 seconds
target->setArmor(target->getArmor() + 20);
}
And with tell, don't ask principle it would look like this (correct me if i'm wrong):
void Attacker::attack(Warrior *target)
{
target->hurt(m_damage);
target->reduceArmor(20);
// wait 5 seconds
target->increaseArmor(20);
}
Now the second one obviously looks better, but I can't find the real benefits of this.
You still need the same amount of methods (increase/decrease vs set/get) and you lose the benefit of asking if you ever need to ask.
For example, how would you set warriors health to 100?
How do you figure out whether you should use heal or hurt, and how much health you need to heal or hurt?
Also, I see setters and getters being used by some of the best programmers in the world.
Most APIs use it, and it's being used in the std lib all the time:
for (i = 0; i < vector.size(); i++) {
my_func(i);
}
// vs.
vector.execForElements(my_func);
And if I have to decide whether to believe people here linking me one article about telling, not asking, or to believe 90% of the large companies (apple, microsoft, android, most of the games, etc. etc.) who have successfully made a lot of money and working programs, it's kinda hard for me to understand why would tell, don't ask be a good principle.
Why should I use it (should I?) when everything seems easier with getters and setters?
You still need the same amount of methods (increase/decrease vs set/get) and you lose the benefit of asking if you ever need to ask.
You got it wrong. The point is to replace the getVariable and setVariable with a meaningful operation: inflictDamage, for example. Replacing getVariable with increaseVariable just gives you different more obscure names for the getter and setter.
Where does this matter. For example, you don't need to provide a setter/getter to track the armor and health differently, a single inflictDamage can be processed by the class by trying to block (and damaging the shield in the process) and then taking damage on the character if the shield is not sufficient or your algorithm demands it. At the same time you can add more complex logic in a single place.
Add a magic shield that will temporarily increase the damage caused by your weapons for a short time when taking damage, for example. If you have getter/setters all attackers need to see if you have such an item, then apply the same logic in multiple places to hopefully get to the same result. In the tell approach attackers still need to just figure out how much damage they do, and tell it to your character. The character can then figure out how the damage is spread across the items, and whether it affects the character in any other way.
Complicate the game and add fire weapons, then you can have inflictFireDamage (or pass the fire damage as a different argument to the inflictDamage function). The Warrior can figure out whether she is affected by a fire resistance spell and ignore the fire damage, rather than having all other objects in the program try to figure out how their action is going to affect the others.
Well, if that's so, why bother with getters and setters after all? You can just have public fields.
void Attacker::attack(Warrior *target)
{
target->health -= m_damage;
target->armor -= 20;
// wait 5 seconds
target->armor += 20;
}
The reason is simple here. Encapsulation. If you have setters and getters, it's no better than public field. You don't create a struct here. You create a proper member of your program with defined semantics.
Quoting the article:
The biggest danger here is that by asking for data from an object, you
are only getting data. You’re not getting an object—not in the large
sense. Even if the thing you received from a query is an object
structurally (e.g., a String) it is no longer an object semantically.
It no longer has any association with its owner object. Just because
you got a string whose contents was “RED”, you can’t ask the string
what that means. Is it the owners last name? The color of the car? The
current condition of the tachometer? An object knows these things,
data does not.
The article here suggests here that "tell, don't ask" is better here because you can't do things that make no sense.
target->setHealth(target->getArmor() - m_damage);
It doesn't make sense here, because the armor has nothing in relation to health.
Also, you got it wrong with std lib here. Getters and setters are only used in std::complex and that's because of language lacking functionality (C++ hadn't had references then). It's the opposite, actually. C++ standard library encourages usage of algorithms, to tell the things to do on containers.
std::for_each(begin(v), end(v), my_func);
std::copy(begin(v), end(v), begin(u));
One reason that comes to mind is the ability to decide where you want the control to be.
For example, with your setter/getter example, the caller can change the Warrior's health arbitrarily. At best, your setter might enforce maximum and minimum values to ensure the health remains valid. But if you use the "tell" form you can enforce additional rules. You might not allow more than a certain amount of damage or healing at once, and so on.
Using this form gives you much greater control over the Warrior's interface: you can define the operations that are permitted, and you can change their implementation without having to rewrite all the code that calls them.
At my point of view, both codes do the same thing. The difference is in the expressivity of each one. The first one (setters anad getters) can be more expressive than the second one (tell, don' ask).
It's true that, when you ask, you are going to make a decision. But it not happens in most part of times. Sometimes you just want to know or set some value of the object, and this is not possible with tell, don't ask.
Of course, when you create a program, it's important to define the responsabilities of an object and make sure that these responsabilities remains only inside the object, letting the logic of your application out of it. This we already know, but if you need ask to make a decision that's not a responsability of your object, how do you make it with tell, don't ask?
Actually, getters and setters prevails, but it's common to see the idea of tell, don't ask together with it. In other words, some APIs has getters and setters and also the methods of the tell, don't ask idea.

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?

Is it a good practice to write classes that typically have only one public method exposed?

The more I get into writing unit tests the more often I find myself writing smaller and smaller classes. The classes are so small now that many of them have only one public method on them that is tied to an interface. The tests then go directly against that public method and are fairly small (sometimes that public method will call out to internal private methods within the class). I then use an IOC container to manage the instantiation of these lightweight classes because there are so many of them.
Is this typical of trying to do things in a more of a TDD manner? I fear that I have now refactored a legacy 3,000 line class that had one method in it into something that is also difficult to maintain on the other side of the spectrum because there is now literally about 100 different class files.
Is what I am doing going too far? I am trying to follow the single responsibility principle with this approach but I may be treading into something that is an anemic class structure where I do not have very intelligent "business objects".
This multitude of small classes would drive me nuts. With this design style it becomes really hard to figure out where the real work gets done. I am not a fan of having a ton of interfaces each with a corresponding implementation class, either. Having lots of "IWidget" and "WidgetImpl" pairings is a code smell in my book.
Breaking up a 3,000 line class into smaller pieces is great and commendable. Remember the goal, though: it's to make the code easier to read and easier to work with. If you end up with 30 classes and interfaces you've likely just created a different type of monster. Now you have a really complicated class design. It takes a lot of mental effort to keep that many classes straight in your head. And with lots of small classes you lose the very useful ability to open up a couple of key files, pick out the most important methods, and get an idea of what the heck is going on.
For what it's worth, though, I'm not really sold on test-driven design. Writing tests early, that's sensible. But reorganizing and restructuring your class design so it can be more easily unit tested? No thanks. I'll make interfaces only if they make architectural sense, not because I need to be able to mock up some objects so I can test my classes. That's putting the cart before the horse.
You might have gone a bit too far if you are asking this question. Having only one public method in a class isn't bad as such, if that class has a clear responsibility/function and encapsulates all logic concerning that function, even if most of it is in private methods.
When refactoring such legacy code, I usually try to identify the components in play at a high level that can be assigned distinct roles/responsibilities and separate them into their own classes. I think about which functions should be which components's responsibility and move the methods into that class.
You write a class so that instances of the class maintain state. You put this state in a class because all the state in the class is related.You have function to managed this state so that invalid permutations of state can't be set (the infamous square that has members width and height, but if width doesn't equal height it's not really a square.)
If you don't have state, you don't need a class, you could just use free functions (or in Java, static functions).
So, the question isn't "should I have one function?" but rather "what state-ful entity does my class encapsulate?"
Maybe you have one function that sets all state -- and you should make it more granular, so that, e.g., instead of having void Rectangle::setWidthAndHeight( int x, int y) you should have a setWidth and a separate setHeight.
Perhaps you have a ctor that sets things up, and a single function that doesIt, whatever "it" is. Then you have a functor, and a single doIt might make sense. E.g., class Add implements Operation { Add( int howmuch); Operand doIt(Operand rhs);}
(But then you may find that you really want something like the Visitor Pattern -- a pure functor is more likely if you have purely value objects, Visitor if they're arranged in a tree and are related to each other.)
Even if having these many small objects, single-function is the correct level of granularity, you may want something like a facade Pattern, to compose out of primitive operations, often-used complex operations.
There's no one answer. If you really have a bunch of functors, it's cool. If you're really just making each free function a class, it's foolish.
The real answer lies in answering the question, "what state am I managing, and how well do my classes model my problem domain?"
I'd be speculating if I gave a definite answer without looking at the code.
However it sounds like you're concerned and that is a definite flag for reviewing the code. The short answer to your question comes back to the definition of Simple Design. Minimal number of classes and methods is one of them. If you feel like you can take away some elements without losing the other desirable attributes, go ahead and collapse/inline them.
Some pointers to help you decide:
Do you have a good check for "Single Responsibility" ? It's deceptively difficult to get it right but is a key skill (I still don't see it like the masters). It doesn't necessarily translate to one method-classes. A good yardstick is 5-7 public methods per class. Each class could have 0-5 collaborators. Also to validate against SRP, ask the question what can drive a change into this class ? If there are multiple unrelated answers (e.g. change in the packet structure (parsing) + change in the packet contents to action map (command dispatcher) ) , maybe the class needs to be split. On the other end, if you feel that a change in the packet structure, can affect 4 different classes - you've run off the other cliff; maybe you need to combine them into a cohesive class.
If you have trouble naming the concrete implementations, maybe you don't need the interface. e.g. XXXImpl classes implmenting XXX need to be looked at. I recently learned of a naming convention, where the interface describes a Role and the implementation is named by the technology used to implement the role (or falling back to what it does). e.g. XmppAuction implements Auction (or SniperNotifier implements AuctionEventListener)
Lastly are you finding it difficult to add / modify / test existing code (e.g. test setup is long or painful ) ? Those can be signs that you need to go refactoring.

Design choice with a container class that several classes use

I have a class that wraps around a list called ExplosionGroup (previously called AllExplosions for reasons I'll explain) which is a list of 'Explosion's (another class).
My original design choice, and what ran for awhile, was to have an ExplosionGroup in the 'Level' class that runs all the levels. Any classes (like ships or bosses) that had functions that would cause them to explode would have this ExplosionGroup passed to those functions. So basically, the Level's ExplosionGroup was sucking in all of the explosions created (hence it was then called AllExplosions).
void Foo::Explode( AllExplosions &explosions ) {
...// Create the explosion
explosions.Add( newExplosions );
}
Recently I ran into a problem where this solution wouldn't work since I needed to create an explosion outside one of these functions, and just putting the code in those functions would a) not make any sense and b) not work correctly.
Thus I came up with the idea to have each of the classes that exploded have their own explosion group. This would allow the classes to deal with explosions however they want, not just in a function where an ExplosionGroup was passed. Then I wrote a TakeExplosions function for ExplosionGroup (which just uses std::list's splice) which took an ExplosionGroup parameter and sucked all of the explosions out of that group. This would be used by Level in unison with an accessor for each classes' ExplosionGroup.
void Foo::TakeExplosions( ExplosionGroup &explosions ) {
m_Explosions.splice( m_Explosions.end(), explosions );
}
I thought this was great, but I've realized that if I use this technique I'll want to use it for all classes that can explode to be consistent. However, there are a few special cases in which I'll need to do this indirectly in order to get the explosions to the Level's explosions. For example, a Boss class holds a BlockWall (a list of blocks), and blocks explode.
Thus, the block wall would need to extract explosions from its blocks, the boss would need to extract explosions from the block wall, and the level would need to extract explosions from the Boss (unless I provided an accessor for the Boss' wall, which I have no intention of doing).
I really don't want to use a global container for explosions so that all of the classes can just add in explosions as they please and be done with it, so I'm asking for any recommendations or ideas towards this issue. I've also considered ditching handling explosions in the Level class and having each class handling in completely on its own, but that seems like a bad abstraction to me.
someBlockWall.ShowExplosions( p_Buffer );
playerShip.ShowExplosions( p_Buffer );
// etc. Seems ugly?
P.S. I understand that its hard to answer a question like this without knowing how animations in the game work, etc. I'm also being tempted to use a global container because I'm slightly worried that all of this playing with lists could have performance implications. However, I haven't done any profiling so I'm trying not to even consider it.
I have no answers, just some questions that would help others (and maybe also yourself) to find a good answer.
What are the exact steps that have to be performed in order to show an explosion?
What are my invariants here? (e.g. are all explosions the same, are the object-specific, dependant on time or position on the level)
Which objects are involved in showing an explosion (renderer, clock, explodable object, etc.)?
There are many possible solutions, but it is hard to choose without knowing all the forces involved.