Php 100k

8 723 vues

Publié le

Vous ne manquez pas de tutoriels pour écrire un "Hello, world" avec n'importe quel framework. Mais que se passe-t-il quand, sur cette base, vous faites travailler une équipe de 4 développeurs pendant 6 mois ? Petit retour d'expérience sur l'architecture logicielle d'une application Symfony2 de taille moyenne, avec des visualisations inédites et des indices pour répondre à cette éternelle question : mais où je le mets ce code ?
Présentation effectuée au PHP Tour Lyon 2014

Publié dans : Technologie
0 commentaire
14 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

Aucun téléchargement
Vues
Nombre de vues
8 723
Sur SlideShare
0
Issues des intégrations
0
Intégrations
4 574
Actions
Partages
0
Téléchargements
53
Commentaires
0
J’aime
14
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

Php 100k

  1. 1. Caressembleàquoi FrançoisZaninotto-@francoisz UneapplicationPHP,quandonarriveà 100000lignesdecode marmelab-PHPTourLyon2014
  2. 2. Caressembleàça • Ca ressemble à quoi une appli à cent mille lignes de code ? A ça. • Une appli à cent mille lignes de code, c’est opaque, poisseux, très dense, et angoissant. • Une appli à cent mille lignes de code, c‘est surtout trop gros pour qu’on la voit en entier d’un coup d’oeil. • C’est le problème de l’éléphant dans la pièce : si vous mettez un éléphant dans une pièce, vous n’aurez jamais assez de recul pour le voir en entier. • Il faut donc choisir un angle de vue et accepter une vision partielle - accepter de cacher des choses. Pour avoir une vision plus globale, il faudra multiplier les points de vue. • A propos, le nombre de lignes de code, c’est une mesure assez mauvaise de la taille d’une application. Le nombre de ligne de code peut varier énormément selon les styles de code. Mais ça peut quand même nous donner un bon ordre de grandeur.
  3. 3. ✦ 10loc ✦ 100loc ✦ 1Kloc ✦ 10Kloc ✦ 100Kloc ✦ 1Mloc ✦ 10Mloc
  4. 4. ✦ 10loc ✦ 100loc ✦ 1Kloc ✦ 10Kloc ✦ 100Kloc ✦ 1Mloc ✦ 10Mloc « Hello, world » en PHP (1 loc) Affichage de la suite de fibonacci (10 loc) Suite de Fibonacci avec tests (50 loc) Production moyenne /dev /jour (100 loc) Gremlins.js (2000 loc) Monolog (7 800 loc) Uptime (9 700 loc) Twig (12 600 loc)
  5. 5. ✦ 10loc ✦ 100loc ✦ 1Kloc ✦ 10Kloc ✦ 100Kloc ✦ 1Mloc ✦ 10Mloc Doctrine (65 kloc) SwiftMailer (73 kloc) Photoshop 1.0 (128 kloc) Symfony2 (180 kloc) Quake 3 (310 kloc) Loc poussées sur GitHub par jour (1 Mloc) CryEngine2 (1 Mloc)
  6. 6. ✦ 10loc ✦ 100loc ✦ 1Kloc ✦ 10Kloc ✦ 100Kloc ✦ 1Mloc ✦ 10Mloc Linux Kernel 2.6.0 (5,9 Mloc) Firefox (9 Mloc) Android (12 Mloc) MySQL (12 Mloc) Linux 3.1 (15,8 Mloc) Facebook Frontend (62 Mloc) OS X Tiger (84 Mloc) Génôme d’une souris (120 M bases)
  7. 7. ✦ 10loc ✦ 100loc ✦ 1Kloc ✦ 10Kloc ✦ 100Kloc ✦ 1Mloc ✦ 10Mloc Etna
  8. 8. Pourquoic’estimportant • Etna, le CMS de marmelab, c’est à peu près 2 années homme de développement, ou 6 mois à 4 développeurs. C’est à peu près 120 000 lignes de code. C’est l’exemple que je vais utiliser pendant cette présentation pour illustrer mes propos. • Que ce soit pour corriger un bug, prendre en charge la TMA, ou refondre le projet dans son ensemble, vous devrez probablement, dans votre carrière, rentrer dans une application à 100 000 loc complètement inconnue. • Et ce jour-là, vous ne serez plus un simple développeur, vous serez un explorateur de code. Ou un aventurier du code, à la recherche d’un trésor perdu. • Vous serez…
  9. 9. 1-Sesituer 2-Découvrir 3-Faireévoluer 4-Entretenir
  10. 10. 1-Sesituer
  11. 11. Sesituer:leproblème • Imaginez que vous êtes lâché dans une ville inconnue. Les noms de rues sont écrits dans un alphabet énigmatique. Les habitants parlent une langue incompréhensible. • Pour tout dire, vous êtes tellementperduquevousavezpeur. • Arriver sur un projet en cours, lancer un projet de refonte, c’est la même chose que se retrouver dans une ville inconnue. Et avant toute chose, il faut sesituer. • Pour se situer, oubliez les détails, il va falloir une vue globale. Une vue de très très haut. Même sur une base à 100 000 loc, il faut pouvoir vous situer en 10 minutes. • Un bon truc, pour ça, c’est de réduire le projet à une de ses dimensions, une dimension qui vous parle. Ca peut être: • Poids en Kilobits • Nombre de lignes de code • Nombre de commentaires
  12. 12. 148K%./app/config% %68K%./app/ DoctrineMigrations% %92K%./app/Resources% %56K%./app/tests% 424K%./app% %%0B%./bin/jar% %44K%./bin/migration% 8,0K%./bin/tools% %32M%./bin% %12K%./config/deploy% %32K%./config% %40K%./docs% 7,9M%./src/Etna% 7,9M%./src% 472K%./web/bootstrap% %56K%./web/components% 156K%./web/css% %44K%./web/daterangeI picker% 740K%./web/front% 352K%./web/img% 1,6M%./web/js% %20K%./web/pnotify% 3,4M%./web% %48M%. #%quelle%est%la%taille%du%projet%?% >%du%Ih%II%'.git'%Id%2%.
  13. 13. du • Si on prend la taille en Kb comme dimension repère, du, l’utilitaire Linux de calcul des tailles des fichiers et répertoires sur le disque, est un bon outil. • Sur Etna, on voit que la plupart du code source est situé sous bin, sous src, et sous web/js/ • Un rapide examen des répertoires bin et src montre sur des fichiers de dépendances sont comités dans le repository (Selenium, jQuery). du est évidemment plus pertinent si on ne commite pas les dépendances. Mais vous saurez à l’avenir ignorer ces fichiers dans votre exploration.
  14. 14. #%quelle%est%la%taille%du%projet%?% >%cloc%.% ! %%%%1630%text%files.% %%%%1625%unique%files.% %%%%2076%files%ignored.% ! http://cloc.sourceforge.net%v%1.58%%T=8.0%s%(167.1%files/s,%21224.6%lines/s)% IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII% Language%%%%%%%%%%%%%%%%%%%%%%files%%%%%%%%%%blank%%%%%%%%comment%%%%%%%%%%%code% IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII% PHP%%%%%%%%%%%%%%%%%%%%%%%%%%%%%900%%%%%%%%%%16719%%%%%%%%%%20410%%%%%%%%%%60200% Javascript%%%%%%%%%%%%%%%%%%%%%%187%%%%%%%%%%%7041%%%%%%%%%%%4764%%%%%%%%%%34299% CSS%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%48%%%%%%%%%%%1599%%%%%%%%%%%%359%%%%%%%%%%12350% YAML%%%%%%%%%%%%%%%%%%%%%%%%%%%%%65%%%%%%%%%%%%363%%%%%%%%%%%%%36%%%%%%%%%%%3561% XML%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%22%%%%%%%%%%%%421%%%%%%%%%%%%%65%%%%%%%%%%%2380% SQL%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%21%%%%%%%%%%%%307%%%%%%%%%%%%363%%%%%%%%%%%2077% HTML%%%%%%%%%%%%%%%%%%%%%%%%%%%%%57%%%%%%%%%%%%%59%%%%%%%%%%%%%%6%%%%%%%%%%%1033% Bourne%Shell%%%%%%%%%%%%%%%%%%%%%31%%%%%%%%%%%%204%%%%%%%%%%%%%57%%%%%%%%%%%%605% XSLT%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%1%%%%%%%%%%%%%27%%%%%%%%%%%%%55%%%%%%%%%%%%266% Ruby%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%4%%%%%%%%%%%%%30%%%%%%%%%%%%%%2%%%%%%%%%%%%128% Bourne%Again%Shell%%%%%%%%%%%%%%%%1%%%%%%%%%%%%%%4%%%%%%%%%%%%%%0%%%%%%%%%%%%%%7% IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII% SUM:%%%%%%%%%%%%%%%%%%%%%%%%%%%1337%%%%%%%%%%26774%%%%%%%%%%26117%%%%%%%%%116906% IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
  15. 15. cloc • Si on prend le nombre de lignes de code comme dimension repère, alors le bon outil c’est cloc. • cloc est un utilitaire open-source qui compte les lignes de code. Il sait ignorer les blancs, les fichiers dupliqués, le répertoire .git, il sait distinguer les commentaires, et divise son total par langage. • Sur Etna, on voit qu’un bon tiers des lignes de code sont du JavaScript, et que le ratio code/commentaire est de 3/1 en PHP. C’est plutôt encourageant.
  16. 16. Quellessontlesmassesdecode? CodeFlower
  17. 17. Oùestlecode,avecplusdedétail? • Le poids des répertoires à la racine ne suffit pas ; tout est souvent dans lib/ ou dans src/. Il faut donc approfondir. • Mais si on descend dans tous les sous-répertoires avec un du ou un cloc , les résultats font des pages et des pages de texte, c’est inexploitable. Je vous rappelle qu’on n’a que 10 minutes pour se situer. • Il faut donc passer à une représentation plus synthétique, une représentation graphique • Marmelab a travaillé à une visualisation basée sur le résultat d’un cloc sur tous les fichiers d’un projet. Cette visualisation s’appelle CodeFlower. • Sur Etna, ça permet de détecter très vite des tendances • Les gros fichiers qu’il faudra éclater • Les branches de test qui font écho aux branches de code • Les répertoires quasi-vides, qui sont souvent le signe de code over-engineeré, à la Java • Hints: Prendre un repo frais pour éviter dépendances PHP et JS, fichiers générés (cache)
  18. 18. %%1533% Jonathan%Petitcolas% %%1456% Emmanuel%Quentin% %%1238% ThieryMichel% %%1006% Noëlie%Amiot% %%%473% Olivia%Ly% %%%315% Daphné%Popin% %%%197% Simon%Rolland% %%%187% Eric%Grange% %%%184% DjebbZ% %%%177% Francois%Zaninotto #%qui%travaille%sur%ce%projet%?% >%git%shortlog%IInumbered%IIsummary%HEAD%|%head%I10
  19. 19. git • Pour continuer dans la prise de repères rapide, l’historique de Git dispose de plein d’infos très utiles, comme ici la liste des contributeurs. • Qui a travaillé sur le code (et donc à qui demander son chemin ?) git shortlog. • Quel est l’état du projet ? Git grep. Comme ça utilise la base de données de git, c’est un grep super rapide qui ignore les fichiers non commités. Mieux que grep ou ack!
  20. 20. #%quel%est%l’état%du%projet%?% >%git%grep%Ii%todo%|%wc%Il% %%%%%%90% >%git%grep%Ii%fixme%|%wc%Il% %%%%%%16% >%git%grep%Ii%todo% ! app/Resources/views/header.html.twig:%%%%%%%%%%%%{#%@TODO:%display%'.headerIapps'%links%here%in%the%future%#}% app/Resources/views/layout.html.twig:%%%%{#%@TODO:%add%print.css%and%manage%styles_ie.css%#}% app/Resources/views/layout.html.twig:%%%%%%%%{#%@TODO:%include%Hot%News%tab%here%#}% app/config/security.yml:%%%%%%%%#%@TODO%:%find%a%way%to%retrieve%current%locale% close:app/Resources/views/header.html.twig:%%%%%%%%%%%%{#%@TODO:%display%'.headerIapps'%links%here%in%the%futur% close:src/Etna/VideoBundle/Resources/views/Video/index.html.twig:{#%@TODO:%apply%.isIactive%on%active%menu%item% close:web/front/css/layout/_layout.styl:%%%%//%@TODO:%Refactoring%[class="^Ititle"]%pour%tous%les%titres% close:web/js/ckeditor/plugins/DiagPlWs/core/xslt/correctionUI.xslt:%%%%%%%%%%%%%<!II%TODO%gestion%des%'%II>% src/Etna/ArticleBundle/Controller/ContentController.php:%%%%%%%%//%@TODO%add%photo%retrieval%to%get%the%credits% src/Etna/ArticleBundle/Document/Article.php:%%%%%*%@TODO:%implement%it%when%refactoring%article%import/export% src/Etna/ArticleBundle/Document/Live.php:%%%%%*%@TODO:%implement%it%when%refactoring%article%import/export% src/Etna/ArticleBundle/Repository/DocumentRepository.php:%%%%%%%%//%@TODO%:%find%a%better%way%to%avoid%paginati% src/Etna/ArticleBundle/Resources/public/css/tags.css:/**%@TODO%Olivia:%review%this%CSS%to%deal%scrollbar%correc% src/Etna/ArticleBundle/Resources/views/Content/article_link.html.twig:%%%%{#%@TODO:%apply%correct%style%accordi% src/Etna/ArticleBundle/Resources/views/Content/content.html.twig:%%%%{#%@TODO:%make%it%dynamic,%according%to%w% :
  21. 21. Surquelleslibrairiess’appuieleprojet? DependencyWheel
  22. 22. Etlesdépendances? • C’est bien joli de visualiser le code comité d’une application PHP, mais à l’époque de composer, le gros du code servant à l’exécution, cen’estpasvousquil’écrivez. Le gros du code est dans les dépendances. • Sur Etna, lesdépendancesreprésentent90%ducode nécessaire pour faire tourner l’application. • Et quand on parle de dépendances, il faut compter les dépendances directes (dans le composer.json) et indirectes (dépendances des dépendances, qu’on trouve dans le composer.lock). • Pour visualiser les dépendances directes et indirectes, on a développé une autre visualisation qui s’appelle DependencyWheel • Sur Etna, on s’aperçoit que le composer.lock liste 47 librairies, mais qu’au final, en comptant les dépendances externes, il en faut 105 pour faire tourner l’application. • On voit même des dépendances inattendues. C’est un projet sous Symfony, mais je vois des composants Zend dans les dépendances. Mais pourquoi télécharger des librairies qui font le travail en double des composants Symfony?
  23. 23. N’oubliezpas JSetCSS
  24. 24. N’oubliezpasleJSetleCSS • De plus en plus de code est déporté côté client. Visualiser le code PHP, ça ne suffit pas ! • C’est en JS et en CSS qu’on trouve les plus gros fichiers. • jQuery et Bootstrap sont souvent commités malgré bower, mais ce n’est pas le plus significatif. En fait, ces librairies ne font pas partie de votre code. • On n’a pas encore une approche aussi modulaire en CSS et JS qu’en PHP et HTML. • Mais ce n’est pas le sujet de cette conf
  25. 25. ✓ Sesituer
  26. 26. Conclusion • En dix minutes, avec quelques commandes bash, deux graphes, et un peu d’astuce, le jeune développeur explorateur n’est déjà plus perdu. Il sait où il se trouve et à qui il a affaire. • Il peut désormais partir serein à la découverte des secrets du code qui recèlent peut-être un trésor perdu. • Mais il n’est pas au bout de ses surprises !
  27. 27. 2-Découvrir
  28. 28. 2-Découvrir • Passée l’angoisse de l’inconnu, une fois que qu’il a réussi à corriger le premier bug, l’explorateur de code cherche à mieuxcomprendre cette application à 100 000 lignes de code. • Il commence à s’éloignerunpeu du code qu’il connait, il s’aventure dans des classes qu’il n’a jamais ouvertes. • Quel est le rôle de cette classe ? Avec qui communique-t-elle ? Comment s’inscrit-elle dans le système ? Les questions sont déjà d’un ordre plus logique que physique. • Declasseenclasse, l’explorateur de code va découvrir l’ensemble de l’application. Il va se l’approprier. Il va l’apprivoiser. • Il lui faut juste un guide pour ne pas se perdre. Un guide, ou une carte, et un annuaire.
  29. 29. #%que%fait%cette%classe?% >%phpunit%Ic%app%—filter%ContentLocker%—testdox% ! EtnaArticleBundleServiceContentLocker% %[x]%Lock%content%should%persist%a%lock% %[x]%Lock%content%should%be%set%with%correct%data% %%%%%when%persisted% %[x]%Lock%content%should%not%be%persisted%if% %%%%%already%exists% %[x]%Unlock%content%should%remove%content%lock% %[x]%Is%locked%content%should%return%true%if%% %%%%%content%is%locked% %[x]%Is%locked%content%should%return%false%if%% %%%%%content%is%not%locked
  30. 30. Lestestsunitaires • De manière peut-être inattendue, le premier guide à interroger, ce sont les tests unitaires. • Les tests décrivent cequ’uneclassedoitfaire. Ils décrivent aussi ce qu’une classe n’arrive plus à faire quandonlacasse. Ils sont donc forcément présent dans une application à 100 000 lignes de code (sinon elle n’est pasmaintenable). • Le compte-rendu des tests, il est facile à lire - pour peu qu’on utilise le bon formatage. • phpUnit propose le format testdox pour générer une documentation agile à partir des tests unitaires. Vous voyez ici ce qu’ils peuvent nous apprendre sur une classe précise (ciblée par l’option —filter)
  31. 31. <?php% class%ContentLockerTest%extends%PHPUnit_Framework_TestCase% {% %%%%public%function%testLockContentShouldPersistALock()% %%%%{% %%%%%%%%//%...% %%%%}% ! %%%%public%function%testLockContentShouldBeSetWithCorrectDataWhenPersisted()% %%%%{% %%%%%%%%//%...% %%%%}% ! %%%%public%function%testLockContentShouldNotBePersistedIfAlreadyExists()% %%%%{% %%%%%%%%//%...% %%%%}% }
  32. 32. Lestestsunitaires • Pour avoir ce joli rendu en « testdox », il faut nommer les méthodes de test avec une phrase explicite, sujet-verbe-complément, et joindre tous les mots écrits en CamelCase. • Gros avantage des tests automatisés: ils sont nécessairement à jour avec le code, sinon ils ne passent pas. • Les tests; c’est bien, mais dites-moi: ce n’est pas le rôle de la documentation de nous aider à découvrir l’inconnu sans trop se mouiller ?
  33. 33. Etladoc?
  34. 34. LaDoc • La documentation, ça prend du temps, c’est obsolète dès qu’on modifie le code, et puis c’est dur à écrire. Par conséquent, soyons honnêtes, autant ne pas en écrire, de documentation. • L’un des préceptes de l’agilité nous dit D’ailleurs : ladocumentation,c’estlecode (« Code as craft ») • Par exemple, si vous utilisez l’injection de dépendance, le constructeur d’une classe vous renseigne tout se suite sur les relation qu’elle a avec d’autres classes. • Pour que le code serve de documentation, il faut qu’il soit lisible. Le code est écrit pour être lupar2choses : le serveur qui l’exécute, et le développeur qui le débuggue. • Travaillez bien votre code pour le rendre lisible et éviter d’avoir à écrire de la documentation. A mon sens, c’est bien plus utile à long terme.
  35. 35. Sanscommentaire
  36. 36. Lescommentaires • Juste un petit aparté sur un malentendu. Quand ils entendent « code as craft », certains développeurs se disent qu’il suffit de barder le code de commentaires. • Ca, souvent, ça ne sert à rien. Je pense par exemple à la phpDocparaphrase, du genre « getPrice : returns the price ». • Un code avec plein de commentaires comme ça, c’est un déguisement. Mais ça ne fait pas illusion. Il suffit de le regarder de plus près pour s’apercevoir qu’il n’est pas plus lisible pour autant. • Les bons usages des commentaires, pour moi, c’est quandlecodeneditpastout, ou que la lecture du code pose des questions. Ca doit vraiment être un complément. • A mon, sens, un code bien écrit a souvent assez peu de commentaires - disons une lignedecommentairepour20lignesdecode. C’est qu’un code bien écrit est son propre commentaire. Un code bien écrit est sa propre documentation.
  37. 37. %%%%/**% %%%%%*%Returns%the%price% %%%%%*% %%%%%*%@param%TaxRule%$tax%The%tax%rule% %%%%%*/% %%%%public%function%getPrice(TaxRule%$tax)% %%%%{% %%%%%%%%//%...% %%%%}%
  38. 38. EtlaDocAPI?
  39. 39. Fairelepoint,dresserl’inventaire • Après avoir vu des méthodes pour comprendre ce que fait une classe, il est temps de chercher des moyens de comprendre des ensembles plus grands. Pour cela, il faut dresser l’inventaire du projet. • On a déjà fit un inventaire des fichiers avec CodeFlower. Mais c’est un inventairephysique. Ce qu’il faut pour découvrir l’application, c’est un inventairelogique, un inventaire des classes et des méthodes. • Cette liste, on appelle ça la DocAPI. Pour le générer, je vous conseille Sami, un utilitaire de Fabien Potencier qui crée un dictionnaire HTML à partir d’une base de code PHP.
  40. 40. Quefaitcetteclasse? Sami
  41. 41. Readthesource,luke • Mais en fait, je trouve que ça ne sert pas à grand chose. La doc API s’adresse à un lecteur humain, mais je vous ai déjà proposé plus haut d’écrire votre code justementpourqu’ilsoitlisibleparunhumain. • Si une doc API sert à trouver le détail d’une classe en tapant son nom, un IDE sait déjà faire ça. Avec Command+T, sur SublimeText, je trouve la classe que je veux en tapant des bouts de son nom. • Votre IDE sait également vous éviter carrément la recherche en proposant de l’autocompletion, et des typehints sur les paramètres d’appels à une méthode. • Pour faire le point, pas besoin donc d’une doc API à mon avis. Utilisez les indexes déjà à votre disposition, ceux de votre IDE.
  42. 42. Dequoidépenduncomposant? ArchitectureTree
  43. 43. Représenterl’architecture • Au fur et à mesure de la découverte, nous sommes passés du plan physique (fichiers, lignes de code), au plan logique (classes, méthodes, interfaces). • Mais pour comprendre en profondeur l’architecture d’une application, il faut passer au plan conceptuel (domaine, entités, relations, aggrégats). • L’idéal dans ce cas, c’est de disposer d’un schémad’architecture. Mais s’il existe, c’est souvent comme pour la documentation: il est déjà obsolète. Sans compter qu’il faut Visio ou OmniGraffle pour pouvoir l’éditer, ce que seuls un ou deux postes dans votre entreprise permettent. • La solution : un schéma d’architecture en HTML5, basé sur un fichier texte, éditable par tous les développeurs. • L’objectif, c’est de tout faire tenir en un seul graphe. Forcément, certaines informations (briques techniques, hébergement) ne se révèleront qu’au rollover. • On l’a appelée: ArchitectureTree. Cela permet de prendre un maximum de hauteur et d’identifier efficacement à la fois les composants de l’application, et leurs relations. • Ce n’est pas encore open-source !
  44. 44. {%"name":%"SaaS",% %%"children":%[% %%%%%%{%"name":%"Xiti"%},% %%%%%%{%"name":%"Imaging",% %%%%%%%%"children":[% %%%%%%%%%%{%"name":%"Horby",% %%%%%%%%%%%%"technos":%["Python",%"ElasticSearch"],% %%%%%%%%%%%%"dependsOn":%["Krakatoa"]%},% %%%%%%%%%%{%"name":%"Hoor",% %%%%%%%%%%%%"technos":%["Python"],% %%%%%%%%%%%%%"dependsOn":%["Photos",%"Horby",%"Photos"]%},% %%%%%%%%%%{%"name":%"Dale",% %%%%%%%%%%%%"technos":%["Python"],% %%%%%%%%%%%%"dependsOn":%["Horby"]%},% %%%%%%%%%%{%"name":%"Krakatoa",% %%%%%%%%%%%%"technos":%["Silex"],% %%%%%%%%%%%%"dependsOn":%["Photos"],% %%%%%%%%%%%%"satisfaction":%0.5%},% %%%%%%%%%%{%"name":%"Stockholm",% %%%%%%%%%%%%"technos":%["Python"],% %%%%%%%%%%%%"dependsOn":%["Photos"],% %%%%%%%%%%%%"satisfaction":%0.2%}% %%%%%%%%%%]},% %%%%%%{%"name":%"Katla",% %%%%%%%%"comments":%"Node.js%application%to%gather%social%counts%on%Etna%contents",% %%%%%%%%"technos":%["Node.js"]%},% %%%%%%{%"name":%"Netino",% %%%%%%%%"comments":%"Comment%moderation%service",% %%%%%%%%"technos":%["SOAP"]%}% %%]% }
  45. 45. ArchitectureTree:lasource • Voici le format JSON utilisé pour alimenter le graphe. • Il décrit, pour chaque noeud du graphe, un nom, des attributs, des dépendances, et des enfants. • C’est facile à éditer par n’importe qui, et le graphe HTML5 s’en nourrit en direct. Il suffit de faire F5 après avoir mis à jour le fichier. • Le graphe peut même être hébergé sur une branche gh-pages sur GitHub pour montrer en permanence l’état de l’architecture.
  46. 46. ✓Découvrir
  47. 47. Conclusion • Avouez que cette application de 100 000 lignes de code, elle nevousfaitdéjàplus peur. • Avec une bonne carte, un IDE efficace, des tests unitaires, et potentiellement un peu de documentation, l’application commence même, en général, à donnerenvie au développeur. • Incidemment, ces outils permettent de découvrirdeschosesqu’onnecherchaitpas. Comme quand on regarde une carte en se disant : « Chéri, tu savais qu’il y a une usine Seveso à 500 mètres de la maison ? ». Les anglo-saxons parlent de serendipity, ce que Google traduit par « don de faire des découverte accidentelles ». • Bon, mais maintenant il va falloir rentrer dans la carte et s’immerger complètement. Maintenant, c’est l’heure de l’aventure.
  48. 48. 3-Faireévoluer
  49. 49. 3-Faireévoluer • L’aventure, c’est defaireévoluer cette application de 100 000 lignes de code. • C’est ce qu’on vous demande touslesjours. « Tu pourrais ajouter un module de recommandation en direct, tu sais, basé sur l’historique de navigation, et sur les clients qui ont des goûts similaires ? » • Tous les jours, sur une application à 100 000 lignes de code, on demande aux développeurs d’ajouter davantagedelignesdecode. Là où c’est une vraie aventure, c’est qu’on ne demande jamais d’ajouter du code qui existe déjà. Il faut le découvrir, l’inventer, ce code. • Commentimplémenterunenouvellefonctionnalité ? Dans quel répertoire mettre une classe ? Comment nommer les fichiers, les méthodes, les services ? • Ce n’est pas le tout de connaître l’application, il faut savoir la modifier à la demande, et trouverlebonchemin d’implémentation. • En évitant au passage, les bugs, les trous de sécurité, les problèmes de performance, et les coupeurs de tête. • Vous vous sentez toujours l’âme d’un aventurier ? Allons-y.
  50. 50. DesignPatterns
  51. 51. DesignPatterns • Pour s’engager en territoire hostile, il faut un peu de préparation. Recruter un bon guide, calculer son itinéraire, s’informer des coutumes locales. • Pour implémenter une fonctionnalité, c’est pareil. Avant même de démarrer, vous savez que vous aurez à router vers une action, injecter un service, persister une entité, afficher un template. • Ces stratégies d’implémentation, ces routes privilégiées, ce sont des design pattern. • Vous en connaissez tous un certain nombre: ActiveRecord, Adapter, Visitor, Template, Front Controller, MVC, Dependency Injection. • Ils ont été conçus par de vieux routards du code et ils nous aident à nous concentrer sur la logique métier sans réinventer la roue. • Le développeur explorateur, avant de partir, potasse sa littérature. Il révise son Martin Fowler et son Eric Evans. Lisez-les vous aussi, sinon votre PHP risque de n’être qu’un gros tas de spaghetti que vous serez le seul à comprendre, et qui ne vous mènera nulle part.
  52. 52. Fullstack Framework
  53. 53. UtiliserunFrameworkfull-stack • D’ailleurs, plutôt que d’essayer d’implémenter le pattern MVC tout seul, il vaut mieux utiliserunframework qui le fait déjà. • Et pas un microframework. On parle d’une application à 100 000 lignes de code ! Un microframework, ça amène péniblement à 10 000 lignes de code maximum. • Et pas un framework propriétaire non plus. On n’est plus en 2004. Si on peut éviter d’avoir à réapprendre une nouvelle manière de gérer les requêtes HTTP, l’accès à la base de données, la validation des formulaires, c’est toujours ça de gagné. • Il faut donc un framework full-stack, open-source, et avec une grosse communauté. • Dans le projet à 100 000 lignes de code dont je vous parle aujourd’hui, on a utilisé Symfony2.
  54. 54. Bonnespratiques
  55. 55. Bonnespratiques • Mais utiliser Symfony2, ça ne suffit pas pour savoir précisément où mettre le code. Pour cela, il faut connaitre les bonnes pratiques. • Fat model, Skinny controllers, Separation of concerns, DRY. Je ne vais pas les expliquer ici, mais c’est quand on les applique sur une grosse base de code qu’elles prennent tout leur sens. • Elles nous permettent de répondre à la question «  mais où mettre ce code ? » Question d’autant plus pertinente si l’application fait déjà 100 000 lignes de code. • Attention, les bonnes pratiques ne sont pas toujours celles qu’on croit. • Je vous donne un exemple. Dans Symfony, la plupart du code source est sous src/, regroupé en « bundles », qui sont des sortes de modules. • Sur Etna, On a fait un bundle par groupe fonctionnel. Vous savez quoi ? C’est une mauvaise idée. • On s’y perdait, du code nécessaire à une fonctionnalité était éclaté dans 2 bundles, les services d’un Bundle devenaient dépendants des services des autres Bundles… • On n’aurait du faire qu’un seul bundle, et mettre la logique métier indépendante du framework dans des répertoires à part. Ca, on s’en est rendus compte trop tard.
  56. 56. >%ls%src/Etna% ! AdminBundle%%%%%%%%%%%OriginBundle% ArticleBundle%%%%%%%%%SurveyBundle% FrameworkBundle%%%%%%%TagBundle% FrontUserBundle%%%%%%%TrackingBundle% HpeBundle%%%%%%%%%%%%%UserBundle% MiscBundle%%%%%%%%%%%%VideoBundle% NotificationBundle
  57. 57. >%ls%src/Etna% ! Article%%%%%%%%%%%%%%%Survey% EtnaBundle%%%%%%%%%%%%Tag% FrontUser%%%%%%%%%%%%%Tracking% HPE%%%%%%%%%%%%%%%%%%%User% Notification%%%%%%%%%%Video% Origin%
  58. 58. Lebonnom
  59. 59. Thereareonlytwohard thingsinComputerScience: cacheinvalidationand namingthings. ! PhilKarlton
  60. 60. Lebonnom • Bien nommer les classes et ses méthodes, c’est 50% du travail. • S’il est choisi trop vite, un nom peut créer de gros malentendus, avec de lourdes conséquences. • Vous connaissez sans doute la citation de Phil Karlton. Trouver le bon nom, en informatique, c’est une des choses les plus dures qu’il soit. • En même temps, Phil Karlton est mort en 1997, il n’a pas pu connaitre Doctrine. Mais je m’égare. • Pour organiser une grosse base de code, nommer correctement ses classes, modules et agrégats, c’est fondamental.
  61. 61. ArticleManager% TagTools% TrackingUtils% NotificationService
  62. 62. Entities% % % % % Services% Article%% % % % % ContentLocker% Notification%% % ArticleCleaner% Lock% % % % % % % SurveyParser% TagRepository%% % UrlGenerator% Link% % % % % % % LiveImporter% ! Framework%classes%I%almost%empty% MediaFormType% LegacyIdListener% CleanContentCommand% ProfileAdminController% BreadcrumbTwigExtension
  63. 63. DéfinirdesStandardsdenommage • Voici des exemples de mauvais noms. Ces noms sont des odeurs de code. Toutes vos classes, en cherchant bien, peuvent être renommées « manager ». C’est un peu comme dans l’organisation des grandes entreprises, tout le monde est responsable de quelque chose. • Le bon nom, il vient du domaine. Le bon nom, c’est celui qui est employé par le client dans son travail de tous les jours. Nommez une chose pour une entité, une action (avec un verbe) pour un service. • Le Domain-Driven-Design, c’est le nom d’un bouquin d’Eric Evans sur les Design Patterns, Le Domain-Driven Design parle de « Langage omniprésent » (ubiquituous language). Ce langage, ces noms, sont une des clés de l‘évolution d’une grosse application. • Et si le Framework que vous utilisez vous impose d’écrire des classes hors du domaine, mettez-y le moins de choses possibles. Ces classes-là doivent s’appuyer sur les classes du domaine.
  64. 64. Respecterles standards
  65. 65. #!/bin/sh% #%in%.git/hooks/preIcommit% ! PROJECTROOT=`echo%$(cd%${0%/*}/../../%&&%pwd%IP)`/% ! RES=`phpIcsIfixer%fix%$PROJECTROOT%IIverbose%IIdryIrun`% if%[%"$RES"%!=%""%];%then% % echo%"Committed%code%is%not%PSRI2%compliant,%cancelling%your%commit."% % echo%$RES% % echo%"If%you%want%to%fix%them%run:"% % echo%"%%%%phpIcsIfixer%fix%${PROJECTROOT}%IIverbose"% % exit%1% fi% % !
  66. 66. Standarddecodage • Un projet de 100 000 lignes de code, c’est au moins 4 développeurs pendant 6 mois. Ca fait donc pasmaldemonde qui passe sur l’appli • Si chacun a sa propre manière de coder, ça devient très vite un beau sacdenoeuds. • A ce niveau, on ne peut pas se passer de standarddecodage • C’est un peu le « code de la route », les panneaux d’interdiction / d’obligation. Une manière astucieuse d’éviter les accidents. • Utilisez des standards existants, là encore pour éviter un délai de mise en route pour les nouveaux arrivants. En PHP, les standards se nomment PSR-0 et PSR-2. • Mais c’est une tâche qu’on sait très bien automatiser. N’embêtez pas vos développeurs avec ça, mais faites un post-commit hook avec un php9cs9fixer qui propose des changements et modifie le dernier commit en cas d’écart.
  67. 67. ✓Faireévoluer
  68. 68. Conclusion • Plus la base de code est grosse, plusilfautdesrègles pour en forcer l’organisation, plus il faut des panneaux pour ne pas s’égarer. • Design patterns, frameworks full-stack, bonnes pratiques, dictionnaire du domaine, standards de codage, tout cela devient obligatoires dès que deux personnes travaillent sur la même base de code. • Du coup, une appli PHP de 100 000 lignes de code ressemble normalement beaucoup à toutesles autresapplisPHPde100000lignesdecode. • Pour un développeur qui a déjà travaillé sur un projet de cette taille, le faire évoluer n’est qu’une formalité. Le plus difficile, c’estlapremièrefois. • Fixer des règles, ce n’est pas une raison pour devenir dogmatique. Ces règles sont faites pour minimiser le coût d’implémentation. Si vos règles augmentent significativement le temps d’implémentation, changez -les.
  69. 69. 4-Entretenir
  70. 70. 4-Entretenir • Une grosse base de code, ça s’entretient, ça se bichonne. • Ca ne suffit pas de lui ajouter des nouvelles fonctionnalités, il faut la refactorer en permanence. • Mais par où commencer ? Qu’est-ce qui est prioritaire ? • Vu le volume, un audit de code manuel n’est pas possible. En plus, il faut être capable d’évaluer la qualité en continu. • Là encore, il va falloir trouver de bons outils.
  71. 71. Ladette technique
  72. 72. Ladettetechnique • On développe tous sous contraintes, on ne peut pas faire un code parfait. D’ailleurs, ce serait en pure perte, puisque les besoins évoluent. Un code parfait est un code de luxe. • Donc, le code s’écarte constamment de la qualité nominale. Cet écart, on l’appelle « dette technique », et on le mesure en temps de développement nécessaire pour la compenser. Par example: « Ma dette technique est de 3 jours sur cette librairie » signifie qu’il faut travailler 3 jours pour atteindre un niveau de qualité nominale. • Cette dette traduit les écarts de performance, de sécurité, de robustesse, de maintenabilité, de lisibilité avec le meilleur niveau communément admis.
  73. 73. Quelssontlespointsfaibles? SensioLabsInsight
  74. 74. SensioLabsInsight • Quelques outils d’analyse automatique permettent d’évaluer la dette technique: PHP CodeSniffer, PHP_MD, PHP_Depend, Le meilleur dans le monde PHP/Symfony, c’est actuellement Insight, de SensioLabs. • Certaines violations proposent même un script de résolution. Y’a pas plus facile pour améliorer la qualité. Si vous êtes sur GitHub, chaque violation permet d’ouvrir un ticket. • Sur Insight, la dette technique s’appelle « coût de remédiation ». Cela donne un très bon aperçu du niveau de qualité d’un projet. • Evidemment, plus il y a du code, plus la dette technique est haute. • On a pu faire des statistiques sur plein de projets Insight. En moyenne, le coût de remédiation d’un projet est de 1 minute pour 1 ligne de code. • Donc un élément encore plus représentatif que le coût de remédiation, c’est le rapport entre le coût de remédiation et le nombre de lignes de code. Insight le calcule, et ça donne le score des projets - c’est tout nouveau !
  75. 75. Paroùcommencer? ViolationSunburst
  76. 76. Visualiserladettetechnique • Sur un gros projet, la dette technique s’élève souvent à plusieursmois. Un outil de contrôle qualité comme Insight révèle facilement plusieurscentaines de violations. • A nouveau, on a besoin d’une visualisation pour synthétiser ces résultats, détecter les points d’attention principaux, les tendances dans le code, mais cette fois du point de vue de la qualité. • Insight relie certaines violations (pas toutes) à un fichier. L’ensemble des violations d’un fichier donné définit ladettetechniquedecefichier. Ca donne une bonne visibilité de là où les efforts d’entretien doivent se concentrer. • On a mis tout ça sur un graphe qu’on a appelé ViolationSunburst. On a choisi d’utiliser lacouleurpourreprésenterlasévéritédesviolations comprises dans un répertoire. Plus c’est rouge, plus c’est critique.
  77. 77. Nepasoublier
  78. 78. Ladimensiontemporelle • Les problèmes de qualité, on a tendance à les oublier facilement. Comme c’est souvent secondaire, on les relègue dans un coin de notre tête pour plus tard, mais il y a toujours plus urgent. • Le résultat, c’est que notre code recèle des bombes à retardement. • Un bon moyen de repérer ces bombes, c’est de repérer les fichiers qui n’ont pas été ouverts depuis longtemps. Ce sont ceux susceptibles de cacher des risques graves, parce qu’on a déjà bâti des choses dessus. • Un autre moyen de repérer les bombes, c’est de voir combien de fois un fichier a été modifié. Plus il y a de modifications, plus le fichier concerne une classe complexe qui a évolué, et plus il y a de risques. • Toutes ces informations (date de dernière modification, nombre de modifications), votre repo Git les a. Il suffit de les mettre en forme pour les exploiter. • C’est ce qu’on a fait avec une dernière visualisation nommée ArcheoloGit.
  79. 79. Qu’est-cequipeutcasser? ArcheoloGit
  80. 80. ✓Entretenir
  81. 81. Conclusion • Entretenir une appli de 100 K loc, c’est du travail • La dette technique s’accumule à chaque développement, sachez l’évaluer et lui donner une consistance visuelle. • Insight, ViolationSunburst et ArcheoloGit sont de bons outils pour ça. • ils peuvent vous aider à convaincre le product owner d’investir de temps à autre pour éponger cette dette. • Faute de quoi, l’application va devenir inmaintenable, les temps de debug vont s’allonger, le temps d’implémentation d’une nouvelle fonctionnalité va exploser. • En pratique, pour une appli de cette taille, il faut consacrer au moins 1 ETP à l’entretien de l’application pour éviter une dérive néfaste du niveau de qualité
  82. 82. Conclusion
  83. 83. 1MillionLOC
  84. 84. Conclusionfinale • A quoi ça ressemble une appli de 100 000 ligne de code ? Cadépend de quel côté on regarde. • J’espère vous avoir donné des outilsetdesvisualisations pertinentes pour mieux vous situer, découvrir, faire évoluer et entretenir une base de code de cette taille. • J’espère surtout vous avoir convaincu de changerpointdevue de temps à autre, de prendredelahauteur pour mieux distinguer les lignes de force. • Entretenir une telle application, c’est un travaild’équipe. Partagez vos visualisations avec toute l’équipe de développement pour qu’ils les fassent vivre. Cultivez la propriétécollectiveducode pour éviter les bombes à retardement. • On arrive assez vite à 100 000 lignes de code sur un projet de 6 mois - 1 an. Vous aurez à utiliser ces outils. • Le problème, c’est que tous les outils que je vous ai montrés ne fonctionnent plus quand on passe au degré suivant, quand on passe à 1 Millions de loc • Ce n’est pas tant la faute des outils, c’est juste que ça devient très difficile de se situer, de découvrir, de faire évoluer et d’entretenir une application d’1 million de lignes de code. • D’ailleurs, une application peut très bien mourir de trop de code. Mais alors, par quoi remplacer une application de plus de 100 000 lignes de code quand elle grossit trop ?
  85. 85. Microservices
  86. 86. Microservices • Prenez l’exemple de Linux. 15 millions de lignes de code qui restent maintenables parce que les développeurs produisent des composants indépendants, simples et interopérables. • The Unix Philosophy (1994) Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface. • Dans le web, on peut interfacer les programmes un peu plus finement grâces aux services HTTP, ou aux files AMQP. • Alors, évitez les très grosses applications, et visez toujours une architecture orientée services (SOA, ou microservices depuis 2014) • A qui ça ressemble une application à 1 million de lignes de code ? • Si c’est une application qui a survécu, c’est forcément plusieurs applications de 100 000 lignes de code, découplées, plus faciles à comprendre et à maintenir.
  87. 87. Merci Cloc http://cloc.sourceforge.net/ CodeFlower https://github.com/fzaninotto/CodeFlower DependencyWheel https://github.com/fzaninotto/DependencyWheel Sami https://github.com/fabpot/sami ArchitectureTree pas encore public Domain-Driven Design http://amzn.com/0321125215 PSR-2 https://github.com/php-fig/fig-standards Insight https://insight.sensiolabs.com/ ViolationSunburst pas encore public ArcheoloGit https://github.com/marmelab/ArcheoloGit Visualisations http://d3js.org/ Illustrations Steven et Georges FrançoisZaninotto-@francoisz

×