Practical Refactoring (PHPNW14)

Practical Refactoring (PHPNW14)

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

October 04, 2014
Tweet

Transcript

  1. 2.

    Refactoring • What is it? • Why would we do

    it? • When do we do it? • How do we do it?
  2. 3.
  3. 4.
  4. 5.

    Code refactoring is the process of changing a computer program's

    internal structure without modifying its external behavior or existing functionality.
  5. 6.
  6. 8.
  7. 9.
  8. 10.

    Code quality • Lessen complexity • Increase readability • Increase

    maintainability • Upgrade performance • Increase stability
  9. 12.
  10. 15.

    What’s in it for them? • Less bugs • Faster

    development • It is part of the process
  11. 16.

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

    new BadRequestHttpException('Order already exists for ShoppingCart'); } } public function isOpen() { return $this->getOrder() === null; } public function isOpen() { return ( $this->getOrder() === null || $this->getOrder()->retryPossible() === true ); }
  12. 17.
  13. 19.
  14. 20.
  15. 22.
  16. 24.

    Continuously • Your code gets better, one step at a

    time • You don’t spend ages on refactoring, it’s part of the project
  17. 25.
  18. 27.

    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 />'; }
  19. 28.
  20. 29.

    $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 />'; }
  21. 30.
  22. 31.

    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); } }
  23. 32.

    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 />'; }
  24. 33.
  25. 34.
  26. 35.
  27. 36.

    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
  28. 37.

    <?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)); } }
  29. 38.

    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); }
  30. 39.

    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)); }
  31. 42.

    Tests • Untested code? • Write tests before refactoring if

    possible • Write tests during refactoring • Tested code? • Expand those tests
  32. 43.

    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
  33. 45.

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

    do it? • When do we do it? • How do we do it?