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

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
  2. 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
  3. Objectifs • Réduire les erreurs. • Augmenter la vitesse de

    dev. • Réduire la dette technique. • Conseils. 9
  4. 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
  5. Duplication de code • Étape 1! • Parfois, un bogue

    est répété 80+ fois. • Réutiliser le code et éliminer les duplications. 14
  6. 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
  7. Fausse sécurité $clean = htmlentities($_POST['id']); // utilisez les fonctions "filter"

    ou un framework $clean = filter_var($_POST['id'], FILTER_SANITIZE_NUMBER_INT); 16
  8. 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
  9. 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
  10. Qu'est-il arrivé à la commande 20117? if ($order_id > 20117)

    { // utiliser cet sql } else { // utiliser cet sql } 17
  11. 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
  12. Mélange de HTML, PHP et includes <?php include 'common.php' ?>

    <?php include 'admin.php' ?> <?php include 'user.php' ?> <table> <?php $sql = 'SELECT * FROM transactions t WHERE t.id IN('.join(',', $tids).')'; ?> 18
  13. Mélange de HTML, PHP et includes <?php include 'common.php' ?>

    <?php include 'admin.php' ?> <?php include 'user.php' ?> <table> <?php $transactions = $user->getTransactions(); ?> 19
  14. Trop d'arguments protected function getMock($originalClassName, $methods = [], array $arguments

    = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false, $callOriginalMethods = false, $proxyTarget = null) { 20
  15. Préparation • Besoin de logging. ◦ Monolog si la version

    PHP le permet. ◦ Au pire: file_put_contents. 22
  16. 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
  17. Stratégie • Élaborez une stratégie autour des contraintes. • Réécriture

    complète ou progressive. ◦ Par fichier/classe. ◦ Par module. ◦ Par appel HTTP. 23
  18. 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
  19. 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
  20. É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
  21. 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
  22. ASP Classic à PHP 5.6 • Spaghetti et hacks de

    15+ ans. • Le language n'est plus supporté. • Gros ERP avec beaucoup de code. 32
  23. 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
  24. 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
  25. Solution • Séparer en serveurs 5.3 et 5.6 pour un

    nouveau départ. • REST et design patterns modernes. • Frontend en AngularJS. 36
  26. Alias est votre ami (5.3 server) Alias "/module-name" "/var/www/project/angular" <Directory

    "/var/www/project/angular"> RewriteBase /module-name/ </Directory> 38
  27. 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
  28. 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
  29. 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