dimanche 27 novembre 2011

mardi 18 octobre 2011

Pas si simple de faire simple

La version express de ce billet est que nous ne faisons pas assez la différence entre “construire avec des briques simples” et “faire des objets simples à utiliser”. Ce n’est pas du tout la même chose!
  • La différence :
    • La simplicité d’utilisation est
      • Contextuel
      • Composé
      • Plutôt fermé à l’évolution
    • Les briques simples sont
      • Généralistes
      • Unitaires
      • Ouverts à l’évolution
  • C’est possible d’avoir les deux.
Voici la version longue, avec des explications et, promis, des exemples.

Dans ce keynote Stuart Halloway explique que le mot simple veut dire quelque chose de très fondamentale. Il soutient que la définition du mot simple est non composé ou non assemblé (non compound en anglais).

Puis il continue à nous expliquer pourquoi il est primordiale de construire seulement à partir de choses simples. Notamment il dit
  • Essayez de faire quelque chose de simple à partir de choses non simples … C’est impossible
Autrement dit, pour avoir une librairie ou application simple, on doit l’assembler de choses simples. Puis il finit son keynote par dire.
  • Si un peu plus du code était écrit dans le respect de la simplicité le monde serait un peu meilleur.
Bon finalement c’était juste le Single Responsibility Principle dans une nouvelle sauce. Soit, seulement quelques jours plus tard, il m’est venu à l’ésprit qu’il y a un paradoxe. Car si j’écris tout mon code de cette manière alors il serait chiant à utiliser, même pour moi. Notamment lorsqu’on utilise fréquemment une fonction/objet avec les mêmes paramètres ce serait chouette de ne pas le répéter partout dans le code. Un code simple n’est pas toujours simple à utiliser.   En regardant de près il n’y a pas de paradoxe, mais la réflexion m’a fait comprendre quelque chose que je vais partager ici.

Pour rendre la vie facile pour ceux qui utilisent notre code (souvent nous mêmes) nous avons tendance à faire du code simple à utiliser. Je suis convaincu que si on échoue à faire quelque chose de simple c’est souvent parce qu’on veut faire quelque chose de simple à utiliser! Et pourtant ce compromis n'est pas nécessaire.

Si on revient à la définition de simple on constate que simple est une qualité intrinsèque et non contextuelle. Il est possible de juger de la simplicité de manière objective.

Avec Simple à utiliser c’est l’inverse. Par définition c’est simple pour l’utilisation prévue. Si on change un peu le contexte il y a toutes les chances que ce ne soit plus très simple à utiliser. Simple à utiliser est contextuel.

Souvent nous trouvons des choses simples à utiliser parce que ça ressemble à quelque chose de connu, par exemple un patron de conception que nous avons déjà utilisé. Simple à utiliser est subjectif.

Ce serait bien dommage de faire des compromis entre une qualité "absolue" et une qualité contextuelle et subjective !

Prenons par exemple cet objet qui fait partie d’une application de crawl basique.

BatchCrawler est simple à utiliser car nous n’avons pas à fournir beaucoup d’arguments pour l’instancier. Par contre il n’est pas Simple car il fait un tas de choses en plus de crawler une liste d’urls :

  • Il spécifie où est configuré le timeout de chargement d’une page.
  • Il contraint ce timeout à ne changer dans toute la JVM voire même on doit redéployer pour la changer.
  • Il contraint à utiliser un RetryingHttpCrawler – qui retente en cas de timeout et qui passe par le protocole HTTP.

Limitant ainsi fortement le potentiel de réutilisation de l’objet.

Pour que l’objet puisse être qualifié de Simple, le constructeur devrait ressembler à ça

Mais alors il deviendrait chiant à utiliser. Si cet objet est instancié de plusieurs endroits de l’application il y aurait de la duplication. Nous allons donc réintroduire ce constructeur sous forme de FactoryMethod avec un nom explicatif (documentation) parce qu’il s’agit d'une façon de configurer ce graph d’objets.

Comme avec tout exemple simplifié c’est n’est jamais trop grave. C’est encore suffisamment petit pour être corrigé après-coup. Seulement dans une application réelle ça peut être un cauchemar car régulièrement on se retrouve avec l’initialisation d’une grappe d’objets - ici BatchCrawler initialise un RetryingHttpCrawler etc. Presque à chaque fois l’initialisation des objets plus bas dans le graphe ont des conséquences indésirables, c’est souvent ça qui nous rend les tests après si difficiles ... Le remplacement d’un objet dans ce graphe n’est pas toujours aisé et le code nécessaire teintera le code d’initialisation avec complèxité.

