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

Rewriting Legacy Code

Rewriting Legacy Code

Did you ever have to maintain a 15-year-old application? Dead code everywhere, hard dependencies, null pointer exceptions, database queries mixed with HTML, no tests and most libraries have been discontinued.

This presentation will show you how to modernize your application using a variety of strategies. You will learn how to avoid common pitfalls, automate legacy testing, manage your development environment and overcome various challenges that arise from dealing with legacy.

Anna Filina
PRO

August 20, 2020
Tweet

More Decks by Anna Filina

Other Decks in Programming

Transcript


  1. Rewriting
    Legacy Code
    SKILLS MATTER | AUG 20, 2020
    @afilina

    View Slide

  2. Anna Filina
    ‣ Coding since 1997.
    ‣ Legacy archaeology.
    ‣ Test automation.
    ‣ Talks and workshops.
    ‣ Twitter advice (@afilina)
    ‣ YouTube videos.

    View Slide

  3. You Inherited a

    10-Year-Old Codebase

    View Slide

  4. You Inherited a

    15-Year-Old Codebase

    View Slide

  5. You Inherited a

    20-Year-Old Codebase

    View Slide

  6. View Slide

  7. History Since 2000
    2004
    PHP 5.0
    2005
    Symfony
    2006
    Zend Framework
    2008
    Clean Code
    2011
    Laravel
    2001
    PHPUnit

    View Slide

  8. Legacy Sadness

    View Slide

  9. 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 10 children down.
    ‣ methodName_new, methodName_new2

    View Slide

  10. 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.

    View Slide

  11. How to Fail a Rewrite

    View Slide

  12. Microservices
    AWS
    GitHub
    Flutter
    CircleCI
    ElasticSearch Ansible
    Docker
    Symfony 5

    View Slide

  13. Start With the Strategy

    View Slide

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

    View Slide

  15. Version Upgrade
    ‣ No need to freeze development.
    ‣ PHPCodeSniffer can detect incompatibilities.
    ‣ Also need to patch libs & framework.
    ‣ Some libs might be easier to swap than to fix (PHPExcel).
    ‣ Regexes are your friends.
    ‣ Rector can automatically refactor.

    View Slide

  16. View Slide

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

    View Slide

  18. Product/IndexHandler
    ProductController
    indexAction
    viewAction
    Product/ViewHandler
    Routes
    Routes
    Product/BaseHandler

    View Slide

  19. 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)

    );
    }
    }

    View Slide

  20. Progressive Rewrite
    ‣ By endpoint/feature
    • Can switch language.
    • Use design extraction.

    View Slide

  21. Old Code
    New Design
    Old Design
    New Code

    View Slide

  22. ‣ Remove dead code.
    ‣ Move logic to a better location.
    ‣ Split long functions.
    Techniques

    View Slide

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

    View Slide

  24. 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.

    View Slide

  25. Testing Approaches

    View Slide

  26. Version Upgrade
    Characterization tests Fix code
    Should work

    for old and new
    versions.
    Unit tests
    New/refactored code.
    What failed in E2E.

    View Slide

  27. New Framework
    Characterization tests Migrate
    Should work

    for old and new
    versions.
    Unit tests
    New/refactored code.
    What failed in E2E.

    View Slide

  28. Progressive Rewrite
    For new code only.
    Characterization tests Unit tests
    Should work

    for old and new
    versions.
    New code

    View Slide

  29. Refactoring Only
    For the 

    upcoming code.
    Characterization tests Unit tests
    Should work

    for old and new
    versions.
    Refactor

    View Slide

  30. Preparing the
    Environments

    View Slide

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

    View Slide

  32. services:
    php_apache: //...
    mysql: //...
    acceptance: //...
    mysql_test: //...

    View Slide

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

    View Slide

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

    View Slide


  35. @afilina
    @afilina

    View Slide