Bienvenue sur Développement Agile

Référence sur le développement logiciel Agile. Nous traitons de conception, de programmation, de pratiques de génie logiciel, d'essais et d'autres sujets connexes.

Vos casseroles sont-elles propres ?

Publié par Jean-Francois Gilbert le dimanche 30 novembre 2014 à 00:00

Source: https://www.flickr.com/photos/nicholassmale

Lors de son son keynote présenté à l'Agile Tour de Québec le 5 novembre dernier, Michael Feathers comparait le code à une cuisine. Avant de préparer de nouveaux plats, il va de soi de nettoyer les ustensiles, poêles et casseroles. Idéalement, on le fait au fur et à mesure qu'on les salie. De cette façon, on n'accumule pas une montagne de vaisselle et la cuisine reste relativement propre en tout temps. 

C'est une analogie intéressante mais le principe n'est pas toujours évident à appliquer dans notre code. Ce n'est pas qu'on ne veuille pas nettoyer au fur et à mesure, mais plutôt qu'on ne réalise pas toujours que le code est sale. L'idée même de code propre ou sale varie d'un programmeur à l'autre. Oui il y a de nombreux livres et articles publiés à ce sujet. Cependant, le pourcentage de développeurs qui ont lû sur le sujet ou qui prennent le temps d'appliquer les bonnes pratiques demeure trop bas. 

Encouragez le réusinage du code et discutez des bienfaits dans votre équipe. Décidez ensemble de ce qui est acceptable et ce qui ne l'est pas, mais visez haut en termes de qualité. Si votre cuisine est sale, peut-être serait-il temps d'y remédier. 

Il y a certainement plus d'une façon de sensibiliser vos collègues à ne pas la salir davantage et à commencer à la nettoyer. Une piste de solution possible serait de créer une "check list" des choses à vérifier une fois que le code est terminé. Avant d'archiver du code, un développeur devrait consulter la liste et s'assurer que le code rencontre les standards de qualité établis par VOTRE équipe. 

Je vous suggère de commencer modestement avec quelques éléments de base en expliquant bien la raison de leur présence sur la liste. Bonifiez-là à mesure que les bonnes pratiques sont ancrées dans les mœurs de votre équipe. 

Alors, dans votre cuisine, les casseroles sont-elles propres ?

Avoiding Layers of Misdirection

Publié par Jean-Nicolas Viens le jeudi 29 mai 2014 à 09:53

Have mocks led you to add frustrating layers of indirection? You are not alone. This is an argument part of the ongoing debate with DHH (David Heinemeier Hansson), Martin Fowler and Kent Beck.

All three of them seem to be in agreement on one thing: mocks should be avoided. This is what I think brings you from layers of indirection to layers of misdirection.

Skippable summary

You may skip this section, even if you are not familiar with the topic. Refer to these links to continue the discussion!

Here are the main parts (I think), in order :

  • Is TDD Dead? David's blog post following his railsconf keynote. The subsequent articles are interesting as well.
  • Their firstsecond and third hangout sessions.
  • Google, twitter

These people have a lot more experience than I do, but I still don't see mocks the same way they do. Hopefully, this will make some sense. As for everything pertaining to this debate : what works for me might not work for you. But, it doesn't mean you should not try it.

This is obviously a vast debate with various angles of approach. If you want test isolation with proper mocking, Gary Bernhardt nailed it in my opinion. Read his post. If the test speed argument is one that bothers you, I suggest you read Corey Haines' article. If you are still unsure that integrations tests can harm you when not done properly, I could not explain it better than J. B. Rainsberger in this video.

What if mocks had nothing to do with it

The angle I want to tackle is one that has confused me a lot over the years. Sorry, there will be no definite answer at the end of this article, just a suggestion for a further conversation. I hope you chip in!

Over the years, I have seen people hate TDD because they had to do mocks. Doing mocks forced them to create new classes. Many of them got confused in their own design after three or four of these classes.

This phenomenon is also seen when you read someone else's code. If it's all in one place, you can read it in one go. Adding layers of indirection makes it harder to follow. DHH puts it this way :

[If I can look at something that fits within 10 lines of clean code], to me that's endlessly easier to understand than sixty lines that has three additional layers of indirection that I have to comprehend first.

I agree with this statement, up until he says "that I have to comprehend first". You don't. The name of the class or method you are calling should be enough to tell you what is happening there. You know the what, not the how. To me this is key to making complex business models work. I never add layers of indirection, I add layers of I-don't-care-ness.

But this is where I get confused. This makes sense to me, but most people seem to disagree. Everyone wants to understand every single layer first, but that is just impossible to do when you live in a world of complex business rules (as opposed to simple CRUD operations).

Maybe this is just a naming problem? Of course, if a method is poorly named, this will become a layer of misdirection. But I think there is more to it.

What if you just made it hard on yourself