En construisant uniquement avec des objets et fonctions Simples on arrive à l’enrober avec une simplicité d’utilisation… pour le besoin actuellement connu. Quand le besoin change (lire toujours) on est le roi du pétrole. On a le beurre et l’argent du beurre.

Note : je ne dis pas qu’il faut essayer d’imaginer le besoin futur, seulement qu’il faut décomposer son code actuel en des briques les plus simples possible. Par dessus on peut ensuite construire la simplicité d’utilisation avec par exemple des valeurs par défaut.

Conclusion
Je ne vais pas conseiller de toujours faire ainsi, car à vrai dire rien n’est toujours vrai. Simplement le message que j’essaie de passer est

  • Il y a une différence importante :
    • La simplicité d’utilisation est
      • Contextuel
      • Composé
      • Plutôt fermé à l’évolution
    • Les briques simples sont
      • Généralistes
      • Unitaires
      • Ouverts à l’évolution
  • C’est possible d’avoir les deux.

dimanche 3 juillet 2011

Symfony actions ARE easily testable

All Symfony experts I've met have told me that I'd better not bother with unit testing the actions because it's difficult enough that it just isn't worth it. Even an official Sensio Labs trainer that wisited our company said the same thing (I find that quite surprising). Only when you're doing TDD it's rather annoying not to be able to test the first lines of a new feature as it breaks your flow.

I should never have believed them. Luckily a colleague of mine didn't. In fact it turns out it's strikingly easy so I'd like to share it with you.


Here's an example of a how to unit test a standard action “executeHelloWorld” and an ajax action “executeGoodEvening”. It takes two simple lines in the setUp to prepare instantiation of the action.



The rest of the non-magic is in the fact that Symfony actions do not directly return the values we are interrested in. Ordinary (non-ajax) actions do not return anything they just prepare the execution of the template by storing values in a var-holder, we access it by action->getVar('name'). Ajax actions generally directly compiles the partials with parameters passed in an array and adds all that to action->response->content.

Credits go to Marc Nazarian and Sebastien Fromont without whom I still wouldn't TDD my actions.

For reference the action code

and the partial used

samedi 28 mai 2011

Software Craftsmanship 2011 - décoiffant!


Je dois dire qu'une conférence où l'on a l'occasion de parler directement avec Gojko Adzic, Steeve Freeman, Michael Feathers, Jason Gorman, etc est forcément passionnante! C'est sans mentionner des sessions d'un très bon niveau où l'on a l'occasion de pair-programmer avec d'autres passionnés! Puis toutes les conversations entre participants.
Voici un petit résumé des sessions auxquelles j'ai assisté.
How object oriented are you feeling today?
Il fallait résoudre un petit problème tout en respectant 9 principes qui mènent infailliblement à un code orienté objet.

Ce que j'aime bien avec les exercices bornés par des règles fortes est que ça permet de sortir de ses habitudes et avoir un inspecteur de code derrière le dos pour nous aider à nous mettre en cause. Aussi lorsqu'une alerte est levée par la violation d'une des règles alors c'est souvent pas important quelle règle a été violée mais signe d'un problème plus profond. Par exemple pendant cette session nous nous sommes trouvés à vouloir avoir 3 collaborateurs (le max étant 2) dans un objet Account: Client, Bank et Money. La banque était nécessaire pour autoriser ou pas un transfert (autorisés uniquement au sein de la même banque). Le problème n'était pas d'avoir un troisième collaborateur, mais que le compte allait gérer trop de choses – le transfer ET la demande de l'autorisation. Une meilleure solution est que la banque autorise le transfert puis délégue le transfert au compte (Single Responsability Principle). Les règles nous ont permis de le voir plus tôt.

Les règles que je compte appliquer strictement au jour le jour
  • first class collections (wrapper chaque collection une classe métier)
  • one level of indentation
Celles que je vais essayer d'appliquer un peu plus
  • no else statements (même pas dans les factories).
  • Wrap all primitives and string in their own class
Détail intéressant, tous les développeurs java à qui j'ai parlé ont adoré, mais j'ai parlé avec deux développeurs Ruby qui trouvaient que ça rendait leur code dégueulasse!


Functional programming with Michael Feathers
Session pas très bien préparée et pas très avancée. Plutôt dirigée sur la question quels éléments de la programmation fonctionnelle devons nous utiliser dans les langages objet. Il a essentiellement montré les expressions lambda (opérations sans état sur collections), avec la conclusion que parfois ça facilite mais parfois elles manquent un peu d'expressivité (même avec un bon nommage).

