Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Does your code spark joy? Refactoring techniques to make your life easier.

jucycabrera
December 12, 2020

Does your code spark joy? Refactoring techniques to make your life easier.

A presentation based on Martin Fowler's book:
Refactoring - Improving the design of existing code.

jucycabrera

December 12, 2020
Tweet

More Decks by jucycabrera

Other Decks in Technology

Transcript

  1. 2 Juciellen Cabrera @jucycabrera Mother of a really smart boy

    PHP and Elephpants PHPWomen Living in Ireland Food lover Meme specialist Software Engineer at Smartbox Group
  2. 4 @jucycabrera A change made to the internal structure of

    software to make it easier to understand and cheaper to modify without changing its observable behavior. Refactoring (noun) It’s also a common error to see refactoring as something to fix past mistakes or clean up ugly code.
  3. 5 @jucycabrera The idea that building an application that will

    not undergo any changes are untrue most of the time. As people change code to achieve short-term goals, often without a full comprehension of the architecture, the code loses its structure. Loss of structure has a cumulative effect. You will find yourself refactoring ugly code, but good code also needs refactoring.
  4. 6 @jucycabrera Self-testing code not only enables refactoring - it

    also makes it much safer to add new features, since any bugs introduced with the new feature can be quickly found and fixed. First things first...
  5. 7 @jucycabrera Bad Smells Smudge, originally known as Cascão, is

    one of the main characters of Monica's Gang. He never takes a bath, he hates water and never, ever touches it.
  6. 8 @jucycabrera Mysterious Name When you can’t think of a

    good name for something, it’s often a sign of a deeper issue.
  7. 9 @jucycabrera Duplicated Code Means that every time you read

    these copies, you need to read them carefully to see if there’s any difference.
  8. 10 @jucycabrera Long Function The longer the function, the more

    difficult is to understand. Large Class A class with too much code is a bad opportunity for duplicated code and chaos.
  9. 11 @jucycabrera Shotgun Surgery When every time you make a

    change, you have to make a lot of little edits to a lot of different classes.
  10. 12 @jucycabrera Long Parameter List Long parameter lists are often

    confusing. Primitive Obsession Primitive types, such as integers, floating pointing numbers and strings, don’t represent a type of data we are dealing with.
  11. 13 @jucycabrera Speculative Generality Things created before they are needed.

    • Abstract class that isn’t doing much • Unnecessary delegation • Functions with unused parameters
  12. 14 @jucycabrera Repeated Switches It also applies to if statement.

    When the same conditional switching logic appears in different places and you add a clause, it is necessary to find all switches and update them.
  13. 16 @jucycabrera Comments When you feel the need to write

    a comment, first try to refactor the code so that any comment becomes unnecessary. Polemic topic!
  14. 18 @jucycabrera Extract Function If you have to spend effort

    looking at a block of code trying to figure out what it’s doing then you should extract it into a function. Inline Function Inverse of Extract Function, where a function has a body as clear as the name.
  15. 19 @jucycabrera Extract Class When you see a class that

    is too big to easily understand, you need to consider where it can be split. Inline Class When a class is no longer pulling its weight and shouldn’t be around anymore.
  16. 20 @jucycabrera Hide Delegate Encapsulation means that modules need to

    know less about other parts of the system. Remove Middle Man Opposite of Hide Delegate. Law of Demeter.
  17. 21 @jucycabrera Extract Variable Add a name to an expression

    that is complex and hard to read. Inline Variable When the name doesn’t really communicate more than the expression itself. Named properties PHP 8
  18. 22 @jucycabrera Change Function Declaration | Rename Method A good

    name allows you to understand what the function does when you see it called. Rename Variable Naming things well is at the heart of a clear programming. Rename Fields Fields names are important especially when they are widely used across an application.
  19. 24 @jucycabrera Introduce Parameters Object Groups of data that are

    often together could be replaced by a data structure. Replace Primitive with Object e.g. Phone number, money Preserve Whole Object Values from the same object passed as an argument can be replaced by passing the whole object.
  20. 25 @jucycabrera Substitute Algorithm Replace the complicated logic with a

    simpler one by decomposing the method, or creating a new algorithm or even using a native function.
  21. 26 @jucycabrera Move Function | Move Field A nested function

    to a top level, or between classes. Slide Statements Code is easier to understand when things related to each other appear together.
  22. 27 @jucycabrera Split Loop You ensure you only need to

    understand one thing a time. Separate refactoring from optimization. $averageAge = 0; $totalSalary = 0; foreach ($people as $person) { $averageAge += $person->page; $totalSalary += $person->salary; } $averageAge = $averageAge / count($people); $averageAge = 0; $totalSalary = 0; foreach ($people as $person) { $averageAge += $person->page; } foreach ($people as $person) { $totalSalary += $person->salary; } $averageAge = $averageAge / count($people);
  23. 28 @jucycabrera Remove Dead Code Commenting out dead code is

    a common habit. Don’t be afraid to delete dead code. We have version control. Joelma: One of Brazil’s Queens
  24. 29 @jucycabrera Decomposite Conditional Apply “Extract Function” on the condition

    and each leg of the conditional. if ($date->before(SUMMER_START) || $date->after(SUMMER_END)) { $charge = $quantity * $winterRate + $winterServiceCharge; } else { $charge = $quantity * $summerRate; } if (isSummer($date)) { $charge = summerCharge($quantity); } else { $charge = winterCharge($quantity); }
  25. 30 @jucycabrera Replace Nested Conditional with Guard Clauses By reversing

    the conditions for example. function getPayAmount() { if ($this->isDead) { $result = $this->deadAmount(); } else { if ($this->isSeparated) { $result = $this->separatedAmount(); } else { if ($this->isRetired) { $result = $this->retiredAmount(); } else { $result = $this->normalPayAmount(); } } } return $result; } function getPayAmount() { if ($this->isDead) { return $this->deadAmount(); } if ($this->isSeparated) { return $this->separatedAmount(); } if ($this->isRetired) { return $this->retiredAmount(); } return $this->normalPayAmount(); }
  26. 31 @jucycabrera Replace Conditional with Polymorphism Create subclasses matching the

    branches of the conditional. abstract class Bird { // ... abstract function getSpeed(); // ... } class European extends Bird { public function getSpeed() { return $this->getBaseSpeed(); } } class African extends Bird { public function getSpeed() { return $this->getBaseSpeed() - $this->getLoadFactor() * $this->numberOfCoconuts; } } class NorwegianBlue extends Bird { public function getSpeed() { return ($this->isNailed) ? 0 : $this->getBaseSpeed($this->voltage); } } // Somewhere in Client code. $speed = $bird->getSpeed(); class Bird { // ... public function getSpeed() { switch ($this->type) { case EUROPEAN: return $this->getBaseSpeed(); case AFRICAN: return $this->getBaseSpeed() - $this->getLoadFactor() * $this->numberOfCoconuts; case NORWEGIAN_BLUE: return ($this->isNailed) ? 0 : $this->getBaseSpeed($this->voltage); } throw new Exception("Should be unreachable"); } // ... }
  27. 32 @jucycabrera Introduce Special Case | Null Object A class

    that provides special behavior for particular cases. if ($customer === null) { $plan = BillingPlan::basic(); } else { $plan = $customer->getPlan(); } class NullCustomer extends Customer { public function isNull() { return true; } public function getPlan() { return new NullPlan(); } // Some other NULL functionality. } // Replace null values with Null-object. $customer = ($order->customer !== null) ? $order->customer : new NullCustomer; // Use Null-object as if it's normal subclass. $plan = $customer->getPlan();
  28. 33 @jucycabrera Separate Query from Modifier A function that returns

    a value should not have observable side effects. The famous case of findAndDoSomethingElse.
  29. 34 @jucycabrera Parameterize Function Functions that have similar logic with

    different values can be removed by using a single function with parameters.
  30. 35 @jucycabrera Remove Flag Argument Flag argument is used to

    indicate which logic the function should execute. It’s clear to provide an explicit function for each task.
  31. 36 @jucycabrera Replace Constructor with Factory Function By creating a

    single point where the class is instantiated you avoid tight coupling. class Employee { // ... public function __construct($type) { $this->type = $type; } // ... } class Employee { // ... static public function create($type) { $employee = new Employee($type); // do some heavy lifting. return $employee; } // ... }
  32. 37 @jucycabrera Extract Super class Pull Up Method Pull Up

    Field Push Down Method Push Down Field Dealing with Inheritance
  33. 38 @jucycabrera The key to effective refactoring is recognizing that

    you go faster when you take tiny steps Martin Fowler
  34. 39 @jucycabrera Tips Keep an eye on updates PHP8 is

    live! Tests first! Create them if you don’t have any Tiny steps Don’t waste an opportunity to improve code Code review is a chance to discuss changes
  35. 40 @jucycabrera Find more by Martin Fowler, with Kent Beck

    2018 - 2nd edition https://martinfowler.com/books/refactoring.html Refactoring Improving the Design of Existing Code https://refactoring.guru