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

Réécriture de code vieux de 15 ans

Réécriture de code vieux de 15 ans

Avez-vous déjà eu à maintenir une application de 15 ans? Du code mort partout, des requêtes de base de données entre les balises HTML et quelques pages encore en PHP 3. Cette présentation de niveau stratégique vous mènera à travers une réécriture progressive depuis du code legacy à la dernière version de PHP. Apprenez à automatiser les tests de legacy, vous balader de façon transparente entre le vieux et nouveau code, et à surmonter d'autres défis qui se posent lorsqu'on travaille avec du legacy.

Anna Filina
PRO

July 07, 2016
Tweet

More Decks by Anna Filina

Other Decks in Programming

Transcript

  1. foolab.ca | @foolabca
    Réécriture de code vieux
    de 15 ans
    PHP Québec, Montréal - 7 juillet, 2016

    View Slide

  2. Anna Filina
    • Développement.
    • Résolution de problèmes.
    • Formation.
    • Conseil stratégique.
    • FooLab + ConFoo.
    2

    View Slide

  3. Vous avez hérité

    d'une application de 10 ans

    View Slide

  4. Vous avez hérité

    d'une application de 12 ans

    View Slide

  5. Vous avez hérité

    d'une application de 15 ans

    View Slide

  6. Vous avez hérité

    d'une application de 15 ans
    Le code ne vieillit pas comme le vin

    View Slide

  7. Le web était 600px de large
    7

    View Slide

  8. Il y a 15 ans
    • Bug Y2K.
    • Google lance AdWords.
    • Pas de Twitter, Facebook, ou iTunes.
    • Internet Explorer 5.
    • Coins arrondis = marque de statut.
    8

    View Slide

  9. Objectifs
    • Réduire les erreurs.
    • Augmenter la vitesse de dev.
    • Réduire la dette technique.
    • Conseils.
    9

    View Slide

  10. Mon expérience
    legacy

    View Slide

  11. Fichier legacy moyen
    • 3000-6000 lignes de code.
    • La moitié est commentée "juste au cas".
    • Méthodes de 800 lignes en moyenne.
    • Abus de classes "helper".
    • Souvent pas de classes.
    11

    View Slide

  12. Code applicatif
    • 5,000 classes.
    • 20,000 méthodes.
    • 1,500,000 lignes de code.
    12

    View Slide

  13. Prendre le code par les
    cornes

    View Slide

  14. Duplication de code
    • Étape 1!
    • Parfois, un bogue est répété 80+ fois.
    • Réutiliser le code et éliminer les duplications.
    14

    View Slide

  15. Méthodes trop longues (800 lignes)
    • Extraire la partie brisée dans une méthode séparée.
    • Écrire les tests pour cette méthode.
    • Corriger le bogue.
    • Appeller à partir de la méga-méthode.
    15

    View Slide

  16. Fausse sécurité
    16

    View Slide

  17. Fausse sécurité
    $clean = htmlentities($_POST['id']);
    16

    View Slide

  18. Fausse sécurité
    $clean = htmlentities($_POST['id']);
    // utilisez les fonctions "filter" ou un framework
    $clean = filter_var($_POST['id'],
    FILTER_SANITIZE_NUMBER_INT);
    16

    View Slide

  19. Fausse sécurité
    $clean = htmlentities($_POST['id']);
    // utilisez les fonctions "filter" ou un framework
    $clean = filter_var($_POST['id'],
    FILTER_SANITIZE_NUMBER_INT);
    // utilisez les requêtes préparées
    $stmt = $pdo->prepare(
    "SELECT * FROM user WHERE id = :id");
    16

    View Slide

  20. Fausse sécurité
    $clean = htmlentities($_POST['id']);
    // utilisez les fonctions "filter" ou un framework
    $clean = filter_var($_POST['id'],
    FILTER_SANITIZE_NUMBER_INT);
    // utilisez les requêtes préparées
    $stmt = $pdo->prepare(
    "SELECT * FROM user WHERE id = :id");
    $stmt->bindParam(':id', $clean);
    $stmt->execute();
    16

    View Slide

  21. Qu'est-il arrivé à la commande 20117?
    17

    View Slide

  22. Qu'est-il arrivé à la commande 20117?
    if ($order_id > 20117) {
    // utiliser cet sql
    } else {
    // utiliser cet sql
    }
    17

    View Slide

  23. Qu'est-il arrivé à la commande 20117?
    if ($order_id > 20117) {
    // utiliser cet sql
    } else {
    // utiliser cet sql
    }
    // réparez les données précédentes
    17

    View Slide

  24. Mélange de HTML, PHP et includes
    18

    View Slide

  25. Mélange de HTML, PHP et includes




    $sql = 'SELECT * FROM transactions t WHERE t.id
    IN('.join(',', $tids).')';
    ?>
    18

    View Slide

  26. Mélange de HTML, PHP et includes
    19

    View Slide

  27. Mélange de HTML, PHP et includes




    $transactions = $user->getTransactions();
    ?>
    19

    View Slide

  28. Trop d'arguments
    20

    View Slide

  29. Trop d'arguments
    protected function getMock($originalClassName,
    $methods = [], array $arguments = [],
    $mockClassName = '', $callOriginalConstructor =
    true, $callOriginalClone = true, $callAutoload =
    true, $cloneArguments = false, $callOriginalMethods
    = false, $proxyTarget = null)
    {
    20

    View Slide

  30. Trop d'arguments
    21

    View Slide

  31. Trop d'arguments
    $mock = $this->getMockBuilder($originalClassName)
    ->disableOriginalConstructor()
    ->disableOriginalClone()
    ->disableArgumentCloning()
    ->disallowMockingUnknownTypes()
    ->getMock();
    21

    View Slide

  32. Préparation
    22

    View Slide

  33. Préparation
    • Besoin de logging.
    ◦ Monolog si la version PHP le permet.
    ◦ Au pire: file_put_contents.
    22

    View Slide

  34. Préparation
    • Besoin de logging.
    ◦ Monolog si la version PHP le permet.
    ◦ Au pire: file_put_contents.
    • Besoin de tests.
    ◦ Mocker les méthodes statiques: Patchwork ou équivalent.
    ◦ Caching des appels API.
    22

    View Slide

  35. Stratégie
    • Élaborez une stratégie autour
    des contraintes.
    • Réécriture complète ou
    progressive.
    ◦ Par fichier/classe.
    ◦ Par module.
    ◦ Par appel HTTP.
    23

    View Slide

  36. Examples
    contraintes ⟶ stratégie

    View Slide

  37. PHP 3 à PHP 5.6
    • HTML + PHP + SQL dans le même fichier.
    • Des includes partout.
    • IFs qui concatènent du SQL.
    • Tentative de réécriture antérieure.
    ◦ Échec, rendu pire.
    ◦ Dossiers de code mort.
    ◦ Du mauvais code écrit de deux façons.
    ◦ Aucune notion d'orienté-objet.
    25

    View Slide

  38. Solution
    • Réécrire formulaires complexes en Symfony 2.
    ◦ Approche: appel HTTP.
    ◦ mod_rewrite pour les pages concernées.
    • Réécrire le module le plus brisé en orienté-objet.
    ◦ Approche: module.
    ◦ Extraction de conception.
    ◦ Test unitaires.
    ◦ Architecture flexible.
    26

    View Slide

  39. Extraction de
    conception

    View Slide

  40. Éviter le biais du code
    • Ancien code → conception.
    • Valider la conception.
    ◦ Clarifier les règles d'affaires.
    • Améliorer la conception.
    ◦ Réduire dette technique.
    ◦ Plus flexible.
    • Conception → nouveau code.
    28

    View Slide

  41. Avant de coder....

    View Slide

  42. Les données se perdent, les choses se brisent
    • Sauvegarde: tester la restauration.
    • Environment staging: versions d'app, configurations.
    • Simuler déploiements/upgrades.
    • Automatiser des tests avant les changements.
    • Évaluer le risque.
    ◦ Ne soyez pas trop optimistes.
    ◦ Considérez les effets secondaires: coût, temps de réparation.
    30

    View Slide

  43. D'autres exemples

    View Slide

  44. ASP Classic à PHP 5.6
    • Spaghetti et hacks de 15+ ans.
    • Le language n'est plus supporté.
    • Gros ERP avec beaucoup de code.
    32

    View Slide

  45. Solution
    • Réécriture dans Symfony 2, page par page.
    • mod_rewrite pour les pages concernées.
    • Adapteur de session dans BD dans les deux apps.
    • Page dans n'importe quel langage = requête HTTP
    ◦ Tests Guzzle.
    33

    View Slide

  46. Tests Guzzle
    34

    View Slide

  47. PHP 5.3 à PHP 5.6
    • Spaghetti et hacks de 12+ ans.
    • Utilise des fonctions obsolètes.
    • Ne peut pas rouler sur PHP 5.6.
    35

    View Slide

  48. Solution
    • Séparer en serveurs 5.3 et 5.6 pour un nouveau départ.
    • REST et design patterns modernes.
    • Frontend en AngularJS.
    36

    View Slide

  49. Séparer les serveurs
    37

    View Slide

  50. Alias est votre ami (5.3 server)
    Alias "/module-name" "/var/www/project/angular"

    RewriteBase /module-name/

    38

    View Slide

  51. Coincé?

    View Slide

  52. Essayez du nouveau
    • Échangez des idées.
    ◦ Nouvelles personnes qui ne connaissent pas le projet.
    • Est-ce que ça a été fait avant?
    • Essayez une approche complètement différente.
    40

    View Slide

  53. Demandez aux experts en legacy
    • Posez des questions.
    • Lisez leur blogue.
    • Embauchez-en au pour une journée de conseils.
    ◦ Stratégie de refactoring.
    ◦ Enlever les blocages.
    ◦ Coaching / workshops / suivi.
    41

    View Slide

  54. Anna Filina
    • Développement.
    • Résolution de bogues et problèmes de performance.
    • Formation sur tests, Symfony et API.
    • Conseil sur stratégie de tests et legacy.
    42

    View Slide

  55. @afilina afilina.com

    View Slide