Bon point : tant que l'interface d'une fonction est pure (pas d'effet de bord, toujours le même résultat pour les mêmes entrées) peu importe si tu utilises la mutabilité à l'intérieure.

J'ai posé la question à Michael Feathers et à Steeve Freeman qui était là aussi « Why should we still develop with object oriented languages today ». C'est une question que je me pose depuis environ un an. Et toutes les réponses que j'ai trouvé sont à mon avis insatisfaisantes (performance, habitude des développeurs, moins de pouvoir = moins de risque) c'est certainement pas parce que l'objet est plus facile à maitriser! J'avais trop hâte de connaître le point de vu de ces cadors. Seulement aucun des deux avaient une réponse à part « I haven't yet seen a project of size written in a functional language ». On manquerait seulement de recul?

Lean code challenge
C'était absolument fabuleux! Chris Parsons a traduit 4 des principes de Lean, (waste, deliver fast, build quality in, customer value) dans un défi ludique de développement.
A travers 6 itérations de 10 minutes nous avons construit un calculateur de prix de panier de fruits avec des stratégies de prix évolutives et franchement changeantes(!). Je ne peux m'empêcher de dire que les stratégies, quoique réalistes, n'étaient absolument pas lean, où il vaut mieux éliminer la complexité que l'automatiser...

Nous avons terminé toutes les exercices et avec un code plus qu'acceptable. Si on n'avait pas fait du TDD j'imagine pas comment on aurait pu y arriver. Bel exemple du ROI sur le TDD en seulement 60 minutes! Gojko Adzic a dit qu'il n'avait commencé le TDD qu'au bout de la deuxième ou troisième itération – avant il ne trouvait pas que c'était utile, intéressant.


L'année prochaine j'y retourne!

jeudi 7 avril 2011

Agile Team Agreement

L'année dernière j'ai vécu dans une équipe qui marchait particulièrement bien. En essayant de comprendre les raisons de ce succès avec un autre des membres, Bernard Huguet, on a mis le doigt sur un pattern qui nous semble prédominant que l'on avait appelé l'Agile Team Agreement - l'ATA. On va essayer de décrire ce qu'on entend par ATA et partager la rétrospective que nous en avons fait. Mais avant d’aller plus loin je voudrais dire que nous ne l’avons pas inventé, l’idée derrière les Team Agreements ou Working Agreements existe sans doute depuis l’aube de l’homme et il n’y a rien d’obligatoirement agile, cela pourrait fonctionner dans n’importe quelle équipe. Le contenu serait juste différent.

Quoi de mieux que la photo de notre ATA pour décrire ce que c'est?


L'équipe a travaillé ensemble pour trouver et partager les pratiques qui lui paraissent être les facteurs clés de son bon fonctionnement. Il est essentiel que ce soit le résultat d'une participation active et équilibrée des membres de l'équipe, peut-importe comment vous y arrivez (pratiques de rétrospectives agiles peuvent aider ici). Exprimé sur un simple bout de papier, ce consensus est un réel contrat d'équipe et on s'attend à ce que tout le monde s'implique à 100%.

Au fil des mois on a pu observer un certain nombre de comportements que l’on pourrait imputer à l’ATA:

Fort sentiment d'appartenance à une équipe
Partager des valeurs, être fier de ce qu’on fait et savoir qu’on peut compter sur les autres membres de l’équipe crée un fort sentiment d’appartenance à cette équipe. C'est un élément important de motivation que d’avoir l’impression de faire parti de quelque chose de plus grand que soi.

Les équipiers ont du courage quand il le faut
Quand on a pris du retard sur un tâche ou que l’on subit une forte pression du management et du business, il est très tentant de discrètement prendre des raccourcis pour finir plus vite. Il y a deux avantages immédiats, 1) on tient les délais prévus et 2) on ne donne pas l’impression d’être lent ou mauvais. Certes on peut choisir de prendre des raccourcis mais ça doit certainement pas être pour sauver sa propre fierté. Les effets négatifs des raccourcis se font généralement sentir assez vite et on les paye souvent sur toute la durée de vie du projet.

Les post-its "Healthy Code", "Rendre problèmes visibles" et "As a team". Aident justement à donner du courage à rendre les problèmes visibles afin qu'un décision lucide puisse être prise par l'équipe.

Confiance partagée en chacun des équipiers
Puisque tes coéquipiers partagent tes valeurs tu peux avoir confiance dans leur travail. Par exemple, nous avions “rendre les problèmes visibles” et “DoD” (Definition of Done) dans notre ATA. Ayant confiance dans le travail de nos coéquipiers on pouvait se concentrer sur notre travail avec l’assurance que ça allait bien se passer et que si un problème survenait, il serait rendu visible rapidement et une action serait prise.

