I have these two methods on a class that differ only in one method call. Obviously, this is very un-DRY, especially as both use the same formula.
int PlayerCharacter::getAttack() {
int attack;
attack = 1 + this->level;
for(int i = 0; i < this->current_equipment; i++) {
attack += this->equipment[i].getAttack();
}
attack *= sqrt(this->level);
return attack;
}
int PlayerCharacter::getDefense() {
int defense;
defense = 1 + this->level;
for(int i = 0; i < this->current_equipment; i++) {
defense += this->equipment[i].getDefense();
}
defense *= sqrt(this->level);
return defense;
}
How can I tidy this up in C++?
"Don't repeat yourself" (DRY) is a principle of software development aimed at reducing repetition of software patterns, replacing it with abstractions or using data normalization to avoid redundancy.
DRY, which stands for 'don't repeat yourself,' is a principle of software development that aims at reducing the repetition of patterns and code duplication in favor of abstractions and avoiding redundancy.
The DRY (don't repeat yourself) principle is a best practice in software development that recommends software engineers to do something once, and only once.
One easy way is to represent all of a piece of equipment's attributes in an array, indexed by an enum.
enum Attributes {
Attack,
Defense,
AttributeMAX
};
class Equipment {
std::vector<int> attributes;
Equipment(int attack, int defense): attributes(AttributeMAX)
{
attributes[ATTACK] = attack;
attributes[DEFENSE] = defense;
}
};
Then you change your function to
int PlayerCharacter::getAttribute(int& value, Attribute attribute) {
value = 1 + this->level;
for(int i = 0; i <= current_equipment; i++) {
value += this->equipment[i].attributes[attribute];
}
value *= sqrt(this->level);
return value;
}
And you can call it like so
player.getAttribute(player.attack, Attack);
In my opinion, what you have is fine, as it will allow you to tweak attack/defense more than if you represented both of them with one function. Once you start testing your game, you'll begin balancing attack/defense formulas, so having separate functions for them is fine.
The whole concept of DRY [don't repeat yourself] is [hopefully] to prevent your code from becoming a huge copy & paste fest. In your situation, the defense/attack formulas will change over time [for example, what if characters have buffs/status-ailment? A specific status ailment might cut defense in half, while increasing attack by 2 (Berserk, FF reference, heh)]
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