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

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.

A8f72e32766355f12a56ede9aaa0ee78?s=128

Stefan Koopmanschap

August 23, 2013
Tweet

Transcript

  1. Practical Refactoring Thursday, August 22, 13

  2. Refactoring Thursday, August 22, 13

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

  4. Refactoring • What is it? • Why would we do

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

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

    it? • When do we do it? • How do we do it? Thursday, August 22, 13
  7. What? Thursday, August 22, 13

  8. Thursday, August 22, 13

  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
  10. Why? Thursday, August 22, 13

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

  12. Thursday, August 22, 13

  13. Thursday, August 22, 13

  14. Code quality Thursday, August 22, 13

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

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

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

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

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

    maintainability • Upgrade performance • Increase stability Thursday, August 22, 13
  20. Functionality Thursday, August 22, 13

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

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

    13
  23. Thursday, August 22, 13

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

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

  26. DON’T... • Just beautify your code • Refactor because of

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

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

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

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

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

    development • It is part of the process Thursday, August 22, 13
  32. Example Thursday, August 22, 13

  33. Example if ($order) { if ( ! $order->retryPossible()) { throw

    new BadRequestHttpException('Order already exists for ShoppingCart'); } } Thursday, August 22, 13
  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
  35. Example Thursday, August 22, 13

  36. Example public function isOpen() { return ( $this->getOrder() === null

    || $this->getOrder()->retryPossible() === true ); } Thursday, August 22, 13
  37. Thursday, August 22, 13

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

  39. Thursday, August 22, 13

  40. When? Thursday, August 22, 13

  41. Continuously Thursday, August 22, 13

  42. Really Thursday, August 22, 13

  43. Continuously Thursday, August 22, 13

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

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

    13
  46. Continuously Thursday, August 22, 13

  47. Continuously • Your code gets better, one step at a

    time Thursday, August 22, 13
  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
  49. How? Thursday, August 22, 13

  50. Isolation Thursday, August 22, 13

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

    13
  52. Isolation • Small, independant classes and methods • Class or

    method too big? refactor again! Thursday, August 22, 13
  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'].'<br />'; echo nl2br($row['message']) . '<br /><br />'; } Thursday, August 22, 13
  54. Thursday, August 22, 13

  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'].'<br />'; echo nl2br($row['message']) . '<br /><br />'; } Thursday, August 22, 13
  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'].'<br />'; echo nl2br($row['message']) . '<br /><br />'; } Thursday, August 22, 13
  57. Thursday, August 22, 13

  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
  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'].'<br />'; echo nl2br($row['message']) . '<br /><br />'; } Thursday, August 22, 13
  60. Thursday, August 22, 13

  61. Thursday, August 22, 13

  62. Thursday, August 22, 13

  63. Tests Thursday, August 22, 13

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

    13
  65. Tests • Tests are contracts and verifications • Contract: Code

    should do what is tested Thursday, August 22, 13
  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
  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
  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
  69. <?php 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
  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
  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
  72. When you change your test... Thursday, August 22, 13

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

    13
  74. Tests Thursday, August 22, 13

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

  76. Tests • Untested code? • Write tests before refactoring if

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

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

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

    possible • Write tests during refactoring • Tested code? • Expand those tests Thursday, August 22, 13
  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
  81. So, refactoring Thursday, August 22, 13

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

  83. So, refactoring • What is it? • Why would we

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

    do it? • When do we do it? Thursday, August 22, 13
  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
  86. Thank you! • https://joind.in/talk/view/8978 • http://php.ingewikkeld.net/ Thursday, August 22, 13