Tout le monde va dans le même sens
De manière générale on est tous influençable. On a envie de plaire aux gens de notre entourage. Autrement dit on va naturellement tendre vers ce que valorise notre entourage … du moment qu’on sait ce que c’est!

Puisque l’ATA rend visible ce qui a beaucoup de valeur pour les équipiers, alors il agit comme un centre de gravité comportemental qui soude l’équipe et qui l’aide à avancer dans le même sens.

Défini dans un contexte facile et utilisé dans un contexte difficile
SI quelqu’un vient régulièrement 5 min en retard aux stand-ups, ou si quelqu’un joue cavalier seul devant le PDG au détriment de quelqu’un d’autre, il est beaucoup plus facile de rappeler l’ATA que d’initier une discussion sur la ponctualité, ou de dire à qu’il a fait le beau devant le management.

Conclusion
Cela a bien marché pour nous et nous n’imaginons pas construire une nouvelle équipe sans cet ingrédient. C’est pour ça qu’on avait envie de partager ce bout de recette avec vous.

D’ailleurs nous sommes à nouveau tous les deux dans une nouvelle équipe et la construction de notre ATA est prévue pour demain :)

samedi 22 janvier 2011

Le CodeRetreat à Grenoble

Vendredi dernier c'était le CodeRetreat à Grenoble. Pour tout le monde c'était leur premier retreat, participants comme organisateurs! Pas facile alors de se lancer. C'est certain on y croyait, surtout après nos premiers tentatives sur le problème du Jeu de la Vie de Conway en décembre on a vu que ce problème était excellent pour nous ébranler dans nos habitudes de code et de TDD. Mais on ne savait pas encore si la journée allait être une réussite.

Maintenant c'est passé et on est très contents de l'avoir fait. C'était une journée intense et tout le monde a vraiment apprécié cette exercice. C'est marrant je crois que tout le monde était fatigué voire vidé à la fin de la journée - ça doit être signe d'avoir appris quelque chose!

La veille j'avais regardé ce vidéo d'introduction d'un CodeRetreat par le maître Yoda des CodeRetreats, Corey Haines, où il explique très bien que dans la vie de tous les jours on a l'obligation de résultat qui nous pousse à ne pas être parfait, à arrondir les angles, à prendre des raccourcis. Certes, c'est normal, obligé et même une bonne chose mais cela nous aide pas à progresser, à se rapprocher de "parfait". Dans le CodeRetreat c'est different, il n'y a pas d'obligation de résultat, même c'est presque impossible de finir en 45 minutes (le temps qu'on a avant de devoir effacer le code!!). C'est donc une occasion unique de s'entrainer au perfectionnisme. De recommencer et recommencer jusqu'à cela devient un automatisme.





Nous avons fini la journée avec une rétrospective où nous avons posé trois questions à chacun
  1. Qu'est-ce que tu as ressenti?
  2. Qu'est-ce que tu as appris?
  3. Qu'est-ce que tu appliqueras dès lundi?
Ces excellentes questions viennent d'un chevronné des CodeRetreats, Alex Bolboaca. En fait la journée est tellement intense et rempli d'expériences qu'il y a besoin de quelque chose de ce genre pour en tirer le maximum de profit. En groupe c'est d'autant plus intéressant car d'un côté le groupe nous oblige de formuler notre pensée la cristallisant ainsi, et de l'autre tout le monde n'a pas appris les mêmes choses et c'est intéressant d'entendre les autres.

Pour ma part j'ai l'impression d'avoir encore besoin de temps pour digérer les expériences de cette journée - et je n'ai à peine touché un clavier !

Seul petit bémol, j'aurais bien voulu qu'on ait le temps de faire une rétro de l'animation, mais tout le monde était trop fatigué. J'espère que les participants nous donneront leurs retours et leurs propositions d'améliorations, sans trop de retenu. En gros, lachez-vous ! ;)

J'ai envie de finir avec quelques commentaires que j'ai entendu au cours de la journée:
  • "Je vais instaurer le pair-programming au moins une demi-journée par semaine"
  • "Le Smalltalk c'est cool!"
  • "Je m'efforçais déjà à prendre des baby-steps mais là je vais le faire encore plus!"
  • "C'est vraiment bien d'écouter ce que me disent les tests pour trouver un meilleur design"
  • "C'est génial de pouvoir pairer avec autant de personnes"
Si vous n'avez toujours pas envie d'aller à un CodeRetreat ou d'en organiser un, allez donc lire ça!

Merci à nos sponsors : le CARA, l'Alpes-JUG et l'Ensimag