![]() Then measure performance and refactor bottlenecks. Pick a decomposition based on the other factors, ![]() Performance: The more levels of abstraction you introduce,.Readability: What do your project team and technology community consider readable?Īll things being equal, familiar idioms are easier to read,īut introducing a new approach to decomposition might aid readability in the long run.The RPG’s damage algorithm is likely to be entirely replaced early in development, What parts of your code tend to change at the same time, and what parts don’t? Maintenance: What does a developer performing enhancements need to keep in their mind to do the change?.Reusing functions across classes might be important. In the RPG, if some weapons have unique damage calculations, Reuse: After you’ve decomposed your code into parts,ĭo those parts need to be reused within the function?.Or would breaking it into abstraction layers help readers comprehend it?įor example, this damage calculation is short,īut breaking it up makes the meaning of the parts of the calculation much more clear. Complexity: Is your calculation easy to understand in every detail,.Which Should I Use?īecause readability is almost always improved by using step variables instead.īut the other types of decomposition above all have strengths that make them useful,ĭepending on the context. These levels of abstraction can be an advantage or a disadvantage,ĭepending on how visible that information needs to be. We can see it is calculated from attack_damage, defense_modifier, and scratch_damage,īut we can’t see what those are calculated from without stepping down a level. The “tree” is really a tree of multiple levels of abstraction. 0 ) end def defense_modifier ( max_defense_rating - defense_rating ) / max_defense_rating end def max_defense_rating 256. Ruby makes this decomposition especially readable by allowing you to call methods without parentheses (sometimes referred to as “ barewords”):ĭef damage ( attack_damage * defense_modifier ) + scratch_damage end private def attack_damage attack_rating * attack_modifier end def attack_modifier rng. Each method might use data from instance variables or from other private methods. Private Method TreeĪ calculation can be split up into a “tree” of private methods that each performs part of the calculation. If you want to hide these details, rather than making a method chain private, there’s another option. ![]() Method chaining provides the same level of re-use as a public function chain,Īs well as the same cost in terms of coupling to implementation details. 0 self end def apply_scratch_damage += 1 self end def amount end end 0 ) self end def apply_defense ( defense_rating ) *= ( 256. amount class Damage def initialize ( damage_amount ) = damage_amount end def randomize *= Random. This can be referred to as “reassignment,”īecause one variable has different values assigned to it at different times:ĭamage = Damage. Storing the result of each step in a variable. One way to decompose this expression is to break it up into steps, Let’s look at how decomposition can make its meaning clearer. It means the code doesn’t communicate its intent without additional commentary. The fact that I had to explain the code is a bad sign: (Rather than adding it conditionally, for simplicity I just always add 1 to the damage.) 1 is added to ensure that, even if the attack is nullified, it always does 1 “scratch” damage.While a rating less than 256 nullifies a proportional amount of the damage. The defending character has a defense rating.Ī defense rating of 256 nullifies the attack entirely,.The damage they do for a given attack varies randomly between 90% and 100% of that value.The attacking character has a base attack rating.
0 Comments
Leave a Reply. |