The question seems very abstract. I will ask by an example instead.
Assume that I have many types of game objects.
They are Bullet, Rocket, Enemy, Zone, ... .
They are all nicely created & deleted & managed by pools, e.g.
Pool<Bullet> poolBullet ;
Pool<Rocket> poolRocket ;
The game logic would manage object in form of Pool_Handle< xxx >, e.g.
Pool_Handle< Bullet > bullet = poolBullet.create() ;
Pool_Handle< Rocket> rocket = poolRocket .create() ;
Now, I look at the refactoring.
For example, if my old code was ...
Bullet* functionA(Rocket* rocket){
for(int n=0;n<rocket->zones.size();n++){
Zone* zone = rocket->zones.get(n);
Bullet* return_value =zone.functionB();
}
}
... it would become ...
Pool_Handle<Bullet> functionA(Pool_Handle<Rocket> rocket){
for(int n=0;n<rocket->zones.size();n++){
Pool_Handle<Zone> zone = rocket->zones.get(n);
Pool_Handle<Bullet> return_value =zone.functionB();
}
}
Notice that they are now Pool_Handle everywhere.
After reading and editing these thousands line codes for a few days, I have grown accustomed to Pool_Handle even more than any game objects. It might be a word that I type fastest now.
How to retain readability and maintainability to equal level of the old code, and if possible, how to reduce time of typing for the variable template?
I don't expect a perfect answer, because every solution I found has some trade-off.
/** remedy 1 **/
template <class TT> using H = Pool_Handle<TT>; //remedy line
H<Bullet> bullet ; //alleviate symptom, better but not perfect
/** remedy 2 **/
using H_Bullet = Pool_Handle<H_Bullet>; //remedy line
H_Bullet bullet ; //looks good, but have limitations
/** remedy 3 **/
auto bullet; //concise, but can't be used everywhere, sometimes also reduce readability
The second solution seems to be nice, but introduces several limitations.
I have to declare a line for Bullet, Rocket, ... and so on, one by one
If there is a new type of game object, I will have to add another line manually.
If a game object is renamed, e.g. Bullet -> MetalBullet, I will also have to change the remedy line to H_MetalBullet manually.
Therefore, it lowers overall maintainability.
Are there any better approaches?
(Edit) You can assume c++11, c++14, whatever.
(Edit) A platform independent solution is favorable.
In the second solution, I have to add "another" line after declare a new class.
The line is ...
using H_Bullet = Pool_Handle<H_Bullet>;
Where should I place it?
inside Bullet.h ;
It will create bad coupling, because Bullet should not know about the Handle at all.
inside some high-level header that is included by every game logic files ;
The result is that there are 2 different places that has some definitions about Bullet.
More places -> Less maintainability.
Both places will yield a certain minor disadvantage : When I call some automatic refactoring I have to call twice, on both Bullet and H_Bullet.
Readability is a measure of how easy a piece of text is to read. The level of complexity of the text, its familiarity, legibility and typography all feed into how readable your text is.
Use short sentences. Content consisting of short sentences is easier to read than content consisting of long sentences. The benefits of short sentences include improved readability and reduced overthinking. Short sentences allow readers to quickly and easily digest information.
The best way to raise your readability score is to cut down lengthy sentences and replace complex words with simpler ones. Fortunately, Grammarly offers a variety of suggestions to help you write concisely and find the exact word you need in any situation.
Aiming for high readability improves the likelihood that the reader will clearly understand your thoughts and ideas. High readability lessens misunderstanding and lets the reader easily process the information that you've shared without expending a lot of energy.
Using the auto
specifier:
auto object = pool.create();
Complete example:
template <typename T>
class Pool {
public:
class Handle {};
Handle create () const {
return Handle();
}
};
class Object {};
int main () {
Pool<Object> pool;
auto object = pool.create();
}
View Successful Compilation Result
Using a typedef
(for those who do not have access to c++11 features):
Object::Handle object = pool.create();
Complete example:
template <typename T>
class Pool {
public:
class Handle {};
Handle create () const {
return Handle();
}
};
class Object {
public:
typedef Pool<Object>::Handle Handle;
};
int main () {
Pool<Object> pool;
Object::Handle object = pool.create();
}
View Successful Compilation Result
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With