Gestion de la dette technique : partie 3 – Les test unitaires

Nous voila dans la suite de l’article de la gestion de la dette technique. Aujourd’hui nous allons parler du point sur les tests unitaires.

Les tests unitaires, vous en avez probablement entendu parler notamment de phpUnit. L’intérêt des tests unitaires est multiple, mon intention ici n’est clairement pas de vous apprendre à faire des tests unitaires mais de rappeler leur intérêt et surtout comment les mettre en place intelligemment.

Rappel, un test unitaire sert à tester une fonction précise unique avec un périmètre défini. Prenons par exemple une fonction que nous nommerons « somme » qui prendra en paramètre deux nombres et qui en retourne la somme. Le périmètre est restreint simple à tester. La fonction parait même simpliste et on pourrait se demander pourquoi la tester. Plusieurs raisons :

  • Ça ne prend pas énormément de temps
  • Vous aurez l’esprit serein quand vous aurez besoin de modifier cette fonction
  • Si ce test ne passe pas et que tout s’écroule vous trouverez rapidement le coupable

Les tests unitaires ne sont pas la pour vous ennuyer ou vous ralentir, mais pour vous apporter une sérénité et un confort de travail. C’est un des points les plus importants des tests unitaires. Vous obtiendrez un retour sur votre travail quasi instantanément. C’est ce retour qui fait que vous avez l’esprit serein.

Prenons un exemple simple, sans test unitaire, vous faites vos modifications, vous vous perdez dedans parce que vous êtes trop confiant, et quand vient l’exécution du code, c’est l’erreur fatale. S’en suit alors une série de ctrl+z ou des var_dump et die en tout genre.

Avec des tests unitaires c’est simple, vous faites vos modifications, vous vous perdez dedans parce que vous êtes trop confiant, et quand vient le passage des tests unitaires, …, vous savez exactement ce qui ne marche pas.

A l’instar d’un correcteur orthographique qui vous dit quand vous tapez si vous avez fait une faute et où vous avez la même chose avec les tests unitaires. Vous vous passeriez sérieusement du correcteur orthographique sur votre PC ?

L’autre point c’est que les tests unitaires prennent fatalement du temps au moment des les réaliser. Autant les prévoir, et avancer avec plus de sérénité pour le futur. Mais bon ce temps représente un coût et vous ne pouvez pas forcement vous le permettre. Alors quoi tester ?

Nous avons pris parti avec mon équipe de tester systématiquement deux éléments :

  • Tous les services qui sont fournis à des tiers
  • Toutes les briques que nous réutilisons en interne

Pourquoi uniquement ces deux points là et pas tout ? Parce que nous n’avons pas le temps, et surtout que tout tester n’est pas forcément pertinent. Par exemple certaines applications événementielle qui vont être jeter au bout de deux semaines nous faisons l’impasse. Le retour sur investissement ne vaut pas le coût.

Nous testons les services fournis aux tiers, pour la simple et bonne raison que nous n’allons pas fournir un service défaillant à des tiers liés uniquement à des modifications de notre part. C’est une question de respect à mon sens. Quand vous payez un service vous ne souhaitez pas que votre fournisseur vous disent : « Ah oui ça marche plus mais c’est parce qu’on a fait des modifications, on est désolé on va réparer ça rapidement, …. bla bla bla ». Vous voulez que ça marche un point c’est tout. Donc on s’y engage.

Nous testons les briques que nous réutilisons, par exemple, nous avons des briques internes qui sont réutilisées à travers toutes nos applications. Celles ci par moyen d’y couper on teste. C’est logique si on a une erreur elle sera multipliée par le nombre de projet. Ça relève plus du bon sens que d’autre chose. D’autant plus que ces briques sont énormément utilisées et complexes, rejouer tous les tests à la main ou penser à tout vérifier est impossible. Alors qu’exécuter les tests unitaires ça prend quelques secondes (un peu plus car on en a quelques centaines voire quelques milliers sur certains projets).

Pour le reste, on ne teste pas unitairement notre backoffice par exemple, parce qu’on n’y voit pas l’intérêt, nous avons moins de 10 utilisateurs dessus, quand ça pète ils s’en rendent compte dans l’environnement de recette et ça ne fait de mal à personne. On corrige, ils vérifient, ça par en prod.

Bref, à mon sens tout tester n’a pas forcément de sens, mais tester est indéniablement un atout pour la tranquillité des équipes et la pérennité du code.

Gestion de la dette technique : partie 2 – Duplication de code

