Slide 1

Slide 1 text

Bringing your application into 2014

Slide 2

Slide 2 text

Refactoring your application in 2014

Slide 3

Slide 3 text

Refactoring your application

Slide 4

Slide 4 text

A practical guide to surviving legacy code

Slide 5

Slide 5 text

A practical guide to surviving any code

Slide 6

Slide 6 text

I’m Michael! • @mheap on Twitter • Fifth time at PHPNW! • Developer at…

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Let me paint you a picture

Slide 9

Slide 9 text

Job interview

Slide 10

Slide 10 text

Job offer

Slide 11

Slide 11 text

10am Start

Slide 12

Slide 12 text

Awesome workstation

Slide 13

Slide 13 text

$dbhost = 'localhost:3036';! $dbuser = 'root';! $dbpass = 'rootpassword';! $conn = mysql_connect($dbhost, $dbuser, $dbpass);! if(! $conn )! {! die('Could not connect: ' . mysql_error());! }! $sql = 'SELECT id, name FROM employee';! ! mysql_select_db('test_db');! $retval = mysql_query( $sql, $conn );! if(! $retval )! {! die('Could not get data: ' . mysql_error());! }! while($row = mysql_fetch_array($retval, MYSQL_ASSOC))! {! echo "EMP ID :{$row['id']}
".! "EMP NAME : {$row['name']}
".! "--------------------------------
";! } ! echo "Fetched data successfully\n";! mysql_close($conn);!

Slide 14

Slide 14 text

The harsh truth

Slide 15

Slide 15 text

All code is legacy code

Slide 16

Slide 16 text

Not about intentions

Slide 17

Slide 17 text

Fixing it

Slide 18

Slide 18 text

Disclaimer

Slide 19

Slide 19 text

Why put the effort in?

Slide 20

Slide 20 text

Reduce complexity

Slide 21

Slide 21 text

Increase maintainability

Slide 22

Slide 22 text

Improve performance

Slide 23

Slide 23 text

Better stability

Slide 24

Slide 24 text

Prerequisites

Slide 25

Slide 25 text

Refactor != Rewrite

Slide 26

Slide 26 text

No new functionality

Slide 27

Slide 27 text

Modern PHP

Slide 28

Slide 28 text

Version control

Slide 29

Slide 29 text

Choose a standard

Slide 30

Slide 30 text

Leave the code a little better than you found it

Slide 31

Slide 31 text

PSR

Slide 32

Slide 32 text

PSR0/4

Slide 33

Slide 33 text

PSR2

Slide 34

Slide 34 text

Request lifecycle

Slide 35

Slide 35 text

Dependency

Slide 36

Slide 36 text

Action

Slide 37

Slide 37 text

Response

Slide 38

Slide 38 text

What about our code?

Slide 39

Slide 39 text

".! "EMP NAME : {$row['name']}
".! "--------------------------------
";! } ! echo "Fetched data successfully\n";! mysql_close($conn);! ?>!

Slide 40

Slide 40 text

Write a test

Slide 41

Slide 41 text

Run the test

Slide 42

Slide 42 text

".! "EMP NAME : {$row['name']}
".! "--------------------------------
";! } ! echo "Fetched data successfully\n";! mysql_close($conn);! ?>!

Slide 43

Slide 43 text

".! "EMP NAME : {$row['name']}
".! "--------------------------------
";! } ! echo "Fetched data successfully\n";! mysql_close($conn);! ?>!

Slide 44

Slide 44 text

…! ! mysql_select_db('test_db');! $retval = mysql_query( $sql, $conn );! if(! $retval )! {! die('Could not get data: ' . mysql_error());! }! while($row = mysql_fetch_array($retval, MYSQL_ASSOC))! {! echo "EMP ID :{$row['id']}
".! "EMP NAME : {$row['name']}
".! "--------------------------------
";! } ! ! …!

Slide 45

Slide 45 text

…! ! mysql_select_db('test_db');! $retval = mysql_query( $sql, $conn );! if(! $retval )! {! die('Could not get data: ' . mysql_error());! }! ! $data = array();! ! while($row = mysql_fetch_array($retval, MYSQL_ASSOC))! {! ! $data[] = $row;! }! ! foreach ($data as $row)! echo "EMP ID :{$row['id']}
".! "EMP NAME : {$row['name']}
".! "--------------------------------
";! } ! ! …

Slide 46

Slide 46 text

…! ! $data = array(! ! array("id" => 1, "name" => "Michael ")! );! ! foreach ($data as $row)! echo "EMP ID :{$row['id']}
".! "EMP NAME : {$row['name']}
".! "--------------------------------
";! } ! ! …!

Slide 47

Slide 47 text

!

Slide 48

Slide 48 text

1, "name" => "Michael ")! );! ! include 'employee_view.php';! ! ?>!

