Ce diaporama a bien été signalé.
Le téléchargement de votre SlideShare est en cours. ×

Conférence #nwx2014 - Maxime Mauchaussée - Partager du code maintenable et évolutif

Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Chargement dans…3
×

Consultez-les par la suite

1 sur 77 Publicité

Plus De Contenu Connexe

Diaporamas pour vous (16)

Publicité

Similaire à Conférence #nwx2014 - Maxime Mauchaussée - Partager du code maintenable et évolutif (20)

Plus par Normandie Web Xperts (20)

Publicité

Plus récents (20)

Conférence #nwx2014 - Maxime Mauchaussée - Partager du code maintenable et évolutif

  1. 1. Partager du code maintenable et évolutif Édition Débutant { PHP Style } @wixiweb / @maximemdotnet
  2. 2. Les années 80 c'est terminé Source : https://secure.flickr.com/photos/flysi/2586786319/in/photostream/
  3. 3. 2014  Fini les nerd qui développent des application à eux tous seul  Entreprise IT / Système d'information / R&D  Freelance / Prestation  Projet open source / communautaire
  4. 4. Les technologies évoluent  L'électronique et l'informatique  Les techniques et langages de programmation  Les services  Les utilisateurs
  5. 5. Internet est omniprésent  Smartphone, tablette, PC, objets connectés  Tout le monde veut être présent  Se démarquer demande de + en + de ressources  Les utilisateurs sont de + en + exigeants
  6. 6. Problématiques Source : https://secure.flickr.com/photos/watz/329055725/in/photostream/
  7. 7. Collaboration vs. Autonomie  Travailler en équipe sans interférer sur les tâches de chacun  Contrôler le code sans être derrière chaque développeur  Intégration de ressource / équipe distante ou télétravail  Être capable de reprendre le code d'un autre développeur
  8. 8. Rapidité vs. Réflexion  Les demandes clients et l'environnement changent  Il faut être réactif et compétitif face à la concurrence  Le manque de visibilité favorise les mauvais choix  Dette technique
  9. 9. Complexité vs. Compréhension  Les architectures sont de + en + complexes  Au fur et à mesure du temps le code devient + complexe  Un code complexe est difficile à maintenir et à changer  La complexité nécessite d'avoir plus de compétences
  10. 10. Pérennité vs. Péremption  Le code a une date de péremption, 3 à 5 ans  Les langages évoluent : amélioration, dépréciation, cassure  Les systèmes d'exploitation évoluent  En tant que développeur, vous évoluez
  11. 11. Solutions Source : https://secure.flickr.com/photos/puuikibeach/3192430591/in/photostream/
  12. 12. 10 trucs & astuces simples et rapides  10 conseils facilement applicables, dès demain !  Centrés sur le travail en équipe et la maintenabilité  Pas besoin d'être un Dieu du PHP pour les utiliser  À peaufiner au quotidien dans votre travail
  13. 13. Disclaimer  Conseils != Règles absolues  Je n'ai pas la prétention de vous apprendre à coder  Mettez en place une organisation à votre échelle  Appliquez le principe du « Close Enough »
  14. 14. Travailler en équipe
  15. 15. 1. Outil de gestion de versions  git, subversion, mercurial  Travailler à plusieurs sur le même code source  Garder un historique et faire des versions de son application  Faire des évolutions et des bugfixes en parallèle
  16. 16. 1. Outil de gestion de versions Source : http://nvie.com/posts/a-successful-git-branching-model/
  17. 17. 2. Utiliser un IDE  Netbeans, PhpStorm, vim  Environnement de Développement Intégré  Regroupe des outils pour coder plus rapidement / facilement  Utiliser le même IDE au sein d'une équipe
  18. 18. 3. Utiliser une convention de codage  PEAR, Zend, PSR-1, PSR-2  Permet d'avoir un code source cohérent et une meilleure prise en main par une personne qui ne l'aurait pas écrit  Les conventions de codage sont faites pour améliorer la lisibilité et éviter les erreurs bêtes  Évite les débats stériles
  19. 19. PSR-*  PHP Framework Interoperability Group (PHP-FIG)  PSR = PHP Specification Request  Une recommandation pour utiliser PHP de manière interopérable  http://www.php-fig.org/
  20. 20. PSR-*  PSR-0 : Standard pour l'Autoloading  PSR-1 : Convention de codage de base  PSR-2 : Convention de style  PSR-4 : Amélioration du standard pour l'Autoloading
  21. 21. PHP_CodeSniffer  https://github.com/squizlabs/PHP_CodeSniffer  Parse le code PHP pour détecter les violations d'une convention de codage définie  Supporte les conventions de codage les + populaires  Tester la compatibilité avec une version de PHP donnée
  22. 22. PHP_CodeSniffer $ phpcs /path/to/code/myfile.php FILE: /path/to/code/myfile.php -------------------------------------------------------------------------------- FOUND 5 ERROR(S) AND 1 WARNING(S) AFFECTING 5 LINE(S) -------------------------------------------------------------------------------- 2 | ERROR | Missing file doc comment 20 | ERROR | PHP keywords must be lowercase; expected "false" but found | | "FALSE" 47 | ERROR | Line not indented correctly; expected 4 spaces but found 1 47 | WARNING | Equals sign not aligned with surrounding assignments 51 | ERROR | Missing function doc comment 88 | ERROR | Line not indented correctly; expected 9 spaces but found 6 --------------------------------------------------------------------------------
  23. 23. PHP_CodeSniffer
  24. 24. 4. Partager un environnement de développement commun  Développer sur un environnement similaire à la production  Système d'exploitation, serveur web, version de PHP, SGBD  Une machine (ou un vhost) par développeur et par projet  Utiliser une solution de virtualisation : docker, proxmox, vagrant
  25. 25. Pourquoi produire du code maintenable ? Source : https://xkcd.com/844/
  26. 26. Deux exemples concrets récents  Le firmware ECM de Toyota  => Un mort  Le bug SSL d'Apple  => Du troll à foison
  27. 27. if ((err = SSLFreeBuffer(&hashCtx)) != 0) goto fail; if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &clientRandom)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) goto fail; goto fail; if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0) goto fail; err = sslRawVerify(ctx, ctx->peerPubKey, dataToSign, /* plaintext */ dataToSignLen, /* plaintext length */ signature, signatureLen); if(err) { sslErrorLog("SSLDecodeSignedServerKeyExchange: sslRawVerify " "returned %dn", (int)err); goto fail; } fail: SSLFreeBuffer(&signedHashes); SSLFreeBuffer(&hashCtx); return err; } Source : https://opensource.apple.com/source/Security/Security-55471/libsecurity_ssl/lib/sslKeyExchange.c?txt
  28. 28. if ((err = SSLFreeBuffer(&hashCtx)) != 0) goto fail; if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &clientRandom)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &serverRandom)) != 0) goto fail; if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) goto fail; goto fail; if ((err = SSLHashSHA1.final(&hashCtx, &hashOut)) != 0) goto fail; err = sslRawVerify(ctx, ctx->peerPubKey, dataToSign, /* plaintext */ dataToSignLen, /* plaintext length */ signature, signatureLen); if(err) { sslErrorLog("SSLDecodeSignedServerKeyExchange: sslRawVerify " "returned %dn", (int)err); goto fail; } fail: SSLFreeBuffer(&signedHashes); SSLFreeBuffer(&hashCtx); return err; }
  29. 29. Le code historique  Legacy code  Code présent avant vous, développé par quelqu'un d'autre  Principe du « touche pas le truc », inchangé depuis des années  Souvent fouillis, complexe, difficilement lisible
  30. 30. Pourquoi détestons-nous le code d'autrui ?  Le code nous paraît complexe  Manque de visibilité sur les choix faits  Syndrôme NIH : Not Invented Here  Avec le temps on déteste notre propre code
  31. 31. Mesurer la complexité WTF / minute
  32. 32. Mesurer la complexité Complexité Cyclomatique  Métrique pour mesurer la complexité logique  ~ Représente le nombre de conditions + boucles dans le code  Plus de conditions équivaut à moins de compréhension  Le cerveau doit être attentif à tous les points de décisions
  33. 33. class Foo { 1 public function example() { 2 if ($a == $b) { 3 if ($a1 == $b1) { fiddle(); 4 } else if ($a2 == $b2) { fiddle(); } else { fiddle(); } 5 } else if ($c == $d) { 6 while ($c == $d) { fiddle(); } 7 } else if ($e == $f) { 8 for ($n = 0; $n > $h; $n++) { fiddle(); } } else{ switch ($z) { 9 case 1: fiddle(); break; 10 case 2: fiddle(); break; 11 case 3: fiddle(); break; 12 default: fiddle(); break; }}}}Source : http://phpmd.org/rules/codesize.html
  34. 34. Mesurer la complexité Complexité N-Path  Représente le nombre de chemins uniques possibles  = nombre de tests nécessaires pour couvrir 100 % des cas  Plus de chemins égale moins de compréhension  Le cerveau doit garder en tête toutes les solutions possibles
  35. 35. Mesurer la complexité Complexité N-Path function example($a, $b) { $c = 0; if ($a < $b) { $c = $a; } elseif ($a > $b) { $c = $b; } if ($c < 2) { $c = $a + $b; } return $c; }
  36. 36. Mesurer la complexité Complexité N-Path
  37. 37. Les seuils idéaux  CC pour une méthode : de 1 à 4  CC moyenne par méthodes : de 1 à 2  CC sur le nombre total de lignes de code : de 0.01 à 0.05  N-Path pour une méthode : de 1 à 16
  38. 38. PHP Mess Detector  http://phpmd.org/  Calcul la complexité d'un code source selon plusieurs indicateurs  Indique l'utilisation de fonctions controversées  Détecte le code mort
  39. 39. PHP Mess Detector
  40. 40. Produire du code maintenable
  41. 41. Qu'est ce qu'un code maintenable ?  Lisible  Compréhensible  Réutilisable  Testable
  42. 42. La meilleure façon d'avoir un code maintenable Source : https://secure.flickr.com/photos/f-oxymoron/9647972522/in/photostream/
  43. 43. La meilleure façon d'avoir un code maintenable Ne pas l'écrire
  44. 44. Source : http://whynne.deviantart.com/art/Comic-Trolls-98357844
  45. 45. La meilleure façon d'avoir un code maintenable  Laisser quelqu'un d'autre coder et corriger à sa place  Ne pas réinventer la roue  L'utilisation de code produit par d'autres est instructif  Attention : ne pas confondre avec le copier / coller !
  46. 46. 5. Utiliser un (bon) framework  Symfony 2, Zend Framework 2, Silex, Aura, Phalcon  Communauté active et ouverte  Des fondateurs / mainteneurs reconnus  Tirant partie des dernières fonctionnalités de PHP
  47. 47. 5. Utiliser un (bon) framework  Symfony 2, Zend Framework 2, Silex, Aura, Phalcon  Communauté active et ouverte  Des fondateurs / mainteneurs reconnus  Tirant partie des dernières fonctionnalités de PHP
  48. 48. Composer  Gestionnaire de dépendances pour PHP  Installe et met à jour les librairies tierces utilisées dans vos projets  Possibilité de télécharger les librairies depuis plusieurs sources : packagist.org par défaut  Génère un fichier pour gérer l'autoload dans vos projet
  49. 49. Composer  composer.json { "require": { "phpmd/phpmd": "~1.5" } }
  50. 50. Composer $ composer.phar install Loading composer repositories with package information Updating dependencies (including require-dev) - Installing symfony/filesystem (v2.5.0) Downloading: 100% - Installing symfony/config (v2.5.0) Downloading: 100% - Installing symfony/dependency-injection (v2.5.0) Downloading: 100% - Installing pdepend/pdepend (2.0.0) Downloading: 100% - Installing phpmd/phpmd (1.5.0) Downloading: 100% symfony/dependency-injection suggests installing symfony/yaml () symfony/dependency-injection suggests installing symfony/proxy-manager-bridge (Generate service proxies to lazy load them) Writing lock file Generating autoload files
  51. 51. Produire du code maintenable (en vrai) Source : https://twitter.com/dr4goonis/status/476617165463105536
  52. 52. Objectifs  Écrire le moins de code possible  Réduire la complexité  Augmenter la ré-utilisabilité  Pouvoir écrire des tests rapidement
  53. 53. Les 5 principes SOLID S Single responsibility Responsabilité unique O Open/closed Ouvert/fermé L Liskov Substitution Substitution de Liskov I Interface Segregation Ségrégation des interfaces D Dependency Inversion Principle Inversion des dépendances
  54. 54. 6. Factoriser son code  20 lignes maximum par méthode  200 lignes maximum par classe  10 méthodes maximum par classe  15 classes maximum par package
  55. 55. 7. Un seul niveau d'indentation par méthode  Pas de condition / boucle imbriquée  Tirer partie des fonctions natives de PHP, + rapides, + lisibles  Responsabilité unique, - complexité, + ré-utilisabilité  Mode ninja : pas de « else »
  56. 56. 7. Un seul niveau d'indentation par méthode  Early return / Guard clauses  Extraire les conditions dans des méthodes : isValid()  PHP propose ~80 fonctions natives pour manipuler les tableaux  D'autres pratiques : http://sourcemaking.com/refactoring/simplifying-conditional-expressions
  57. 57. 7. Un seul niveau d'indentation par méthode
  58. 58. 8. Pas d’abréviation !  Utiliser des noms de variable et méthode qui ont du sens (in english !)  Penser le nommage comme des Lego  Éviter les noms génériques : $index,  $key, $value, $object, etc.  Nom de variable / méthode trop long et dupliqué partout ? → Trop de responsabilités, pas assez de factorisation
  59. 59. $temp = array(); for ($i = 0; $i < strlen($title); $i++) { $ordinal = ord($title[$i]); if ($ordinal < 128) { $x[] = "|".$ordinal; } else { if (count($temp) == 0) { $count = ($ordinal < 224) ? 2 : 3; } $temp[] = $ordinal; if (count($temp) == $count) { $number = ($count == 3) ? (($temp['0'] % 16) * 4096) + (($temp['1'] % 64) * 64) + ($temp['2'] % $x[] = "|".$number; $count = 1; $temp = array(); } } } Source : CodeIgniter 2.2.0
  60. 60. 8. Pas d’abréviation ! Source : http://trollcats.com
  61. 61. 8. Pas d’abréviation ! function findUserByEmail($emailAddress) {} function write(PostTitle $postTitle, PostContent $postContent); $pageCount = ceil(count($userCollection) / $entityPerPage); $addressLines = explode(PHP_EOL, $address);
  62. 62. 8. Pas d’abréviation !
  63. 63. 9. Lisibilité Morbi molestie, elit vitae consectetur adipiscing, orci nulla hendrerit risus, ac vehicula orci eros sed leo. Fusce auctor ut ipsum non pharetra. Nunc at lorem gravida, scelerisque neque sed, lacinia ipsum! Aenean malesuada felis quam, fermentum fermentum elit viverra ut! Ut a orci sapien. Nulla dictum leo et tortor sollicitudin tempus. Aliquam lacinia, quam in condimentum aliquet, nisi augue feugiat ligula; eget cursus felis est sit amet augue. Morbi pulvinar pharetra cursus? Mauris feugiat lectus vel felis bibendum dignissim. In hac habitasse platea dictumst. Phasellus id consectetur magna!
  64. 64. 9. Lisibilité Morbi molestie, elit vitae consectetur adipiscing, orci nulla hendrerit risus, ac vehicula orci eros sed leo. Fusce auctor ut ipsum non pharetra. Nunc at lorem gravida, scelerisque neque sed, lacinia ipsum! Aenean malesuada felis quam, fermentum fermentum elit viverra ut! Ut a orci sapien. Nulla dictum leo et tortor sollicitudin tempus. Aliquam lacinia, quam in condimentum aliquet, nisi augue feugiat ligula; eget cursus felis est sit amet augue.
  65. 65. 9. Lisibilité  Penser le code comme du texte  Faire des paragraphes, aérer le code  Faire le moins de colonnes possibles  Une seule par ligne→
  66. 66. 9. Lisibilité $serviceManager = $this->serviceManager; $events = $this->events; $listeners = array_unique(array_merge($this->defaultListeners, $listeners)); foreach ($listeners as $listener) { $events->attach($serviceManager->get($listener)); } // Setup MVC Event $this->event = $event = new MvcEvent(); $event->setTarget($this); $event->setApplication($this) ->setRequest($this->request) ->setResponse($this->response) ->setRouter($serviceManager->get('Router')); // Trigger bootstrap events $events->trigger(MvcEvent::EVENT_BOOTSTRAP, $event); return $this; Source : Zend Framework 2.3.1
  67. 67. 9. Lisibilité public function someVeryLongMethodName(ObjectType $firstArgument, ObjectType $secondArgument, ObjectType $thirdArgument) { // ... } public function someVeryLongMethodName( ObjectType $firstArgument, ObjectType $secondArgument, ObjectType $thirdArgument) { // ... } $longVariableName = array($someKey => $someValue, $anotherKey => $anotherValue); $longVariableName = array( $someKey => $someValue, $anotherKey => $anotherValue);
  68. 68. 9. Lisibilité $this->context->customer->firstname.' '.$this->context->customer->lastname $this->getCustomer() ->getFullname(); Source : Prestashop 1.6.0.8
  69. 69. 10. Documenter son code  Utiliser le (presque) standard PHPDoc  Ajouter un DocBlock au début de chaque méthode  1 à 2 lignes de commentaires au début de chaque paragraphe  Auto-complétion / Documentation dans l'IDE
  70. 70. 10. Documenter son code // Si le formulaire est valide if ($form->isValid() === true) { } // Retourne l'utilisateur return $user; //When I wrote this, only God and I understood what I was doing //Now, God only knows
  71. 71. 10. Documenter son code /** * Bootstrap the application * * Defines and binds the MvcEvent, and passes it the request, response, and * router. Attaches the ViewManager as a listener. Triggers the bootstrap * event. * * @param array $listeners List of listeners to attach. * @return Application */ public function bootstrap(array $listeners = array()) Source : Zend Framework 2.3.1
  72. 72. 10. Documenter son code // Send a challenge in each acceptable authentication scheme $headers = $this->response->getHeaders(); if (in_array('basic', $this->acceptSchemes)) { $headers->addHeaderLine($headerName, $this->_basicHeader()); } if (in_array('digest', $this->acceptSchemes)) { $headers->addHeaderLine($headerName, $this->_digestHeader()); } return new AuthenticationResult( AuthenticationResult::FAILURE_CREDENTIAL_INVALID, array(), array('Invalid or absent credentials; challenging client') ); Source : Zend Framework 2.3.1
  73. 73. Récapitulatif 1. Utiliser un outil de gestion de versions 2. Utiliser un IDE 3. Utiliser une convention de codage 4. Partager un environnement de développement commun 5. Utiliser un framework / du code produit par d'autres équipes 6. Factoriser son code : 20 lignes de code maximum par méthode 7. 1 niveau d'indentation maximum par méthode 8. Pas d'abréviation dans les noms de variables et méthodes 9. Améliorer la lisibilité de son code en formant des paragraphes 10.Documenter son code
  74. 74. Prochaines étapes  Écrire du code propice à l'évolution  Tester son code  Intégration continue  Passer Paladin niveau 7
  75. 75. Entraînez-vous :)
  76. 76. Questions ?
  77. 77. Merci de votre attention :) @wixiweb / @maximemdotnet

×