Slide 1

Slide 1 text

Rewriting Legacy Code THE LEGACY OF SOCRATES | MAY 13, 2020 @afilina

Slide 2

Slide 2 text

Anna Filina ‣ Coding since 1997. ‣ Legacy archaeology. ‣ Test automation. ‣ Talks and workshops. ‣ YouTube videos.

Slide 3

Slide 3 text

You Inherited a
 10-Year-Old Codebase

Slide 4

Slide 4 text

You Inherited a
 15-Year-Old Codebase

Slide 5

Slide 5 text

You Inherited a
 20-Year-Old Codebase

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Web in 2000 ‣ Y2K bug. ‣ Internet Explorer 5. ‣ ICQ was starting to be cool. ‣ Background music. ‣ Rounded corners = status symbol.

Slide 8

Slide 8 text

Legacy Sadness

Slide 9

Slide 9 text

The Methods ‣ Can easily exceed a thousand lines. ‣ Mixing SQL, PHP and HTML. ‣ Receiving dozens of arguments of arbitrary type. ‣ Accessing hundreds of potentially undefined properties. ‣ Expect properties to have been set by a child 10 method calls ago. ‣ methodName_new, methodName_new2

Slide 10

Slide 10 text

The Dynamic Types ‣ Null pointer exceptions of every flavor. ‣ Attempting to split an array. ‣ Attempting to divide by a null. ‣ Attempting to count the number of elements in a float. ‣ Attempting to max($array1, $array2),
 where array items are of mixed types.

Slide 11

Slide 11 text

How to Fail a Rewrite

Slide 12

Slide 12 text

Microservices AWS GitHub React CircleCI ElasticSearch Ansible Docker Symfony Ambitious new tech stack

Slide 13

Slide 13 text

Other Ambitions ‣ SOLID. ‣ Test-driven development. ‣ Strong typing. Too many new things at once

Slide 14

Slide 14 text

Expanding Scope ‣ Rethinking existing features. ‣ New features. ‣ New work methodology.

Slide 15

Slide 15 text

Start With the Strategy

Slide 16

Slide 16 text

Strategy ‣ Version upgrade. ‣ New framework. ‣ Progressive rewrite. ‣ Refactoring only. ‣ Full rewrite.

Slide 17

Slide 17 text

Version Upgrade ‣ PHPCodeSniffer can detect incompatibilities. ‣ Some libs might be easier to swap than to fix (PHPExcel). ‣ Regexes are your friends. ‣ Rector can automatically refactor. ‣ Need to freeze development.

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

New Framework ‣ Use dependency injection. ‣ Automate large chunks with Rector. ‣ Use adapters. ‣ Need to freeze development.

Slide 20

Slide 20 text

Product/IndexHandler ProductController indexAction viewAction Product/ViewHandler Routes Routes Product/BaseHandler Example: Zend Framework 1 to Zend Expressive

Slide 21

Slide 21 text

class IndexHandler extends BaseHandler implements RequestHandlerInterface { public function __construct( TemplateRendererInterface $template, ProductModel $productModel ) { //... } public function handle(ServerRequestInterface $request): ResponseInterface { return new HtmlResponse(
 $this->template->render('admin::product/index', $view)
 ); } }

Slide 22

Slide 22 text

Progressive Rewrite ‣ By class. ‣ By module • Can switch language. • Use design extraction.

Slide 23

Slide 23 text

Old Code New Design Old Design New Code

Slide 24

Slide 24 text

‣ Some criteria for refactoring: • Need to change. • Hard to understand, but need to work with it. Refactoring Only

Slide 25

Slide 25 text

Full Rewrite ‣ Discouraged. ‣ My criteria: • Can disregard existing features. • Few or no integrations. • Can trash old database. • If not, need a team experienced in full rewrites.

Slide 26

Slide 26 text

Spot Problems Early ‣ PHPStorm inspections. ‣ Pslam: start with auto-detected level.

Slide 27

Slide 27 text

Unknown Unknowns

Slide 28

Slide 28 text

Docs ‣ No docs. ‣ Too many, little relevance. ‣ Outdated or misleading.

Slide 29

Slide 29 text

Tests ‣ No tests. ‣ Not runnable. ‣ Failing. ‣ Brittle: specific environment or inter-dependencies. ‣ Unreliable.

Slide 30

Slide 30 text

Dead Code ‣ Unused endpoints. ‣ Commented-out code. ‣ Unused classes or methods: exercise extreme caution. ‣ Merge duplicated code (bug repeated 80 times).

Slide 31

Slide 31 text

Testing Approaches

Slide 32

Slide 32 text

Version Upgrade Smoke tests Fix code Should work
 for old and new versions. Unit tests

Slide 33

Slide 33 text

New Framework Smoke tests Migrate Should work
 for old and new versions. Unit tests

Slide 34

Slide 34 text

Progressive Rewrite For new code only. Acceptance tests Unit tests Should work
 for old and new versions. New code

Slide 35

Slide 35 text

Refactoring Only For the code that you want to write. Acceptance tests Unit tests Should work
 for old and new versions. Refactor

Slide 36

Slide 36 text

Preparing the Environments

Slide 37

Slide 37 text

Local Environment ‣ Docker. ‣ Baseline image. ‣ Migration image. ‣ Match server / vagrant.

Slide 38

Slide 38 text

services: php: //... mysql: //... acceptance: //... mysql_test: //...

Slide 39

Slide 39 text

Gotchas ‣ Pay attention to MySQL mode. ‣ Run composer inside Docker, commit composer.lock ‣ Anonymized production database. ‣ Send e-mails to relay: DebugMail, MailTrap, etc.

Slide 40

Slide 40 text

Staging Environment ‣ Baseline server. ‣ Migration server. ‣ Staging config: point to sandboxes.

Slide 41

Slide 41 text

Credit: xebia.com

Slide 42

Slide 42 text

THANKS! @afilina