Just let go.

Adding a layer, or simply a private method, allows me to understand a small portion of the algorithm faster than anything else. When you write a complex algorithm without tests, what do you do? Write a part of it, refresh, does it work? Yes, keep going. You iterate. Test the algorithm bit by bit. Adding layers allows you to do just that, in a TDD flow that makes sure you get every part of the algorithm right.

Here is a simple example. What does this do?


receipt = new Receipt(employeeNumber);
for(int i = 0; i < items.size; i++) {
    receipt.registeredItems.add(items[i]);
}
return receipt;

You can most likely figure it out, but this version should be faster to understand :


receipt = receiptFactory.create(employeeNumber);
receipt.registerItems(items);

What happened? Did I really remove code? Not at all. In fact, I would have added code. The number of lines of code pertaining to the business logic would be the same, but code to make the compiler happy would be added. That is class declaration, brackets, etc. It would even add one more file. 

Is it still worth it? Hell yeah! I've now stopped caring about two things: how to create a receipt and how to add items to it. Do you need to queue the new receipt somewhere? Don't know don't care. Do you need to add something between each items? Don't know don't care. Our brain is very limited, asking less of it each time is good. You get more lines of code, but less code to care about for each step: you brain is happy.

Tests get better too. I can now have a test that says "you should create a receipt and add items to it" (hint: mocks required!). Obviously, the factory will now have to be tested: is the receipt created properly? Same goes for the receipt itself. 

I added a layer of indirection, but the resulting algorithm is simpler, in each and every one of these classes. +1 for the readability because you know where to look if you want to change how a receipt is created. If you don't care, you don't even need to look for it. +1 for test documentation too, I now know they fully document these pieces of code.

This code is not tested!

The code above has not been tested. It looks like java, but who cares.

If I was to do it in TDD, I would probably have come up with better names, better collaborators. I have found that the best way to figure out the proper use of layers is through (mockist) TDD.

If a mock is hard to reason about, it is wrong. An integration test will not put enough pressure on my design to let me know about it. The slice which is being tested will grow, and grow, and grow... until the "in-between" becomes unreadable. What do we do? We split it! We add a layer of I-don't-care-ness, or at least that's what we think we are doing. We are using the code immediately, so it looks easy enough to understand. Here is the catch: how do you know you made the right separation? Is it viable in the long term?

This is where I leave it up to you

What do you think? Do you have to understand each parts before changing an algorithm? How does it add complexity?

I know the example is an over simplification, but in my experience, it scales properly.

Am I the only one to imagine software in my head and see all the moving parts interacting with each other? No I am not crazy, my mother had me tested - Sheldon Cooper.

Présentation: Esclave de votre dette technique?

Publié par Félix-Antoine Bourbonnais, Pascal Roy le vendredi 15 novembre 2013 à 12:00

 

Description

Votre code est un trou noir? Chaque fonctionnalité est de plus en plus difficile à développer? Vous ne voulez plus toucher à un module sous peine de voir toute votre énergie aspirée?

Cette présentation vous permettra de prendre conscience de l’impact de la dette technique sur votre quotidien et sur votre capacité à livrer du logiciel fonctionnel et de qualité à chaque itération.

Comment soutenir le même niveau de productivité? Comment garder son codesimple et facile à changer?

La présentation sera en trois volets : identifier ce qu’est la dette et ses impacts, quelles sont les techniques et pratiques pour éviter la « patrimonialite aigüe» (infection d’un système vieillissant) et finalement, comment gérer la dette déjà accumulée, y compris quelques trucs pour votre PO.

Non, la déprime n’est pas le destin de tous les projets vieillissants…

  • Niveau : Tous
  • Public cible : Équipes de développement et gestionnaires

Présentation

Bob Martin nous parle de son livre Clean Coder

Publié par David Beaumier le jeudi 2 février 2012 à 19:45

Dans cette seconde vidéo Robert C. Martin discute avec Louis-Philippe Carignan de son plus récent livre, The Clean Coder: A Code of Conduct for Professional Programmers. Il explique comment ce livre est en réalité un ouvrage très personnel puisqu'il est basé sur son propre parcours professionel. Il y partage avec ses lecteurs ses réussites comme ses échecs. Ce livre est aussi son premier ouvrage qui ne soit pas purement orienté sur des aspects techniques.

Nous espérons que cette entrevue vous donnera le goût de lire ou relire cet excellent bouquin et que vous bénéficierez de l'expérience de Bob Martin.

Comme promis, d'autres vidéos de l'Oncle Bob suivront dans les prochains jours.

Pourrez-vous soutenir le rythme?

Publié par Philippe Tremblay le vendredi 27 janvier 2012 à 13:00

Lors d’un précédent billet intitulé « OÙ EN ÊTES-VOUS DANS VOTRE PROGRESSION AGILE », nous avons énuméré quelques techniques permettant d’évaluer la progression d’une adoption Agile dans une organisation.

