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

Rewriting Legacy Code

Rewriting Legacy Code

Video: https://youtu.be/bTuvjjtGipY

Did you ever have to maintain a 20-year-old application? Dead code and tables everywhere, static methods, database queries in between HTML tags and some pages still in PHP3.

This presentation will lead you through a progressive rewrite from very old legacy to the latest shiny version of PHP. Learn how to automate legacy testing, how to pick the right rewrite strategy, and how to overcome other challenges that arise from dealing with legacy.

Anna Filina

May 13, 2020

More Decks by Anna Filina

Other Decks in Technology


  1. Anna Filina ‣ Coding since 1997. ‣ Legacy archaeology. ‣

    Test automation. ‣ Talks and workshops. ‣ YouTube videos.
  2. Web in 2000 ‣ Y2K bug. ‣ Internet Explorer 5.

    ‣ ICQ was starting to be cool. ‣ Background music. ‣ Rounded corners = status symbol.
  3. 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
  4. 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.
  5. 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.
  6. New Framework ‣ Use dependency injection. ‣ Automate large chunks

    with Rector. ‣ Use adapters. ‣ Need to freeze development.
  7. 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)
 ); } }
  8. Progressive Rewrite ‣ By class. ‣ By module • Can

    switch language. • Use design extraction.
  9. ‣ Some criteria for refactoring: • Need to change. •

    Hard to understand, but need to work with it. Refactoring Only
  10. 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.
  11. Tests ‣ No tests. ‣ Not runnable. ‣ Failing. ‣

    Brittle: specific environment or inter-dependencies. ‣ Unreliable.
  12. Dead Code ‣ Unused endpoints. ‣ Commented-out code. ‣ Unused

    classes or methods: exercise extreme caution. ‣ Merge duplicated code (bug repeated 80 times).
  13. Progressive Rewrite For new code only. Acceptance tests Unit tests

    Should work
 for old and new versions. New code
  14. Refactoring Only For the code that you want to write.

    Acceptance tests Unit tests Should work
 for old and new versions. Refactor
  15. Gotchas ‣ Pay attention to MySQL mode. ‣ Run composer

    inside Docker, commit composer.lock ‣ Anonymized production database. ‣ Send e-mails to relay: DebugMail, MailTrap, etc.