$30 off During Our Annual Pro Sale. View Details »

Practical Refactoring (NomadPHP)

Practical Refactoring (NomadPHP)

Every codebase builds up some legacy over time, there is hardly a way around that. But how you handle the legacy is what seperates a good developer from a great developer. Refactoring code should be a part of your every day work, but how to effectively refactor your code? How to ensure the quality of the new code as well as the fact that refactoring code won’t break something elsewhere in your code? During this talk we’ll go into the why, when and how of refactoring.

Stefan Koopmanschap

August 23, 2013
Tweet

More Decks by Stefan Koopmanschap

Other Decks in Technology

Transcript

  1. Practical Refactoring
    Thursday, August 22, 13

    View Slide

  2. Refactoring
    Thursday, August 22, 13

    View Slide

  3. Refactoring
    • What is it?
    Thursday, August 22, 13

    View Slide

  4. Refactoring
    • What is it?
    • Why would we do it?
    Thursday, August 22, 13

    View Slide

  5. Refactoring
    • What is it?
    • Why would we do it?
    • When do we do it?
    Thursday, August 22, 13

    View Slide

  6. Refactoring
    • What is it?
    • Why would we do it?
    • When do we do it?
    • How do we do it?
    Thursday, August 22, 13

    View Slide

  7. What?
    Thursday, August 22, 13

    View Slide

  8. Thursday, August 22, 13

    View Slide

  9. Code refactoring is the process of changing a computer
    program's internal structure without modifying its
    external behavior or existing functionality.
    Thursday, August 22, 13

    View Slide

  10. Why?
    Thursday, August 22, 13

    View Slide

  11. Code is never perfect
    Thursday, August 22, 13

    View Slide

  12. Thursday, August 22, 13

    View Slide

  13. Thursday, August 22, 13

    View Slide

  14. Code quality
    Thursday, August 22, 13

    View Slide

  15. Code quality
    • Lessen complexity
    Thursday, August 22, 13

    View Slide

  16. Code quality
    • Lessen complexity
    • Increase readability
    Thursday, August 22, 13

    View Slide

  17. Code quality
    • Lessen complexity
    • Increase readability
    • Increase maintainability
    Thursday, August 22, 13

    View Slide

  18. Code quality
    • Lessen complexity
    • Increase readability
    • Increase maintainability
    • Upgrade performance
    Thursday, August 22, 13

    View Slide

  19. Code quality
    • Lessen complexity
    • Increase readability
    • Increase maintainability
    • Upgrade performance
    • Increase stability
    Thursday, August 22, 13

    View Slide

  20. Functionality
    Thursday, August 22, 13

    View Slide

  21. Functionality
    • New functionality
    Thursday, August 22, 13

    View Slide

  22. Functionality
    • New functionality
    • Updated functionality
    Thursday, August 22, 13

    View Slide

  23. Thursday, August 22, 13

    View Slide

  24. DON’T...
    Thursday, August 22, 13

    View Slide

  25. DON’T...
    • Just beautify your code
    Thursday, August 22, 13

    View Slide

  26. DON’T...
    • Just beautify your code
    • Refactor because of refactoring
    Thursday, August 22, 13

    View Slide

  27. Selling refactoring to
    your manager/customer
    Thursday, August 22, 13

    View Slide

  28. What’s in it for them?
    Thursday, August 22, 13

    View Slide

  29. What’s in it for them?
    • Less bugs
    Thursday, August 22, 13

    View Slide

  30. What’s in it for them?
    • Less bugs
    • Faster development
    Thursday, August 22, 13

    View Slide

  31. What’s in it for them?
    • Less bugs
    • Faster development
    • It is part of the process
    Thursday, August 22, 13

    View Slide

  32. Example
    Thursday, August 22, 13

    View Slide

  33. Example
    if ($order) {
    if ( ! $order->retryPossible()) {
    throw new BadRequestHttpException('Order already exists for ShoppingCart');
    }
    }
    Thursday, August 22, 13

    View Slide

  34. Example
    if ($order) {
    if ( ! $order->retryPossible()) {
    throw new BadRequestHttpException('Order already exists for ShoppingCart');
    }
    }
    public function isOpen()
    {
    return $this->getOrder() === null;
    }
    Thursday, August 22, 13

    View Slide

  35. Example
    Thursday, August 22, 13

    View Slide

  36. Example
    public function isOpen()
    {
    return (
    $this->getOrder() === null ||
    $this->getOrder()->retryPossible() === true
    );
    }
    Thursday, August 22, 13

    View Slide

  37. Thursday, August 22, 13

    View Slide

  38. A good read
    http://robots.thoughtbot.com/post/2685998010/ongoing-refactoring-and-client-work
    Thursday, August 22, 13

    View Slide

  39. Thursday, August 22, 13

    View Slide

  40. When?
    Thursday, August 22, 13

    View Slide

  41. Continuously
    Thursday, August 22, 13

    View Slide

  42. Really
    Thursday, August 22, 13

    View Slide

  43. Continuously
    Thursday, August 22, 13

    View Slide

  44. Continuously
    • NOT: Always
    Thursday, August 22, 13

    View Slide

  45. Continuously
    • NOT: Always
    • NOT: Immediately
    Thursday, August 22, 13

    View Slide

  46. Continuously
    Thursday, August 22, 13

    View Slide

  47. Continuously
    • Your code gets better, one step at a time
    Thursday, August 22, 13

    View Slide

  48. Continuously
    • Your code gets better, one step at a time
    • You don’t spend ages on refactoring, it’s
    part of the project
    Thursday, August 22, 13

    View Slide

  49. How?
    Thursday, August 22, 13

    View Slide

  50. Isolation
    Thursday, August 22, 13

    View Slide

  51. Isolation
    • Small, independant classes and methods
    Thursday, August 22, 13

    View Slide

  52. Isolation
    • Small, independant classes and methods
    • Class or method too big? refactor again!
    Thursday, August 22, 13

    View Slide

  53. mysql_connect('127.0.0.1', 'root');
    mysql_select_db('refactoring');
    $newsSQL = "SELECT * FROM NEWS ORDER BY published_at DESC";
    $result = mysql_query($newsSQL);
    while($row = mysql_fetch_assoc($result))
    {
    echo $row['published_at'] . ': ' . $row['title'].'
    ';
    echo nl2br($row['message']) . '

    ';
    }
    Thursday, August 22, 13

    View Slide

  54. Thursday, August 22, 13

    View Slide

  55. require_once('config.php');
    $db = new PDO('mysql:dbname='.$db_name.';host='.$db_server,
    $db_user, $db_pass);
    $newsSQL = "SELECT * FROM NEWS ORDER BY published_at DESC";
    $stmt = $db->prepare($newsSQL);
    $stmt->execute();
    while($row = $stmt->fetch(PDO::FETCH_ASSOC))
    {
    echo $row['published_at'] . ': ' . $row['title'].'
    ';
    echo nl2br($row['message']) . '

    ';
    }
    Thursday, August 22, 13

    View Slide

  56. $db_server = '127.0.0.1';
    $db_user = 'root';
    $db_pass = '';
    $db_name = 'refactoring';
    require_once('config.php');
    $db = new PDO('mysql:dbname='.$db_name.';host='.$db_server,
    $db_user, $db_pass);
    $newsSQL = "SELECT * FROM NEWS ORDER BY published_at DESC";
    $stmt = $db->prepare($newsSQL);
    $stmt->execute();
    while($row = $stmt->fetch(PDO::FETCH_ASSOC))
    {
    echo $row['published_at'] . ': ' . $row['title'].'
    ';
    echo nl2br($row['message']) . '

    ';
    }
    Thursday, August 22, 13

    View Slide

  57. Thursday, August 22, 13

    View Slide

  58. class NewsRepository
    {
    private $db;
    public function __construct($db)
    {
    $this->db = $db;
    }
    public function getAllNews()
    {
    $newsSQL = "SELECT * FROM NEWS ORDER BY published_at
    DESC";
    $stmt = $this->db->prepare($newsSQL);
    $stmt->execute();
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    }
    Thursday, August 22, 13

    View Slide

  59. require_once('config.php');
    require_once('NewsRepository.php');
    $db = new PDO('mysql:dbname='.$db_name.';host='.$db_server,
    $db_user, $db_pass);
    $newsRepo = new NewsRepository($db);
    $news = $newsRepo->getAllNews();
    foreach($news as $row)
    {
    echo $row['published_at'] . ': ' . $row['title'].'
    ';
    echo nl2br($row['message']) . '

    ';
    }
    Thursday, August 22, 13

    View Slide

  60. Thursday, August 22, 13

    View Slide

  61. Thursday, August 22, 13

    View Slide

  62. Thursday, August 22, 13

    View Slide

  63. Tests
    Thursday, August 22, 13

    View Slide

  64. Tests
    • Tests are contracts and verifications
    Thursday, August 22, 13

    View Slide

  65. Tests
    • Tests are contracts and verifications
    • Contract: Code should do what is tested
    Thursday, August 22, 13

    View Slide

  66. Tests
    • Tests are contracts and verifications
    • Contract: Code should do what is tested
    • Verification: Does it do what is tested?
    Thursday, August 22, 13

    View Slide

  67. Tests
    • Tests are contracts and verifications
    • Contract: Code should do what is tested
    • Verification: Does it do what is tested?
    • Don’t change the tests
    Thursday, August 22, 13

    View Slide

  68. Tests
    • Tests are contracts and verifications
    • Contract: Code should do what is tested
    • Verification: Does it do what is tested?
    • Don’t change the tests
    • Just expand the test
    Thursday, August 22, 13

    View Slide

  69. class NewsRepositoryTest extends PHPUnit_Framework_TestCase
    {
    $private $MockDb;
    public function setUp()
    {
    // here we set up the mock class
    $this->MockDb = new MockDb();
    }
    public function testGetAllNews()
    {
    $newsRepo = new NewsRepository($this->MockDb);
    // mock repo returns 2 newsitems
    $news = $newsRepo->getAllNews();
    $this->assertEquals(2, count($news));
    }
    }
    Thursday, August 22, 13

    View Slide

  70. public function getAllNews($limit = null)
    {
    $newsSQL = "SELECT * FROM NEWS ORDER BY published_at DESC";
    if ( ! is_null($limit)) {
    $newsSQL .= " LIMIT 0, " . $limit;
    }
    $stmt = $this->db->prepare($newsSQL);
    $stmt->execute();
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    Thursday, August 22, 13

    View Slide

  71. public function testGetAllNews()
    {
    $newsRepo = new NewsRepository($this->MockDb);
    // mock repo returns 2 newsitems
    $news = $newsRepo->getAllNews();
    $this->assertEquals(2, count($news));
    // new functionality: limit the newsitems
    $news = $newsRepo->getAllNews(1);
    $this->assertEquals(1, count($news));
    }
    Thursday, August 22, 13

    View Slide

  72. When you change your
    test...
    Thursday, August 22, 13

    View Slide

  73. You change the
    behaviour of your code
    Thursday, August 22, 13

    View Slide

  74. Tests
    Thursday, August 22, 13

    View Slide

  75. Tests
    • Untested code?
    Thursday, August 22, 13

    View Slide

  76. Tests
    • Untested code?
    • Write tests before refactoring if possible
    Thursday, August 22, 13

    View Slide

  77. Tests
    • Untested code?
    • Write tests before refactoring if possible
    • Write tests during refactoring
    Thursday, August 22, 13

    View Slide

  78. Tests
    • Untested code?
    • Write tests before refactoring if possible
    • Write tests during refactoring
    • Tested code?
    Thursday, August 22, 13

    View Slide

  79. Tests
    • Untested code?
    • Write tests before refactoring if possible
    • Write tests during refactoring
    • Tested code?
    • Expand those tests
    Thursday, August 22, 13

    View Slide

  80. Your IDE can help
    • Most IDE’s have refactoring support
    • Scan for usage of methods and classes
    • http://qafoo.com/blog/
    041_refactoring_browser.html
    Thursday, August 22, 13

    View Slide

  81. So, refactoring
    Thursday, August 22, 13

    View Slide

  82. So, refactoring
    • What is it?
    Thursday, August 22, 13

    View Slide

  83. So, refactoring
    • What is it?
    • Why would we do it?
    Thursday, August 22, 13

    View Slide

  84. So, refactoring
    • What is it?
    • Why would we do it?
    • When do we do it?
    Thursday, August 22, 13

    View Slide

  85. So, refactoring
    • What is it?
    • Why would we do it?
    • When do we do it?
    • How do we do it?
    Thursday, August 22, 13

    View Slide

  86. Thank you!
    • https://joind.in/talk/view/8978
    • http://php.ingewikkeld.net/
    Thursday, August 22, 13

    View Slide