Slide 49

Slide 49 text

!

Slide 50

Slide 50 text

!

Slide 51

Slide 51 text

!

Slide 52

Slide 52 text

!

Slide 53

Slide 53 text

conn );! ! ! if(! $retval )! ! ! {! ! ! die('Could not get data: ' . mysql_error());! ! ! }! ! ! ! while($row = mysql_fetch_array($retval, MYSQL_ASSOC))! ! ! {! ! ! ! $data[] = $row;! ! ! }! ! ! ! return $data;! ! ! }! }!

Slide 54

Slide 54 text

query('SELECT id, name FROM employee');! include 'employee_view.php';! ! include 'db_teardown.php';! ?>!

Slide 55

Slide 55 text

query('SELECT id, name FROM employee');! ! }! }!

Slide 56

Slide 56 text

db = $db;! ! }! ! ! public function getAllEmployees() {! ! ! return $this->db->query('SELECT id, name FROM employee');! ! }! }!

Slide 57

Slide 57 text

getAllEmployees();! include 'employee_view.php';! ! include 'db_teardown.php';! ?>!

Slide 58

Slide 58 text

class Db

Slide 59

Slide 59 text

/src/Db.php

Slide 60

Slide 60 text

class Foo_Bar_Baz

Slide 61

Slide 61 text

/src/Foo/Bar/Baz.php

Slide 62

Slide 62 text

class \mheap\Foo

Slide 63

Slide 63 text

src mheap/Foo.php

Slide 64

Slide 64 text

getAllEmployees();! include 'employee_view.php';! ?>!

Slide 65

Slide 65 text

db = $db;! ! }! ! ! public function getAllEmployees() {! ! ! return $this->db->query('SELECT id, name FROM employee');! ! }! }!

Slide 66

Slide 66 text

db = $db;! ! }! ! ! public function getAllEmployees() {! ! ! return $this->db->query(‘SELECT id, name FROM employee');! ! }! }!

Slide 67

Slide 67 text

getAllEmployees();! include 'employee_view.php';! ?>!

Slide 68

Slide 68 text

getAllEmployees();! ! $response = new Response();! ob_start();! include 'employee_view.php';! $reponse->content = ob_get_contents();! ob_end_clean();! ! $response->send();! ?>!

Slide 69

Slide 69 text

assertEquals($response->content, "EMP ID: ...etc");! ! ?>!

Slide 70

Slide 70 text

And more!

Slide 71

Slide 71 text

Do it alongside your app

Slide 72

Slide 72 text

No content

Slide 73

Slide 73 text

No content

Slide 74

Slide 74 text

Review

Slide 75

Slide 75 text

Dependency

Slide 76

Slide 76 text

Action

Slide 77

Slide 77 text

Response

Slide 78

Slide 78 text

Small, reusable classes

Slide 79

Slide 79 text

Don’t change behaviour

Slide 80

Slide 80 text

Useful tools

Slide 81

Slide 81 text

PHPCS

Slide 82

Slide 82 text

PHPMD

Slide 83

Slide 83 text

PHPCPD

Slide 84

Slide 84 text

“Don’t Repeat Yourself” was never about code. It’s about knowledge. It’s about cohesion. If two pieces of code represent the exact same knowledge, they will always change together. Having to change them both is risky: you might forget one of them. On the other hand, if two identical pieces of code represent different knowledge, they will change independently. De-duplicating them introduces risk, because changing the knowledge for one object, might accidentally change it for the other object. - http://verraes.net/2014/08/dry-is-about-knowledge/

Slide 85

Slide 85 text

Qafoo Refactoring Tools

Slide 86

Slide 86 text

Scrutinizer CI

Slide 87

Slide 87 text

The parts that didn’t fit

Slide 88

Slide 88 text

Testing legacy code

Slide 89

Slide 89 text

Working with external dependencies

Slide 90

Slide 90 text

Most of the PHP-FIG work

Slide 91

Slide 91 text

Logging strategies

Slide 92

Slide 92 text

Automation

Slide 93

Slide 93 text

Effective version control

Slide 94

Slide 94 text

Find me later

Slide 95

Slide 95 text

Parting thoughts

Slide 96

Slide 96 text

Perfect is the enemy of better

Slide 97

Slide 97 text

Optimise for reading code

Slide 98

Slide 98 text

$ordersWithProducts rather than $data.

Slide 99

Slide 99 text

markReadAndNotifyUser() rather than markRead(true)

Slide 100

Slide 100 text

Constants are good

Slide 101

Slide 101 text

Code doesn't lie

Slide 102

Slide 102 text

Any questions?

Slide 103

Slide 103 text

Thank you http://joind.in/11802