Bien que ces mesures permettent l’évaluation de l’état actuel de la situation, bien peu d’entre elles permettent d’estimer si le produit développé permettra à une organisation de soutenir le rythme et contribuer à la prédictibilité espérée en développement itératif.

Soutenir le rythme

Au cours de sa durée de vie, est-ce que votre logiciel pourra évoluer tout en maintenant un niveau de coût linéaire plutôt qu’exponentiel? La figure suivante illustre la différence entre les coûts de développement au cours du temps d’un produit répondant aux (nombreux) critères de qualité et un autre qui minimise ou voir même néglige l’importance des principes de qualité logicielle.

Cout Logiciel Duree Vie

Figure A - Coûts du développement d’un produit dans le temps

Un logiciel de qualité pourrait avoir un coût initial plus élevé qu’un autre de moindre qualité. Il est cependant indéniable que les raccourcis pris (consciemment ou non) lors de la conception de ce dernier rattraperont et dépasseront rapidement les coûts de celui développé selon les caractéristiques d’un logiciel de qualité.

Un « nouveau » produit deviendra assez tôt un « ancien » sans ces caractéristiques de qualité. Il sera bientôt difficile de défendre le produit contre les attaques des coûts de maintenance astronomique et l’incessante croissance de la complexité. Ironiquement, ce sera probablement l’équipe de développement qui militera face aux gestionnaires afin de remplacer l’ancien produit par un (autre) nouveau. Et malgré les bonnes intentions, il est fort possible que les caractéristiques de qualité soient encore absentes et que le gaspillage se répète tout en dilapidant les précieux revenus de l’organisation.

Un logiciel de qualité, c’est quoi exactement?

Pour bien répondre, nous devrions faire plusieurs billets sur le sujet, mais de façon (très) concise, voici quelques-unes des caractéristiques d’un logiciel de qualité

Feuilles de thé ou lignes de la main?

Vous pouvez toujours essayer les méthodes « alternatives » afin de faire des prévisions sur la capacité du logiciel à soutenir le rythme, mais ce ne serait pas notre premier conseil. Quelles mesures pourraient bien nous aider?

La vélocité? Pas vraiment. Bien que la vélocité permette d’estimer la capacité de l’équipe, elle dépend de beaucoup de facteurs subjectifs et variables. Dont celui de notre définition de « Terminé ». Ce qui signifie que nous pourrions avoir une vélocité moindre en ajoutant des critères de qualité à notre définition de « Terminé ».

Le nombre de défectuosités? Après tout, avoir la plus petite quantité de défectuosités possible, n’est-ce pas ce qu’on entend par « un logiciel de qualité »? Non, non et non! On peut atteindre un nombre limité de défectuosités en investissant une quantité de temps indécente dans le « contrôle de qualité » d’un produit plus que déficient.

Le taux de couverture de nos tests automatisés, ça c’est bon…N’est-ce pas? Désolé, un logiciel de piètre qualité peut avoir 100% de couverture en tests automatisés tout en demeurant illisible et sans respecter les principes SOLID ou Clean code etc.

La beauté, c’est à l’intérieur

Hé oui, vous devrez « regardez sous le capot » pour savoir si vous avez un logiciel de qualité entre les mains. Vous me direz peut-être que vous faites de la revue de code régulièrement. Que signifie régulièrement pour vous? Plusieurs fois par année, par mois? Peut-être avez-vous la discipline de le faire plusieurs fois par semaine. Même cette fréquence ne peut probablement pas permettre d’obtenir une idée objective de la qualité du logiciel au cours des itérations.

Afin de soutenir le rythme d’un développement itératif et de vous assurer que vous n’êtes pas en train d’alimenter le spectre d’une dette technique grandissante, plusieurs outils et techniques sont à votre disposition. En voici quelques-uns

  • Outils automatisés pour les mesures statiques
    • Sonar (Java, C#, C, PHP)
    • TFS avec CodeMetric
    • NDepend (mesures statiques et analyse des dépendances)
    • Revue de code entre les pairs intégré dans votre définition de « Terminé »
    • Programmation en pair

Conclusion

N’oublions jamais le paradigme sous lequel nous devons concevoir les projets sous les principes Agile. La qualité ne doit plus être une variable, mais bien une constante (Figure B). La meilleure façon d’obtenir cette régularité est d’inspecter et adapter assidûment ce que l’on crée afin que l’organisation génère un actif plutôt qu’un passif.

C’est ainsi que l’organisation sera en meilleure posture afin de répondre aux besoins de ses clients…aujourd’hui et demain.

Agile Triangle

Figure B – Paradigme des contraintes de projets Agile

©Cette image est une gracieuseté de M. Patrik Malmquist (http://www.applitude.se)

Archive