Nous voila dans la suite de l’article de la gestion de la dette technique. Aujourd’hui nous allons parler du point sur le code dupliqué, code duplicate ou encore très souvent nommé « copier/coller à l’arrache ».

Le premier point sur ce sujet c’est tout simplement de comprendre pourquoi un code dupliqué est nuisible dans un projet unitaire. L’évidence même c’est tout simplement qu’au lieu d’avoir un bug, vous en avez autant de fois que vous avez dupliqué le code. Ca semble une évidence et pourtant.

Pour éviter ce genre de bourde nous utilisons plusieurs choses. La première c’est un outil simple et surtout automatique que vous pourrez intégrer dans jenkins. J’ai nommé : phpcpd

La seconde chose c’est l’échange entre les développeurs. Sans échanges au sein de l’équipe de développement il y’aura forcément du code dupliqué. Il est utopiste de penser que tous les développeurs d’un même projet ont la même connaissance de l’ensemble du projet. Chacun a ses préférences, d’autres ont travaillé plus de temps sur un point, et tout simplement tout le monde ne peut pas tout retenir.

Ok, très bien, qu’est ce qu’on fait de ce code dupliqué dans notre projet unitaire. C’est assez simple, il suffit d’en faire une librairie. Sortez le code dupliqué dans une fonction avec des paramètres d’entrées et la sortie qui va bien. Le tour est joué.

Quoi que… Il faudra faire attention à une chose. Le moment où ce code dupliqué utilisé par N autres personnes aura besoin d’une petite spécificité pour l’un d’entre eux. Il sera alors temps de ne surtout pas faire un petit « fix » à l’intérieur spécialement pour l’un pouvant impacter les autres.

Mais le véritable problème du code dupliqué c’est quand il est transverse à plusieurs projets. Là ça devient vraiment pas cool. La raison est toujours la même que précédemment, on va devoir corriger des bugs de partout. Et surtout c’est potentiellement des personnes différentes qui vont corriger le bug de façon différente.

Pour éviter ça, nous échangeons le plus possible à l’oral pour savoir qui fait quoi. Quand quelqu’un rencontre un problème avant de le corriger, on demande si quelqu’un l’a déjà rencontré. Les compétences de chacun sont ainsi tirées vers le haut, et l’émulation se crée au sein de l’équipe.

Une fois qu’on identifie des éléments dupliqués au sein de plusieurs projets nous en faisons si possible une librairie qui se retrouve ensuite en sous module des différents projets. Il faut faire attention à ce point et essayer de garder à jour un schéma de tout ça car ça peut devenir un nœud de spaghetti. Mais surtout la mise à jour du dépôt parent peut engendrer des effets en cascade sur les projets enfants.

Il n’y a pas de solution miracle, c’est l’échange, la revue de code, le pair programming qui restent à mon sens la clé du succès sur ce point même si des outils existent et peuvent attirer votre attention dessus.

Gestion de la dette technique : partie 1 – C’est quoi une dette technique

Suite à la lecture de cet article sur la différence entre ce qu’est une bonne et une mauvaise dette technique j’ai pris l’initiative de faire réfléchir mon équipe et moi même sur le sujet. Nous avons abordé les choses en plusieurs points,  en commençant par qu’est ce qu’une dette technique pour nous.

J’insiste un peu sur le « pour nous » car cet article et les suivants n’ont pas vocation à évangéliser les foules juste à vous partager un retour d’expérience.

Nous avons donc listé les points suivants et je vais tacher à travers une série d’articles de vous faire partager notre expérience.

Une dette technique pour nous c’est :

  • absence de respect d’une convention de codage
  • absence de commentaires
  • complexité du code trop importante
  • code dupliqué
  • pas de tests unitaires
  • pas de test fonctionnel

Nous avons ensuite pris chaque point pour les prioriser et surtout définir le périmètre de chacun. Pour chacun nous avons également discuté des options de mitigation afin de ne pas accumuler de dette sur des points simple.

Commençons par le plus simple la convention de codage. Nous avons adopté les conventions de codage psr 0-1-2-3 c’était un choix évident étant donné qu’on utilise Zend framework 2. Tous les membres de l’équipe ont bien assimilés la chose, tout le monde y trouve son compte en gagnant en lisibilité et en adaptabilité en passant sans problème du code de l’un à l’autre.

Même si la convention est présente dans l’esprit de chacun au court du développement, nous restons des humains faillibles. Pour cela nous nous sommes donc posés la question de comment garantir le respect de cette convention. Nous avons plusieurs éléments à notre disposition.

Premier point notre serveur d’intégration continue,  jenkins. On y a PHP code sniffer (phpcs) avec l’implémentation de la convention PSR disponible ici. C’est bien mais on est réactif et non proactif et ça ne nous convient pas complètement.

Nous avons alors utilisé des plugins dans nos IDE. Sur sublime text ou netbeans il existe de solutions qui font tourner phpcs au fil des modifications. C’est bien pratique pour corriger au fil de l’eau les erreurs d’inattention.

Mais cette solution ne convient pas à tout le monde. Alors nous avons rajouté un autre système le pré commit hook. Ce pré commit lance cs fixer de sensiolabs qui corrige automatiquement les erreurs.  Et derrière on passe de nouveau phpcs. Ceinture et bretelles on est tranquille.

Actuellement nous n’avons plus ce type d’erreur ou alors occasionnellement quand on fait des développements en dehors de nos ide etc… C’est rarissime mais ça peut arriver. Deux ou trois fois par an.

C’est pas grave on a pas tué un bébé panda.

Voilà pour la partie convention de codage. La prochaine fois on attaque le code dupliqué ;-)

PHP : PSR pour ceux qui ont raté le coche

Actuellement en poste chez France Télévisions j’ai fait adopté à mes équipes et mes sous traitants la suite de convention PSR. Pour ceux qui auraient loupé un épisode dans le fabuleux monde de PHP mais surtout sur dans un monde qui veut aller vers du mieux, PSR c’est une suite de « normes ». Actuellement il y a 4 chapitres dans PSR nommés très justement PSR-0, PSR-1, PSR-2 et je vous le donne dans le mille, PSR-3.

C’est une suite qui va plus loin qu’une « simple » convention PEAR ou ZEND, je ne vais pas tout vous citer ici mais voici ce que vous trouverez dans chaque chapitre.

PSR-0

L’objectif c’est en se basant sur le namespace d’une classe être capable de la charger. C’est ce qu’on appelle l’autoloader.

Toutes les infos sur github : https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md

PSR-1

L’objectif c’est de définir une convention de codage « à minima »

  • Files MUST use only <?php and <?= tags.
  • Files MUST use only UTF-8 without BOM for PHP code.
  • Files SHOULD either declare symbols (classes, functions, constants, etc.) or cause side-effects (e.g. generate output, change .ini settings, etc.) but SHOULD NOT do both.
  • Namespaces and classes MUST follow PSR-0.
  • Class names MUST be declared in StudlyCaps.
  • Class constants MUST be declared in all upper case with underscore separators.
  • Method names MUST be declared in camelCase.

Toutes les infos sur github : https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md

PSR-2

L’objectif est d’enrichir PSR-1. Il n’y a qu’un point avec lequel je suis en désaccord, c’est la limitation du nombre de caractères par ligne que je trouve trop bas.

  • Code MUST follow PSR-1.
  • Code MUST use 4 spaces for indenting, not tabs.
  • There MUST NOT be a hard limit on line length; the soft limit MUST be 120 characters; lines SHOULD be 80 characters or less.
  • There MUST be one blank line after the namespace declaration, and there MUST be one blank line after the block of usedeclarations.
  • Opening braces for classes MUST go on the next line, and closing braces MUST go on the next line after the body.
  • Opening braces for methods MUST go on the next line, and closing braces MUST go on the next line after the body.
  • Visibility MUST be declared on all properties and methods; abstract and final MUST be declared before the visibility;static MUST be declared after the visibility.
  • Control structure keywords MUST have one space after them; method and function calls MUST NOT.
  • Opening braces for control structures MUST go on the same line, and closing braces MUST go on the next line after the body.
  • Opening parentheses for control structures MUST NOT have a space after them, and closing parentheses for control structures MUST NOT have a space before.

Toutes les infos sur github : https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md

PSR-3

L’objectif c’est de définir comment votre application doit logger des évènements. Je trouve l’idée intéressante mais je suis un peu dubitatif sur le fait que ce soit un standard.

Toutes les infos sur github : https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md

 

Je continue sur PSR, pour ceux qui voudraient passer leur code aux normes PSR, Sensio Labs (Symfony) a publié un outil pour faciliter la mise en place : http://cs.sensiolabs.org/. Je ne l’ai pas testé personnellement, mais je suis preneur de vos retours dans les commentaires ;)

Enfin pour terminer le chapitre PSR, voici un outil pour vérifier dans votre environnement d’intégration continue que tout est conforme, grâce à une implémentation des rulesets de PHP_CodeSniffer disponible ici :https://github.com/klaussilveira/phpcs-psr .

Voila ça fait une petite piqûre de rappel ou qui sera peut être une grande découverte pour d’autres ;)