I. Introduction▲
Suite à la publication de mon article sur les Tests en Trois temps (« 3T »)Présentation de 3T et aux différentes questions pratiques que j'ai reçues, je me suis lancé dans la rédaction d'un second article facile à lire. Je ne voulais pas paraphraser le premier article et, en même temps, je voulais utiliser un ton léger. Pour cela je me suis décidé à présenter « 3T » sous la forme d'un miniroman, en m'inspirant de mes collègues passés pour inventer les personnages, et des problématiques courantes pour illustrer un projet fictif.
Pour rappel, « 3T » est une version simplifiée (et une vision personnelle) des TDD (les Développements Guidés par les Tests). Je suis parti du constat que les TDD sont souvent accusés, à tort, de ralentir les projets, d'être complexes et de couter cher. Le principe de base de « 3T » est de mécaniser le processus de développement en subdivisant les interventions et les rôles. Chaque sous-partie devient d'autant plus simple ; il suffit la plupart du temps de recopier le cahier des charges. Au prix de quelques légères entorses aux TDD, les développeurs peuvent alors concentrer leur énergie sur la qualité de leurs productions, tout en ayant une vitesse de développement élevée et un retour sur investissement fort.
Le premier article à propos de « 3T » est disponible sur le site de developpez à l'adresse suivante : https://thierry-leriche-dessirier.developpez.com/tutoriels/java/methode-3t/Présentation de 3T
Les codes présentés dans l'article sont volontairement simplifiés pour faciliter la lecture. Les codes réels sont disponibles dans le fichier Zip.
Zip avec les sources utilisées (projet « Boutique du Chien-Copain ») pour cet article : boutique-chien-copain.zip.
I-A. D'où vient « 3T » ?▲
Il est important de noter que « 3T » n'est en aucun cas une méthode « officielle », contrairement aux TDD. « 3T » est une proposition de simplification des TDD qui devrait suffire à la plupart des équipes. En effet, mon expérience personnelle, liée à l'utilisation de Xp, de Scrum et bien entendu des TDD, me conduit à croire que les développeurs n'utilisent pas tout (certains aspects des TDD sont difficiles à faire et mangent beaucoup de temps), mais se concentrent sur certains points importants dont « 3T » est un résumé cadré. On peut voir « 3T » comme la formulation d'une pratique de simplification dont l'objectif est de gagner du temps (et de l'argent). Dans cet article, « 3T » est associée à Scrum, ce qui permet d'en suivre la mise en place à travers un projet fictif. C'est une simple illustration.
I-B. Lexique rapide▲
« 3T » n'invente rien ; c'est seulement un résumé cadré d'autres méthodes. Les termes employés dans cet article ne sont pas nouveaux. Voici néanmoins quelques définitions rapides.
Scrum et Xp : ce sont deux méthodes agiles, souvent associées.
Sprint : dans Scrum, un Sprint correspond à une période (généralement 2-4 semaines) durant laquelle on doit développer un ensemble donné de fonctionnalités.
Dashborad : dans Scrum, il s'agit d'un tableau comportant trois colonnes : à faire, en cours et fait. Les fonctionnalités à développer durant le sprint sont indiquées sur des Post-It. Ces derniers changent de colonne en fonction de l'avancement. À la fin du sprint, tous les Post-It doivent être passés de la colonne des choses à faire à la colonne des choses faites.
Le sprint backlog : Il s'agit simplement du nom Scrum de la colonne des choses à faire dans le dashboard. Cette colonne est généralement positionnée à gauche.
II. Histoire▲
Cet article présente les Tests en Trois Temps (3T)Article sur les Tests en Trois Temps sur le site developpez.com sous la forme d'un miniroman. Les rôles des personnages et leurs interactions sont volontairement décrits de manière naïve. Pour cela, j'ai allègrement pioché dans les clichés les plus courants. Mais finalement, je crois que ça rend les acteurs plus touchants et plus proches. D'ailleurs j'ai le sentiment que chacun y retrouvera le portrait de ses propres collègues.
II-A. La société et son projet▲
La société « Chien-Copain » commercialise une gamme moderne de produits canins fabriqués dans ses usines dans le respect de l'environnement. L'enseigne s'est constitué une clientèle fidèle et régulière.
À l'occasion de l'ouverture de son vingtième magasin, la société « Chien-Copain » souhaite se doter d'un service de vente en ligne dont le nom sera « la Boutique du Chien-Copain ». L'entreprise dispose déjà d'outils de comptabilité et de gestion de ses stocks ainsi qu'un site vitrine sur Internet.
La Web Agency « Green Soft », qui avait déjà réalisé le site « www.chien-copain.fr » et dont les prestations avaient été appréciées, a naturellement été choisie pour développer la nouvelle application.
Dans le cadre de cet article, pour simplifier l'explication, on ne s'intéressera qu'à une sous-partie de la boutique en ligne : la génération d'un mot de passe et son cryptage.
II-B. Les personnages▲
Pour illustrer l'utilisation de « 3T » et les phases préparatoires, cet article met en scène une poignée d'acteurs. Certains sont des personnages principaux tandis que d'autres ont un rôle symbolique.
Je me suis attaché à bien séparer les rôles (responsabilités) pour mettre en évidence les possibilités de la méthode, notamment en termes de parallélisation des tâches. On gardera toutefois en tête que, dans la vraie vie, les membres de l'équipe rempliront plusieurs fonctions.
II-B-1. La cliente (Claire)▲
Claire est salariée de « Chien-Copain ». C'est d'ailleurs la seule de cette histoire ; tous les autres personnages travaillent pour « Green Soft ». Claire est en charge de la boutique en ligne. Elle écrit et gère le cahier des charges. Elle a pouvoir de décision.
II-B-2. L'architecte (Laurent)▲
Laurent possède une solide expérience du développement. Il fréquente assidument les blogs des grandes SSII et les conférences. Pour lui, la réussite d'un projet passe nécessairement par les tests et il prend son rôle d'évangélisation au sérieux.
II-B-3. Le chef (Michel)▲
Michel a lui aussi de la bouteille. Il déjeune souvent avec Laurent, mais trouve que les TDD (Développement Dirigé par les Tests) sont trop complexes, d'autant qu'il a du mal à les faire accepter par sa hiérarchie pour des raisons budgétaires et à les imposer au sein de ses équipes. Il a découvert « 3T »sur developpez.com et compte bien l'appliquer sur le projet de la « Boutique du Chien-Copain ». C'est aussi un adepte des méthodes agiles et plus particulièrement de Scrum depuis qu'il a lu le livre « Scrum et Xp depuis les tranchées » sur Internet.
II-B-4. Les développeurs (Julie, Sébastien et John)▲
Sébastien, Julie et John écrivent le code de l'application. Ils ont des expériences différentes.
Pour pimenter le tout, disons que Julie est la fiancée de Laurent (l'architecte) et que ce dernier lui décrit régulièrement les bienfaits des TDD. Julie va tout faire pour plaire à son amoureux.
|
|
|
II-B-5. La secrétaire (Vanessa)▲
Vanessa ne joue pas un rôle important dans l'histoire. Elle ne fait même pas partie du projet. Elle incarne l'élément perturbateur : ses passages dans le bureau font chuter dramatiquement le niveau général de concentration et la productivité de l'équipe. Il faut préciser que Vanessa est charmante.
II-B-6. Le testeur (Bernard)▲
Arrivant en bout de chaine, lors de la phase de qualification, Bernard s'assure que le logiciel livré est conforme au cahier des charges dont Claire lui a envoyé une copie. Si tout est bon, il appose son cachet sur le bon de livraison, mais sinon il répond par un refus franc au chef de projet.
III. Action▲
L'histoire commence lorsque Claire (la cliente) envoie le cahier des charges de « la boutique du Chien-Copain », qu'elle vient d'écrire, à Michel (le chef de projet). Ce dernier en prend rapidement connaissance puis transmet le document à Sébastien, Julie et John (les développeurs) ainsi qu'à Laurent (l'architecte) pour obtenir leurs remarques.
III-A. Les Post-It▲
Après une prompte analyse, l'équipe se réunit pour définir un jeu de Post-It, relatif aux fonctionnalités décrites dans le cahier des charges. En effet, Michel (le chef de projet) a choisi d'appliquer « 3T » lors du développement du projet (cf. les conversations en annexes) et souhaite travailler avec les outils les plus simples (i.e. les Post-It), ce qui aura un avantage plus tard lors des « Sprints Scrum ».
III-A-1. Les Post-It généraux (jaunes)▲
À la sortie de la réunion, Michel repart avec 72 Post-It jaunes représentant les demandes identifiées dans le cahier des charges. Parmi ces Post-It, on retrouve les Post-It, portant les références « RG023 » et "RG024, constituant le sous-ensemble de l'application auquel cet article va se limiter : la génération d'un mot de passe (RG023) et son cryptage (RG024).
Les numéros des Post-It n'ont pas d'importance. Dans le cas présent, ils indiquent que vingt-deux autres Post-It ont été écrits avant, sans rien indiquer sur d'éventuels successeurs. L'équipe a simplement numéroté les Post-It par ordre d'arrivée.
Pour identifier ces deux Post-It, l'équipe est partie du cahier des charges. Un des chapitres indiquait que « le système permettra de générer un nouveau mot de passe et que ce dernier devra être crypté pour des raisons évidentes de sécurité ». L'équipe a décomposé ce paragraphe en deux besoins distincts, ce qui a donc conduit à la création des deux Post-It.
Les deux Post-It qui nous intéressent sont les suivants :
|
[Post-It RG023] |
|
[Post-It RG024] |
III-A-2. Les Post-It détaillés (bleus)▲
Les Post-It généraux (jaunes) ne suffisent évidemment pas pour développer l'application, car il subsiste de nombreuses questions. Michel (le chef de projet) organise donc une réunion avec Claire (la cliente) et son équipe. Une série de questions a été transmise quelques jours en avance à Claire et des Post-It bleus, correspondant aux réponses attendues, ont été préremplis en laissant des vides pour les informations manquantes.
Les Post-It bleus, ainsi définis et liés aux précédents Post-It jaunes, sont les suivants :
|
[Post-It RG023.1] |
|
[Post-It RG023.2] |
|
[Post-It RG024.1] |
III-A-3. Les Post-It techniques (orange)▲
En plus des Post-It généraux jaunes et des Post-It détaillés bleus, l'équipe a écrit des Post-It techniques orange. Ces derniers définissent des règles techniques, qui n'intéressent pas particulièrement Claire (la cliente), relatives aux mécanismes mis en œuvre au sein de l'application. Plus concrètement, les Post-It techniques (orange) concernent des points spécifiques liés à Java, ou à la base de données, ou au réseau, etc.
Le Post-It orange ainsi créé est le suivant :
[Post-It RG024.2] |
III-A-4. Le cahier des charges modifié▲
Lorsque tous les Post-It sont écrits, John (le développeur) les prend en photos avec son « iPhone » et les sauvegarde sur le réseau, dans un dossier réservé au projet de la boutique.
Une fois que tous les Post-It sont écrits, et présentés sous forme de tableau comme dans cet article (cf. ci-dessus), il devient très simple de les intégrer (reporter) dans le cahier des charges. Les Post-It ne seront utilisés qu'en guise de support de travail facile à manipuler.
Bien entendu, si on ne se limite pas au sous-ensemble de fonctionnalités de génération de mot de passe et de cryptage, il faut créer de nombreux Post-It. Il faut donc mettre à jour le cahier des charges de manière conséquente.
Pour finir, l'équipe agrafe les Post-It bleus et orange aux Post-It jaunes. Cela permet de les avoir facilement à portée de main. Bien entendu, chaque développeur peut consulter le cahier des charges, mis à jour, sur le réseau.
III-B. Premier temps (T1) : écriture des interfaces▲
Chaque membre de l'équipe choisit un (ou plusieurs) Post-It à traiter sur le « dashboard ». Dans le cadre de cet article, l'illustration va se limiter aux Post-It présentés ci-dessus. Disons que Julie prend le Post-It « RG023 » et que Sébastien prend le Post-It « RG024 ». Quant à John, il s'occupe d'un Post-It qui n'est pas présenté dans cet article.
Conformément aux pratiques de « Green Soft », chaque développeur colle une gommette, à sa couleur, sur le Post-It dont il a pris possession.
|
[Post-It RG023] |
|
[Post-It RG024] |
Pour commencer, Julie crée l'interface « PasswordGenerator » correspondant au Post-It « RG023 » et y ajoute la méthode « generate() ». Elle documente son code en recopiant les numéros de Post-It. L'opération ne dure que quelques minutes.
package
fr.chiencopain.boutique.service.credentials;
/**
* Outil de generation de mot de passe.
*
* REGLE RG023
*
*
@author
Julie
*
*/
public
interface
PasswordGenerator {
/**
* Genere un mot de passe.
*
* REGLE RG023
*
*
@return
*/
String generate
(
);
}
Pour bien faire, Julie crée aussi la classe « DefaultPasswordGenerator » qui servira d'implémentation pour le service qu'elle vient de définir.
package
fr.chiencopain.boutique.service.credentials;
/**
* Outil de generation de mot de passe.
*
* REGLE RG023, RG023.1, RG023.2
*
*
@author
Julie
*
*/
public
class
DefaultPasswordGenerator implements
PasswordGenerator {
/**
* REGLE RG023, RG023.1, RG023.2
*
*
{@inheritDoc}
*/
public
String generate
(
) {
// TODO Cette methode n'est pas encore developpee.
throw
new
UnsupportedOperationException
(
"Cette methode n'est pas encore developpee."
);
}
}
Julie crée la classe « DefaultPasswordGenerator » de sorte qu'elle compile mais elle ne remplit pas les méthodes.
Finalement, Julie indique sur le Post-It que sa partie est réalisée. Pour simplifier le travail de la personne qui prendra le relais (cf. plus bas), Julie ajoute quelques remarques au verso des Post-It.
|
[Post-It RG023] RECTO |
|
[Post-It RG023] VERSO |
|
[Post-It RG023.1] VERSO |
|
[Post-It RG023.2] VERSO |
Le Post-It peut retourner dans le « sprint backlog » (la colonne de gauche du « dashboard »).
De son côté, Sébastien réalise un travail, équivalent à celui de Julie, pour le Post-It « RG024 ». Il commence par créer l'interface « Encryptor ».
package
fr.chiencopain.boutique.util.encryption;
/**
* Outil de cryptage.
*
* REGLE RG024
*
*
@author
Sebastien
*
*/
public
interface
Encryptor {
/**
* Crypte le message passe en parametre.
<
br/
>
*
* REGLE RG024
*
*
@param
message
*
@return
*/
String encrypt
(
String message);
}
Ensuite il crée l'implémentation vide « MD5Encryptor » qui recevra le code pour le cryptage MD5.
package
fr.chiencopain.boutique.util.encryption;
/**
* Outil de cryptage.
*
* REGLE RG024, RG024.1
*
*
@author
Sebastien
*
*/
public
class
MD5Encryptor implements
Encryptor {
/**
* REGLE RG024, RG024.1
*
*
{@inheritDoc}
*/
public
String encrypt
(
String message) {
// TODO Cette methode n'est pas encore developpee.
throw
new
UnsupportedOperationException
(
"Cette methode n'est pas encore developpee."
);
}
}
Puis, comme Julie, il met à jour ses Post-It en indiquant son avancement.
|
[Post-It RG024] RECTO |
|
[Post-It RG024] VERSO |
|
[Post-It RG024.1] VERSO |
|
[Post-It RG024.2] VERSO |
III-C. Premier reporting▲
À partir du code source ainsi écrit, ne comportant pour l'instant que des interfaces, on peut générer un peu de documentation, et notamment des rapports.
Dans la configuration du projet Maven (cf. pom.xml en annexes), j'ai inclus plusieurs plugins spécialisés dans le reporting. Deux d'entre eux vont immédiatement servir à Michel (le chef de projet) bien que peu d'éléments aient été réalisés.
D'abord le plugin « Tag list » permet de répertorier toutes les références aux règles dans le code ainsi que les travaux (programmés) restant à faire à ce stade.
Ensuite, le plugin « Cobertura » mesure la couverture du code (c'est-à-dire la quantité de tests). À ce stade, les résultats indiquent en toute logique un score de zéro.
Note : Ces données peuvent être consultées tout au long du projet. Il n'est pas nécessaire d'attendre que les phases successives de « 3T » soient terminées, d'autant que plusieurs Post-It, dans des phases différentes, peuvent être traités simultanément, comme le laisse deviner le « dashboard » suivant.
III-D. Deuxième temps (« T2 ») : écriture des tests▲
Maintenant que plusieurs Post-It ont franchi le cap de « T1 » (c'est-à-dire le premier temps), les développeurs qui piochent dans le « sprint backlog » peuvent choisir entre des Post-It « vierges » et des Post-It à faire évoluer vers « T2 ». Bien évidemment, c'est ce second choix que va illustrer cet article.
Disons que Julie prend en charge l'écriture des tests pour les Post-It « RG024.x » et que John s'occupe de « RG023.x ». De son côté, Sébastien travaille sur d'autres Post-It, non présentés dans cet article, ou alors il est en RTT, ou encore il prend une pause. Bref il fait autre chose.
Bien que ce ne soit pas prohibé dans « 3T », il vaut mieux que les développeurs ne travaillent pas sur deux temps consécutifs d'un même Post-It. Plus concrètement, si Julie écrit l'interface d'un Post-It (i.e. « T1 ») alors c'est mieux si elle ne s'occupe pas de la rédaction des tests (i.e. « T2 »).
Pour commencer, comme lors de « T1 » et toujours en accord avec les habitudes chez « Green Soft », les développeurs apposent des gommettes à leurs couleurs sur les Post-It qu'ils prennent en charge.
|
[Post-It RG023] RECTO |
|
[Post-It RG024] RECTO |
John prend donc en charge les Post-It « RG023.x » pour lesquels il doit écrire les tests unitaires. Globalement, il suffit de se concentrer sur les deux Post-It bleus « RG023.1 » et « RG023.2 ».
package
fr.chiencopain.boutique.service.credentials;
import
static
junit.framework.Assert.assertEquals;
import
static
junit.framework.Assert.assertNotNull;
import
static
junit.framework.Assert.assertTrue;
import
java.util.regex.Matcher;
import
java.util.regex.Pattern;
import
org.junit.Before;
import
org.junit.Test;
/**
* Tests de DefaultPasswordGenerator.
*
* REGLE RG023, RG023.1, RG023.2
*
*
@author
John
*
*/
public
class
DefaultPasswordGeneratorTest {
/**
* PasswordGenerator
*/
PasswordGenerator passwordGenerator;
/**
* DefaultPasswordGenerator
*/
@Before
public
void
doBefore
(
) {
passwordGenerator =
new
DefaultPasswordGenerator
(
);
}
/**
* Le mot de passe genere sera compose de 8 digits.
<
br/
>
*
* REGLE RG023.1
<
br/
>
*
* RESULT : length = 8
<
br/
>
*
* Exemple a : football
<
br/
>
* Exemple b : voitures
*/
@Test
public
void
testGenerate_RG023_1
(
) {
// Param
final
int
tailleAttendue =
8
;
// Appel
final
String password =
passwordGenerator.generate
(
);
// Tests
assertNotNull
(
password);
assertEquals
(
tailleAttendue, password.length
(
));
}
/**
* Le mot de passe genere sera compose des 26 lettres de l'alphabet, en
* majuscules et/ou en minuscules, et des chiffres de 0 à 9.
<
br/
>
*
* REGLE RG023.2
<
br/
>
*
* Exemple a : abcd1234
<
br/
>
* Exemple b : Hello012
*/
@Test
public
void
testGenerate_RG023_2
(
) {
final
String lettresAutoriseesRegex =
"[a-zA-Z0-9]+"
;
// Appel
final
String password =
passwordGenerator.generate
(
);
// Tests
assertNotNull
(
password);
assertTrue
(
verifyRegex
(
lettresAutoriseesRegex, password));
}
/**
* Verifie si le message "match" la regex.
*
*
@param
regex
*
@param
message
*
@return
true si ca match, false sinon.
*/
private
boolean
verifyRegex
(
String regex, String message) {
final
Pattern pattern =
Pattern.compile
(
regex);
final
Matcher matcher =
pattern.matcher
(
message);
return
matcher.matches
(
);
}
}
Lorsqu'on écrit des tests, il est recommandé de suivre toujours le même formalisme pour faciliter la lecture. Dans le cadre de « 3T » il est plus particulièrement conseillé de suivre la méthode « triple A » ou AAA, de l'anglais « Arrange-Act-Assert » (traduction personnelle : « Préparer-Agir-Tester »), et à propos de laquelle on peut lire quelques lignes sur le Web à l'adresse http://www.arrangeactassert.com/why-and-what-is-arrange-act-assert/ ou encore sur http://c2.com/cgi/wiki?ArrangeActAssert et surtout sur le blog de William C. Wake.
Lorsqu'il lance les tests JUnit depuis Eclipse, John constate qu'ils sont tous rouges, ce qui est tout à fait normal ; c'est le résultat attendu.
John n'a plus qu'à indiquer son avancement et/ou ses remarques sur les Post-It, puis les remettre dans le « sprint backlog ».
|
[Post-It RG023] RECTO |
|
[Post-It RG023] VERSO |
|
[Post-It RG023.1] VERSO |
|
[Post-It RG023.2] VERSO |
De son côté, Julie écrit les tests pour les règles « RG024.x », c'est-à-dire le Post-It bleu « RG024.1 » et le Post-It orange « RG024.2 ». C'est relativement rapide puisqu'il suffit, là encore, de recopier les Post-It.
package
fr.chiencopain.boutique.util.encryption;
import
static
junit.framework.Assert.assertEquals;
import
static
junit.framework.Assert.assertNotNull;
import
org.junit.Before;
import
org.junit.Test;
/**
* Tests de MD5Encryptor : Le systeme peut crypter un mot de passe.
*
* REGLE RG024, RG024.1, RG024.2
*
*
@author
Julie
*
*/
public
class
MD5EncryptorTest {
/**
* Encryptor
*/
private
Encryptor encryptor;
/**
* MD5Encryptor
*/
@Before
public
void
doBefore
(
) {
encryptor =
new
MD5Encryptor
(
);
}
/**
* Les mots de passe seront cryptes à l'aide de l'algorithme MD5.
<
br/
>
*
* REGLE RG024.1-a
<
br/
>
*
* PARAM password = "football"
<
br/
>
* RESULT "37b4e2d82900d5e94b8da524fbeb33c0"
*/
@Test
public
void
testEncrypt_RG024_1a
(
) {
// PARAM
final
String password =
"football"
;
final
String passwordCrypteAttendu =
"37b4e2d82900d5e94b8da524fbeb33c0"
;
// Appel
doTestEncrypt
(
password, passwordCrypteAttendu);
}
/**
* Les mots de passe seront cryptes à l'aide de l'algorithme MD5.
<
br/
>
*
* REGLE RG024.1-b
<
br/
>
*
* PARAM password = "Hello012"
<
br/
>
* RESULT "00dd4826e068dad5be5e95ef692f62e6"
*/
@Test
public
void
testEncrypt_RG024_1b
(
) {
// PARAM
final
String password =
"Hello012"
;
final
String passwordCrypteAttendu =
"00dd4826e068dad5be5e95ef692f62e6"
;
// Appel
doTestEncrypt
(
password, passwordCrypteAttendu);
}
/**
* On ne peut pas crypter un mot de passe vide. Si on essaie, ça doit lancer
* une erreur.
<
br/
>
*
* REGLE RG024.2-a
<
br/
>
*
* PARAM password = ""
<
br/
>
* RESULT IllegalArgumentException
*/
@Test
(
expected =
IllegalArgumentException.class
)
public
void
testEncrypt_RG024_2a
(
) {
// PARAM
final
String password =
""
;
final
String passwordCrypteAttendu =
"..."
;
// Appel
doTestEncrypt
(
password, passwordCrypteAttendu);
}
/**
* On ne peut pas crypter un mot de passe vide. Si on essaie, ça doit lancer
* une erreur.
<
br/
>
*
* REGLE RG024.2-b
<
br/
>
*
* PARAM password = null
<
br/
>
* RESULT IllegalArgumentException
*/
@Test
(
expected =
IllegalArgumentException.class
)
public
void
testEncrypt_RG024_2b
(
) {
// PARAM
final
String password =
null
;
final
String passwordCrypteAttendu =
"..."
;
// Appel
doTestEncrypt
(
password, passwordCrypteAttendu);
}
/**
* REGLE RG024.x
*/
private
void
doTestEncrypt
(
String password, String passwordCrypteAttendu) {
// Appel
final
String passwordCrypte =
encryptor.encrypt
(
password);
// Tests
assertNotNull
(
passwordCrypte);
assertEquals
(
passwordCrypteAttendu, passwordCrypte);
}
}
Comme John, Julie constate que ses tests passent tous au rouge lorsqu'elle lance JUnit depuis Eclipse.
À son tour, Julie met également à jour ses Post-It.
|
[Post-It RG024] RECTO |
|
[Post-It RG024] VERSO |
|
[Post-It RG024.1] VERSO |
|
[Post-It RG024.2] VERSO |
III-E. Deuxième reporting▲
Durant le « sprint », Michel (le chef de projet) consulte régulièrement les métriques du projet. Chez « Green Soft », l'outil d'intégration continue est « Hudson ». Il est configuré pour compiler l'application, à l'aide de Maven, dix minutes après chaque « commit » dans gestionnaire de sources Subversion (SVN). Hudson est également réglé de sorte qu'il génère la documentation (reporting inclus) tous les soirs. Ainsi Michel peut prendre connaissance de l'avancement du projet chaque matin.
L'intervalle de dix minutes avant de lancer le « build » Maven permet aux développeurs de corriger des petites inattentions ou des oublis de fichier par exemple.
Romain Linsolas nous propose un très bon article à propos de « L'intégration Continue avec Hudson » sur le site de developpez.com à l'adresse : https://linsolas.developpez.com/articles/hudson/Intégration Continue avec Hudson
Hudson est un produit d'Oracle (qui a acheté Sun). Le site d'Hudson est visible à l'adresse : http://hudson-ci.org/Hudson
Pour commencer, Michel voit que la liste des tags a évolué. Les références, déjà indiquées dans les interfaces, ont été reportées dans les classes de test.
Il constate ensuite que la couverture de code, qui était de zéro pour cent en « T1 », s'est améliorée. Dans l'exemple, Cobertura donne une note de 100 %, ce qui est excellent.
Un score de 100 % est rarement atteint. Peu d'équipes ont les moyens d'y arriver sur des projets complexes. Une des forces de « 3T » est d'encourager un tel objectif.
Enfin, Michel peut consulter la liste des tests ayant été écrits. Le rapport indique le nombre et l'emplacement des tests. À la fin de « T2 », tous les nouveaux tests doivent échouer (i.e. être rouges). Ce n'est qu'à la fin de « T3 » qu'ils seront verts.
Comme aucun nouveau « vrai code » n'a été écrit, les anciens tests ne doivent pas changer de couleur.
III-F. Troisième temps (« T3 ») : écriture du vrai code▲
Une fois de plus, et pour la dernière fois, les développeurs piochent des Post-It dans le « sprint backlog ». Bien entendu, l'illustration va se faire sur les Post-It « RG023 » et « RG024 ». Disons que Julie s'occupe des règles « RG023.x » et que John choisit « RG024.x ». Sébastien, quant à lui, est encore en vacances ou s'occupe d'autres Post-It, etc.
|
[Post-It RG023] RECTO |
|
[Post-It RG024] RECTO |
Dans l'exemple, le Post-It « RG023 » aura été pris en charge par Julie et John uniquement. Le Post-It « RG024 » aura été traité par tous les membres de l'équipe. Julie aura donc travaillé deux fois sur « RG023 », mais sur des temps (de « 3T ») non successifs.
Julie commence donc à coder la classe « DefaultPasswordGenerator » qu'elle avait elle-même initialisée lors de « T1 ». Elle programme ses Post-It dans l'ordre. Tout d'abord, elle doit générer un mot de passe de huit caractères.
package
fr.chiencopain.boutique.service.credentials;
import
java.util.Random;
/**
* Outil de generation de mot de passe.
*
* REGLE RG023, RG023.1, RG023.2
*
*
@author
Julie (T1 et T3)
*
*/
public
class
DefaultPasswordGenerator implements
PasswordGenerator {
/**
* REGLE RG023, RG023.1, RG023.2
*
*
{@inheritDoc}
*/
public
String generate
(
) {
final
StringBuilder sb =
new
StringBuilder
(
);
// REGLE RG023.1
for
(
int
i =
0
; i <
8
; i++
) {
final
char
digit =
'
\0
'
;
sb.append
(
digit);
}
return
sb.toString
(
);
}
}
Contente d'elle, Julie lance une première batterie de tests. Elle constate que la règle « RG023.1 » a correctement passé le test. Elle peut donc passer à la suite (i.e. la règle « RG023.2 ») qui reste rouge.
Julie aime tester au fur et à mesure. Certains développeurs préfèrent tout programmer d'un coup et, donc, tout tester d'un coup. Ce n'est pas le cas de Julie. Dans le cadre de « 3T », il est recommandé de laisser les tests guider les développements, et donc de tester au fur et à mesure.
Maintenant que le générateur produit un mot de passe de huit digits, Julie doit faire en sorte que les caractères soient choisis parmi les 26 lettres de l'alphabet et/ou les chiffres.
/**
* Outil de generation de mot de passe.
*
* REGLE RG023, RG023.1, RG023.2
*
*
@author
Julie (T1 et T3)
*
*/
public
class
DefaultPasswordGenerator implements
PasswordGenerator {
/**
* Caracteres autorises.
*
* REGLE RG023.2
*/
private
static
final
String CARACTERES_AUTORISES =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
;
/**
* REGLE RG023, RG023.1, RG023.2
*
*
{@inheritDoc}
*/
public
String generate
(
) {
final
StringBuilder sb =
new
StringBuilder
(
);
// REGLE RG023.1
for
(
int
i =
0
; i <
8
; i++
) {
// REGLE RG023.2
final
char
digit =
generateOneDigit
(
);
sb.append
(
digit);
}
return
sb.toString
(
);
}
/**
* Selection un caractere au hasard dans la liste des caracteres autorises.
*
* REGLE RG023.2
*
*
@return
un caractere au hasard.
*/
private
char
generateOneDigit
(
) {
final
Random random =
new
Random
(
);
final
int
position =
random.nextInt
(
CARACTERES_AUTORISES.length
(
));
final
char
digit =
CARACTERES_AUTORISES.charAt
(
position);
return
digit;
}
}
Une fois satisfaite, Julie relance les tests. Elle constate, comme prévu, que tous les tests passent au vert.
Julie peut donc, en toute bonne foi, se dire qu'elle a terminé la fonctionnalité. Par acquit de conscience elle lance aussi les tests des fonctionnalités pouvant être impactées par son code (ici, il n'y en a aucune) pour vérifier qu'elle n'a pas engendré de régression.
Chez « Green Soft », le logiciel Hudson est configuré pour lancer régulièrement l'ensemble des tests de l'application, pour vérifier complètement la non-régression, ce qui peut prendre du temps. Les développeurs peuvent donc se concentrer sur leurs périmètres.
Si tout est bon, elle peut mettre à jour ses Post-It. Cette fois, contrairement à « T1 » et « T2 », le Post-It ne retourne pas dans le « sprint backlog », mais va dans la colonne des fonctionnalités terminées.
|
[Post-It RG023] RECTO |
|
[Post-It RG023] VERSO |
|
[Post-It RG023.1] VERSO |
|
[Post-It RG023.2] VERSO |
De son côté, John travaille sur « RG024.x ». Contrairement à Julie, qui traite les Post-It par ordre numérique, John préfère commencer par les Post-It techniques (i.e. orange). Il commence donc son développement par le Post-It « RG024.2 ».
package
fr.chiencopain.boutique.util.encryption;
/**
* Outil de cryptage.
*
* REGLE RG024, RG024.1
*
*
@author
Sebastien, John
*
*/
public
class
MD5Encryptor implements
Encryptor {
/**
* REGLE RG024, RG024.1
*
*
{@inheritDoc}
*/
public
String encrypt
(
String message) {
// REGLE RG024.2
if
(
message ==
null
||
message.length
(
) ==
0
) {
throw
new
IllegalArgumentException
(
"Le param 'message' ne peut pas etre vide."
);
}
// TODO Cette methode n'est pas encore developpee.
throw
new
UnsupportedOperationException
(
"Cette methode n'est pas encore developpee."
);
}
}
John lance ses tests. Il constate que les tests « RG024.2-x » passent au vert, mais que les autres tests, pour lesquels il n'a encore rien programmé, restent rouges.
John passe à la suite : le cryptage du mot de passe en MD5.
Un petit rebondissement se produit dans cette histoire ; Vanessa (la secrétaire sexy) entre dans le bureau des développeurs. Elle vient discuter (cf. conversations en annexes) des derniers ragots avec Julie. Automatiquement, la concentration de John baisse dramatiquement et cela va se ressentir sur la qualité de son code.
|
|
|
/**
* Outil de cryptage.
*
* REGLE RG024, RG024.1
*
*
@author
Sebastien, John
*
*/
public
class
MD5Encryptor implements
Encryptor {
/**
* MD5
*
* REGLE RG024.1
*/
public
final
static
String ALGO_MD5 =
"MD55"
;
/**
* REGLE RG024, RG024.1
*
*
{@inheritDoc}
*/
public
String encrypt
(
String message) {
// REGLE RG024.2
if
(
message ==
null
||
message.length
(
) ==
0
) {
throw
new
IllegalArgumentException
(
"Le param 'message' ne peut pas etre vide."
);
}
// REGLE RG024.1
try
{
final
byte
[] uniqueKey =
message.getBytes
(
);
final
byte
[] hash =
MessageDigest.getInstance
(
ALGO_MD5).digest
(
uniqueKey);
final
StringBuilder sb =
new
StringBuilder
(
);
for
(
int
i =
0
; i <
hash.length; i++
) {
String hex =
Integer.toHexString
(
hash[i]);
if
(
hex.length
(
) ==
1
) {
sb.append
(
'0'
);
sb.append
(
hex.charAt
(
hex.length
(
) -
1
));
}
else
{
sb.append
(
hex.substring
(
hex.length
(
) -
2
));
}
}
final
String encrypt =
sb.toString
(
);
return
encrypt;
}
catch
(
NoSuchAlgorithmException e) {
return
null
;
}
}
}
Quand John relance ses tests, il découvre qu'ils sont restés rouges.
Que se passe-t-il ? John, perturbé par la présence de la charmante Vanessa, a fait une faute de frappe. Il a ainsi écrit « MD55 » alors qu'il voulait utiliser l'algorithme « MD5 » avec un seul « 5 ». L'erreur est simple à corriger, mais elle serait très probablement passée inaperçue s'il n'y avait pas eu de test pour la détecter.
Une petite correction, d'une demi- seconde, devrait suffire.
/**
* MD5
*
* REGLE RG024.1
*/
public
final
static
String ALGO_MD5 =
"MD5"
;
Cette fois, les tests deviennent bien (tous) verts. Il s'en est fallu de peu…
John lance les autres tests de l'application pour s'assurer qu'il n'a pas, lui non plus, apporté de régression. Comme tout est bon, il peut légitimement penser que sa fonctionnalité est prête. Il ne reste plus qu'à compléter ses Post-It.
|
[Post-It RG024] RECTO |
|
[Post-It RG024] VERSO |
|
[Post-It RG024.1] VERSO |
|
[Post-It RG024.2] VERSO |
Je me suis attaché à employer une écriture et un style différents pour chaque développeur intervenant sur les Post-It. Pour les débuts de « 3T » sur la boutique, chacun se crée ses propres habitudes.
III-G. Troisième reporting▲
Comme lors des temps précédents, Michel peut consulter la liste des tags du code. Il constate que la liste des choses à faire s'est vidée. Il peut en profiter pour vérifier le bon report des numéros de règle dans le code.
Michel peut également consulter le rapport Surefire (JUnit) qui indique désormais que tous les tests sont OK. À ce stade, il est en droit de penser, puisqu'il a utilisé « 3T » que le développement de l'application est terminé.
En vérifiant le rapport Cobertura, Michel (le chef de projet) constate que le niveau de couverture du code a légèrement baissé.
Immédiatement, un peu inquiet, il clique pour voir les détails. Le rapport lui indique très précisément les points faibles dans le code.
Ici, ce n'est pas difficile de revenir à 100 %. Michel demandera simplement à John de compléter les tests, voire de créer un Post-It technique (orange) additionnel, dès qu'il aura un peu de temps.
Globalement, Michel est très content, car le développement des fonctionnalités a été hyper rapide. En effet, les développeurs ont pu s'appuyer sur les Post-It la plupart du temps et avancer par itérations, en construisant l'application sur des bases de plus en plus solides. Les tests ont permis aux membres de l'équipe d'avoir une confiance élevée dans les codes produits. Les reportings ont permis à Michel de suivre l'avancement des travaux en fournissant des métriques fiables que Michel peut remonter à sa hiérarchie et au client.
III-H. Inspection surprise▲
Laurent (l'architecte) profite d'un moment de flottement, en fin de « sprint », pour improviser une revue de code. En temps normal, les développeurs s'autoorganisent déjà dans ce sens, mais Laurent souhaite constater/vérifier lui-même l'impact de « 3T » sur la qualité du code. Il a quelques craintes à propos de la méthode. Tout semble si simple qu'il a peur que les développeurs se soient laissé entrainer par cette apparente simplicité pour « bâcler » le travail. En outre, il sait que Michel (le chef de projet) se sent principalement concerné par les tests et la qualité visible de l'application.
Chez « Green Soft », on utilise les logiciels « Check style » et « PMD » pour mesurer la qualité du code. Combinés avec une revue manuelle du code, ces outils fournissent de bonnes indications. Pour sa part, Laurent travaille principalement avec « Check style » directement depuis Eclipse. Michel, quant à lui, préfère consulter les rapports édités depuis Maven.
Laurent s'installe donc avec les développeurs, à tour de rôle, et active les vérifications « Check style » lorsqu'elles n'étaient pas déjà activées. En tout, il ne trouve qu'une vingtaine de petites violations aux règles « Check Style » de « Green Soft » (mots clés dans le mauvais ordre, paramètres non déclarés finaux, Javadoc incomplète, etc.), qu'il fait corriger directement par les développeurs concernés. C'est plutôt pas mal.
Le code source, dans le fichier Zip, est déjà corrigé.
Globalement, Laurent n'a rien à dire, à part les détails indiqués ci-dessus, car le principe d'écriture de « 3T » conduit naturellement à écrire du code propre, à proscrire les duplications, à avoir une forte couverture de test, à séparer les responsabilités, à respecter les standards, etc. En fait, puisque « 3T » apporte un processus simple où les étapes sont décomposées et guident les développeurs, ces derniers peuvent se concentrer sur la qualité de leurs travaux, ce qui n'est pas toujours le cas dans des projets classiques.
III-I. La qualification▲
Arrivant en fin de projet (et/ou de « sprint »), Bernard (le responsable de la Qualif) doit s'assurer que le produit fabriqué est conforme aux attentes du client. Il a reçu les versions successives du cahier des charges et se tient prêt à vérifier les livrables.
Par habitude, Bernard sait qu'il va rejeter la première (et même les suivantes) tentative de livraison après seulement quelques heures de test. En effet, il trouve toujours quelque chose à redire sur la conformité du produit. Pour se faire, il teste scrupuleusement tous les points spécifiés dans le cahier des charges.
Le plus dur de son travail consiste à mettre en place les jeux de test nécessaires, à dérouler lesdits tests, puis à consigner les anomalies dans Mantis (l'outil de « bug tracking » open source utilisé par « Green Soft »). D'ailleurs, Bernard en a ras le bol de créer des fiches Mantis à longueur de journée. Il aimerait bien se concentrer sur la mise en place de tests puissants, allant bien au-delà des besoins exprimés, et qui contribueraient à asseoir la réputation de « Green Soft ».
Quelle va donc être sa surprise lorsque, après avoir lancé ses batteries de tests, Bernard ne détecte aucune anomalie ? Ça n'est jamais arrivé jusque-là. Il croit d'abord à une mauvaise manipulation et relance entièrement sa série de tests. Mais là encore, rien à signaler ! Interloqué, il appose son tampon de validation et envoie un email de félicitations au chef de projet (Michel) et au DSI.
En réalité, lorsque « 3T » est appliqué sur un projet, son principe premier veut que les développements soient réalisés en partant des tests, eux-mêmes écrits à partir du cahier des charges. Or il est probable que les tests écrits par l'équipe de développement soient très proches de ceux de Bernard.
IV. Évolutions▲
Nous avons constaté que « 3T » est efficace immédiatement, mais « 3T » est également intéressante sur le long terme. Pour le comprendre, revenons à « la Boutique du Chien-Copain », un an plus tard.
Les choses ont bien changé depuis la mise en production de « la Boutique du Chien-Copain ». Environ un an s'est écoulé. L'enseigne a ouvert quinze nouveaux magasins en France, en Suisse et en Belgique. La société canine devient une multinationale. Et les projets sont nombreux. D'ailleurs, l'un des premiers projets que « Chien-Copain » veut lancer est une évolution (dans la suite on parlera de « v2 ») de la boutique en ligne. La collaboration avec « Green Soft » ayant été fructueuse, c'est naturellement à Michel (le chef de projet de la boutique chez « Green Soft ») que cette nouvelle version a été directement confiée.
De son côté, la Web Agency « Green Soft » s'est également agrandie. Elle a remporté de nombreux contrats en France et en Europe. L'utilisation de « 3T » initiée sur « la Boutique du Chien-Copain » est maintenant une pratique de plus en plus orchestrée, au moins sur les nouveaux projets.
IV-A. Les nouveaux Post-It▲
Claire (la cliente) a une liste de nouvelles demandes qu'elle souhaite voir développées en « v2 ». Dans le cadre de cet article, on ne va évidemment illustrer que les besoins liés à la génération et le cryptage de mot de passe, pour faire suite aux chapitres précédents.
Tout d'abord, Claire souhaite que les mots de passe générés soient de taille variable. Pour des raisons de sécurité, elle veut également que les mots de passe générés ne soient plus uniquement composés de lettres et/ou de chiffres, mais qu'ils contiennent aussi des caractères de ponctuation. Enfin, Claire a découvert, en écoutant l'excellent podcast « Techno IT »podcast Techno IT que le cryptage « SHA-1 » a remplacé le « MD5 ». Bien qu'elle n'ait pas compris les raisons de ce changement, elle souhaite que « Green Soft » l'accompagne dans ce sens.
De nouveau, Michel (le chef de projet) réunit son équipe pour analyser le nouveau cahier des charges. Après discussion avec Claire, l'équipe part sur les Post-It suivants. Les Post-It « 023.3 », « 023.4 » et « 024.3 » sont nouveaux.
|
[Post-It RG023.3] |
|
[Post-It RG023.4] |
|
[Post-It RG024.2] |
|
[Post-It RG024.3] |
De manière générale, quand le sujet d'un Post-It évolue, on peut soit mettre à jour le Post-It, en en gérant les versions successives, soit « annuler » le Post-It et le remplacer par un nouveau. C'est donc ce second choix qui a été retenu chez « Green Soft ». Les Post-It « 023.1 », « 023.2 » et « 024.1 » sont marqués comme annulés.
|
[Post-It RG023.1] |
|
[Post-It RG023.2] |
|
[Post-It RG024.1] |
Les Post-It (fonctionnels) jaunes de la « v1 », quant à eux, sont simplement remplacés par de nouveaux Post-It jaunes pour la « v2 ». Les nouveaux Post-It sont prêts à suivre un nouveau « processus 3T » couplé à Scrum.
|
[Post-It RG023] v2 |
|
[Post-It RG024] v2 |
IV-B. Évolution de l'équipe▲
En une année, l'équipe de développement a beaucoup évolué. Tout d'abord, Laurent (l'architecte) et Julie se sont mariés. Une grande fête a été organisée dans les bureaux de « Green Soft » pour célébrer l'événement. Une chose en entrainant une autre, Julie est désormais en congé maternité et ne participera donc pas au développement des évolutions de « la boutique du Chien-Copain ». John (le développeur barbu) travaille désormais en Belgique, en tant que « team leader » sur un projet du gouvernement dont « Green Soft » a remporté l'appel d'offres.
De l'équipe initiale, il ne reste donc plus que Sébastien. Ce dernier a rapidement été rejoint par William et Nathalie, puis par Luc un peu plus tard.
|
|
|
|
William et Nathalie reviennent d'un projet Web, pris en charge par « Green Soft », chez un opérateur de télécom, où ils travaillaient en « pair programming » dans le cadre d'une méthodologie « XP ». Luc, quant à lui, a été remercié d'un autre projet dans lequel il s'ennuyait. Michel, avec qui il était resté en contact, lui a proposé de rejoindre l'équipe pour découvrir les bienfaits de « 3T » et redécouvrir des bases de travail motivantes.
Un point intéressant des TDD, est la capacité de prise en main rapide que la méthode offre aux nouveaux développeurs du projet. En effet, puisque les tests sont documentés et guident le code source des programmes, il suffit de repartir des tests pour comprendre ce que fait le programme. Les développeurs peuvent donc s'appuyer sur leurs compétences techniques pour s'immerger dans le fonctionnel de l'application. En outre, puisque « 3T » s'inspire directement du cahier des charges, la démarche est d'autant plus simplifiée.
Dans l'histoire, Sébastien est le seul développeur restant à posséder une connaissance à la fois technique et fonctionnelle de « la Boutique du Chien-Copain ». Son rôle ne va pas être de transmettre cette connaissance, mais de guider les nouveaux membres de l'équipe à travers les TDD et « 3T » pour qu'ils accèdent progressivement au même niveau de compétence (cf. conversations en annexes).
IV-C. Les trois temps▲
Sans surprise, puisque c'est l'objet de cet article, les développements de la « v2 » de la boutique en ligne vont suivre les trois temps de « 3T ».
Cette partie ne sera pas illustrée à chaque étape à l'aide de Post-It scannés. Cela occupe trop de place et prend (en toute franchise) trop de temps dans le logiciel d'imagerie. Seuls les scans des Post-It finals (c'est-à-dire après « T3 ») seront présentés plus bas.
Les phases d'évolution de l'application diffèrent légèrement des phases de création dans la mesure où il faut revenir (c'est-à-dire annuler,modifier) sur l'existant pour l'adapter aux nouvelles demandes.
IV-C-1. Les interfaces (T1)▲
Dans un premier temps, disons que Sébastien s'occupe des interfaces de génération et de cryptage des mots de passe. Il n'y a pas grand-chose à faire. Plus exactement, il n'y a rien (ou presque) du tout à faire au niveau des interfaces Java puisque les contrats de service n'ont pas changé.
/**
* Outil de generation de mot de passe.
*
* REGLE RG023
*
*
@author
Julie
*
*/
public
interface
PasswordGenerator {
/**
* Genere un mot de passe.
*
* REGLE RG023
*
*
@return
Un mot de passe genere.
*/
String generate
(
);
}
/**
* Outil de cryptage.
*
* REGLE RG024
*
*
@author
Sebastien
*
*/
public
interface
Encryptor {
/**
* Crypte le message passe en parametre.
<
br/
>
*
* REGLE RG024
*
*
@param
message
* Le message a crypter.
*
@return
une version cryptee du message.
*/
String encrypt
(
String message);
}
En revanche, on peut créer une classe vide spécifique pour l'implémentation du cryptage SHA-1 et une classe vide pour la nouvelle implémentation du générateur de mot de passe. À cette étape, Sébastien ne doit pas modifier le code plus que ça.
package
fr.chiencopain.boutique.service.credentials;
/**
* Outil de generation de mot de passe.
*
* REGLE RG023
*
*
@author
Sébastien
*
*/
public
class
AdvancePasswordGenerator implements
PasswordGenerator {
/**
* REGLE RG023
*
*
{@inheritDoc}
*/
public
final
String generate
(
) {
// TODO Cette methode n'est pas encore developpee.
throw
new
UnsupportedOperationException
(
"Cette methode n'est pas encore developpee."
);
}
}
package
fr.chiencopain.boutique.util.encryption;
/**
* Outil de cryptage.
*
* REGLE RG024
*
*
@author
Sebastien
*
*/
public
class
Sha1Encryptor implements
Encryptor {
/**
* REGLE RG024
*
*
{@inheritDoc}
*/
public
final
String encrypt
(
final
String message) {
// TODO Cette methode n'est pas encore developpee.
throw
new
UnsupportedOperationException
(
"Cette methode n'est pas encore developpee."
);
}
}
IV-C-2. Les tests (T2)▲
Durant ce deuxième temps, disons que Nathalie et William vont écrire, en « pair programming », les tests de « RG023 » et que Luc va s'occuper de « RG024 ».
Lorsqu'on écrit du code pour la première fois, c'est relativement simple puisqu'il suffit de partir de zéro. On est libre d'aller dans la direction qui nous intéresse sans contrainte. En revanche, lorsqu'on fait évoluer du code, comme c'est le cas ici, par ajout de nouvelles règles, il faut s'intégrer dans l'existant. L'objectif est de s'inspirer de ce que les développeurs précédents ont réalisé, tout en complétant/modifiant le code. Dans le cas présent, en ce qui concerne les tests unitaires et l'addition de nouveaux tests qui ressemblent aux anciens, cela se traduit par un peu de réorganisation, et notamment par de la factorisation et de l'héritage.
Conformément aux Post-It, certains tests sont annulés. Ils devraient donc être supprimés du code. Toutefois, dans la mesure où de nouvelles classes ont été prévues pour accueillir les évolutions, et que ces dernières (programmées ainsi) ne sont pas incompatibles avec l'existant, l'équipe décide de tout conserver. En outre, cela m'arrange pour l'illustration de cet article.
Nathalie et William vont donc créer une classe de test abstraite et réorganiser la classe existante pour qu'elle utilise la nouvelle classe.
package
fr.chiencopain.boutique.service.credentials;
import
java.util.regex.Matcher;
import
java.util.regex.Pattern;
/**
*
*
@author
Nathalie et William
*
*/
public
abstract
class
AbstractPasswordGeneratorTest {
/**
* Verifie si le message "match" la regex.
*
*
@param
regex
* la regex de controle.
*
@param
message
* le message a valider.
*
@return
true si ca match, false sinon.
*/
protected
final
boolean
verifyRegex
(
final
String regex, final
String message) {
final
Pattern pattern =
Pattern.compile
(
regex);
final
Matcher matcher =
pattern.matcher
(
message);
return
matcher.matches
(
);
}
}
/**
* Tests de DefaultPasswordGenerator.
*
* REGLE RG023, RG023.1, RG023.2
*
*
@author
John, puis Nathalie et William (v2)
*
*/
public
class
DefaultPasswordGeneratorTest extends
AbstractPasswordGeneratorTest {
/**
* PasswordGenerator
*/
private
PasswordGenerator passwordGenerator;
/**
* DefaultPasswordGenerator
*/
@Before
public
final
void
doBefore
(
) {
passwordGenerator =
new
DefaultPasswordGenerator
(
);
}
/**
* Le mot de passe genere sera compose de 8 digits.
<
br/
>
*
* REGLE RG023.1
<
br/
>
*
* RESULT : length = 8
<
br/
>
*
* Exemple a : football
<
br/
>
* Exemple b : voitures
*/
@Test
public
final
void
testGenerate_RG023_1
(
) {
// Param
final
int
tailleAttendue =
8
;
// Appel
final
String password =
passwordGenerator.generate
(
);
// Tests
assertNotNull
(
password);
assertEquals
(
tailleAttendue, password.length
(
));
}
/**
* Le mot de passe genere sera compose des 26 lettres de l'alphabet, en
* majuscules et/ou en minuscules, et des chiffres de 0 à 9.
<
br/
>
*
* REGLE RG023.2
<
br/
>
*
* Exemple a : abcd1234
<
br/
>
* Exemple b : Hello012
*/
@Test
public
final
void
testGenerate_RG023_2
(
) {
final
String lettresAutoriseesRegex =
"[a-zA-Z0-9]+"
;
// Appel
final
String password =
passwordGenerator.generate
(
);
// Tests
assertNotNull
(
password);
assertTrue
(
verifyRegex
(
lettresAutoriseesRegex, password));
}
}
package
fr.chiencopain.boutique.service.credentials;
import
static
junit.framework.Assert.assertNotNull;
import
static
junit.framework.Assert.assertTrue;
import
org.junit.Before;
import
org.junit.Test;
/**
* Tests de AdvancePasswordGenerator.
*
* REGLE RG023, RG023.3, RG023.4
*
*
@author
Nathalie et William
*
*/
public
class
AdvancePasswordGeneratorTest extends
AbstractPasswordGeneratorTest {
/**
* PasswordGenerator
*/
private
PasswordGenerator passwordGenerator;
/**
* AdvancePasswordGenerator
*/
@Before
public
final
void
doBefore
(
) {
passwordGenerator =
new
AdvancePasswordGenerator
(
);
}
/**
* Le mot de passe genere sera compose de 6 à 10 digits.
<
br/
>
*
* REGLE RG023.3
<
br/
>
* Test en boucle a cause du comportement aleatoire.
<
br/
>
*
* PARAM nbDigitMin = 6
<
br/
>
* PARAM nbDigitMax = 10
*
*/
@Test
public
final
void
testGenerate_RG023_3_boucle
(
) {
// Param
final
int
nbDigitMin =
6
;
final
int
nbDigitMax =
10
;
// Boucle car on cherche a tester plein de cas.
for
(
int
i =
0
; i <
1000
; i++
) {
// Appel
final
String password =
passwordGenerator.generate
(
);
// Tests
assertNotNull
(
password);
final
int
passwordLength =
password.length
(
);
assertTrue
(
nbDigitMin <=
passwordLength);
assertTrue
(
passwordLength <=
nbDigitMax);
}
}
/**
* Le mot de passe genere sera compose des 26 lettres en majuscules et/ou en
* minuscules, des chiffres et des ponctuations simples ou doubles.
<
br/
>
*
* REGLE RG023.2
<
br/
>
*
* Exemple a : abcd1234
<
br/
>
* Exemple b : Hello012
*/
@Test
public
final
void
testGenerate_RG023_4
(
) {
// Param
// regex : [a-zA-Z0-9,.'";:!?\-]+
final
String lettresAutoriseesRegex =
"[a-zA-Z0-9,.'
\"
;:!?
\\
-]+"
;
// Appel
final
String password =
passwordGenerator.generate
(
);
// Tests
assertNotNull
(
password);
assertTrue
(
verifyRegex
(
lettresAutoriseesRegex, password));
}
}
Durant le développement, Nathalie et William doivent vérifier qu'ils ne modifient pas le comportement des anciens tests. Bien entendu, après « T2 », les nouveaux tests doivent échouer (i.e. être rouges).
Luc va adopter la même stratégie pour les nouveaux tests dont il s'occupe.
package
fr.chiencopain.boutique.util.encryption;
import
static
junit.framework.Assert.assertEquals;
import
static
junit.framework.Assert.assertNotNull;
import
org.junit.Test;
/**
* REGLE RG024.2
*
@author
Luc
*
*/
public
abstract
class
AbstractEncryptorTest {
/**
* Encryptor
*/
protected
Encryptor encryptor;
/**
* REGLE RG024.x
*
*
@param
password
* Le mot de passe en clair.
*
@param
passwordCrypteAttendu
* Le mot de passe crypte attendu.
*/
protected
final
void
doTestEncrypt
(
final
String password, final
String passwordCrypteAttendu) {
// Appel
final
String passwordCrypte =
encryptor.encrypt
(
password);
// Tests
assertNotNull
(
passwordCrypte);
assertEquals
(
passwordCrypteAttendu, passwordCrypte);
}
/**
* On ne peut pas crypter un mot de passe vide. Si on essaie, ça doit lancer
* une erreur.
<
br/
>
*
* REGLE RG024.2-a
<
br/
>
*
* PARAM password = ""
<
br/
>
* RESULT IllegalArgumentException
*/
@Test
(
expected =
IllegalArgumentException.class
)
public
final
void
testEncrypt_RG024_2a
(
) {
// PARAM
final
String password =
""
;
final
String passwordCrypteAttendu =
"..."
;
// Appel
doTestEncrypt
(
password, passwordCrypteAttendu);
}
/**
* On ne peut pas crypter un mot de passe vide. Si on essaie, ça doit lancer
* une erreur.
<
br/
>
*
* REGLE RG024.2-b
<
br/
>
*
* PARAM password = null
<
br/
>
* RESULT IllegalArgumentException
*/
@Test
(
expected =
IllegalArgumentException.class
)
public
final
void
testEncrypt_RG024_2b
(
) {
// PARAM
final
String password =
null
;
final
String passwordCrypteAttendu =
"..."
;
// Appel
doTestEncrypt
(
password, passwordCrypteAttendu);
}
}
/**
* Tests de MD5Encryptor : Le systeme peut crypter un mot de passe.
*
* REGLE RG024, RG024.1, RG024.2
*
*
@author
Julie, puis modifiée par Luc en v2.
*
*/
public
class
MD5EncryptorTest extends
AbstractEncryptorTest {
/**
* MD5Encryptor
*/
@Before
public
final
void
doBefore
(
) {
encryptor =
new
MD5Encryptor
(
);
}
/**
* Les mots de passe seront cryptes à l'aide de l'algorithme MD5.
<
br/
>
*
* REGLE RG024.1-a
<
br/
>
*
* PARAM password = "football"
<
br/
>
* RESULT "37b4e2d82900d5e94b8da524fbeb33c0"
*/
@Test
public
final
void
testEncrypt_RG024_1a
(
) {
// PARAM
final
String password =
"football"
;
final
String passwordCrypteAttendu =
"37b4e2d82900d5e94b8da524fbeb33c0"
;
// Appel
doTestEncrypt
(
password, passwordCrypteAttendu);
}
/**
* Les mots de passe seront cryptes a l'aide de l'algorithme MD5.
<
br/
>
*
* REGLE RG024.1-b
<
br/
>
*
* PARAM password = "Hello012"
<
br/
>
* RESULT "00dd4826e068dad5be5e95ef692f62e6"
*/
@Test
public
final
void
testEncrypt_RG024_1b
(
) {
// PARAM
final
String password =
"Hello012"
;
final
String passwordCrypteAttendu =
"00dd4826e068dad5be5e95ef692f62e6"
;
// Appel
doTestEncrypt
(
password, passwordCrypteAttendu);
}
}
package
fr.chiencopain.boutique.util.encryption;
import
org.junit.Before;
import
org.junit.Test;
/**
* Tests de Sha1Encryptor : Le systeme peut crypter un mot de passe.
*
* REGLE RG024, RG024.2, RG024.3
*
*
@author
Luc
*
*/
public
class
Sha1EncryptorTest extends
AbstractEncryptorTest {
/**
* Sha1Encryptor
*/
@Before
public
final
void
doBefore
(
) {
encryptor =
new
Sha1Encryptor
(
);
}
/**
* Le système doit crypter les mots de passe en SHA-1.
<
br/
>
*
* REGLE RG024.3
<
br/
>
*
* PARAM password = "football"
<
br/
>
* RESULT "2d27b62c597ec858f6e7b54e7e58525e6a95e6d8"
*/
@Test
public
final
void
testEncrypt_RG024_3
(
) {
// PARAM
final
String password =
"football"
;
final
String passwordCrypteAttendu =
"2d27b62c597ec858f6e7b54e7e58525e6a95e6d8"
;
// Appel
doTestEncrypt
(
password, passwordCrypteAttendu);
}
}
Finalement, les anciens tests doivent rester verts et les nouveaux tests, conçus pour échouer au sens de « 3T », doivent être rouges, ce que les développeurs peuvent vérifier directement depuis Eclipse.
IV-C-3. Les développements (T3)▲
Les Post-It arrivent désormais dans le dernier temps pour cette « v2 » et le plus gros du travail a déjà été réalisé en « v1 », un an auparavant. Les nouveaux développements vont pouvoir s'appuyer allègrement sur l'existant, en plus des tests qui vont guider l'écriture. Comme pour l'ajout de tests lors de « T2 », les nouveaux codes (en « T3 ») vont entrainer un peu de réorganisation.
Disons que Luc prend en charge le développement de « RG023 » et que Sébastien s'occupe de « RG024 ».
Luc s'inspire largement des tests, pour lesquels l'équipe a identifié un besoin de « refactoring », laissant supposer que cette action aura une réponse similaire dans le cadre du développement final. Luc crée donc une classe abstraite et adapte les anciens codes. Enfin, il code la classe qui va générer des mots de passe avec les nouvelles règles.
package
fr.chiencopain.boutique.service.credentials;
import
java.util.Random;
/**
* REGLE RG023.2
*
*
@author
Luc
*
*/
public
abstract
class
AbstractPasswordGenerator implements
PasswordGenerator {
/**
* Selection un caractere au hasard dans la liste des caracteres autorises.
*
* REGLE RG023.2
*
*
@param
caracteresAutorises
* les caracteres qui sont autorises.
*
@return
un caractere au hasard.
*/
protected
final
char
generateOneDigit
(
final
String caracteresAutorises) {
final
Random random =
new
Random
(
);
final
int
position =
random.nextInt
(
caracteresAutorises.length
(
));
final
char
digit =
caracteresAutorises.charAt
(
position);
return
digit;
}
}
/**
* Outil de generation de mot de passe.
*
* REGLE RG023, RG023.1, RG023.2
*
*
@author
Julie (T1 et T3), Luc en v2.
*
*/
public
class
DefaultPasswordGenerator extends
AbstractPasswordGenerator implements
PasswordGenerator {
/**
* Caracteres autorises.
*
* REGLE RG023.2
*/
private
static
final
String CARACTERES_AUTORISES =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
;
/**
* REGLE RG023, RG023.1, RG023.2
*
*
{@inheritDoc}
*/
public
final
String generate
(
) {
final
StringBuilder sb =
new
StringBuilder
(
);
// REGLE RG023.1
final
int
nombreDigit =
8
;
for
(
int
i =
0
; i <
nombreDigit; i++
) {
// REGLE RG023.2
final
char
digit =
generateOneDigit
(
);
sb.append
(
digit);
}
return
sb.toString
(
);
}
/**
* Selection un caractere au hasard dans la liste des caracteres autorises.
*
* REGLE RG023.2
*
*
@return
un caractere au hasard.
*/
private
char
generateOneDigit
(
) {
return
generateOneDigit
(
CARACTERES_AUTORISES);
}
}
package
fr.chiencopain.boutique.service.credentials;
import
java.util.Random;
/**
* Outil de generation de mot de passe.
*
* REGLE RG023
*
*
@author
Sébastien (T1), Luc (T3)
*
*/
public
class
AdvancePasswordGenerator extends
AbstractPasswordGenerator implements
PasswordGenerator {
/**
* Caracteres autorises.
*
* lettres : a-z et A-Z
<
br/
>
* chiffres : 0-9
<
br/
>
* Ponctuations : ,.'";:!- (virgule, point, apostrophe, guillemet,
* point-virgule, deux-point, point d'exclamation, point d'interrogation,
* tiret)
*
* REGLE RG023.4
*/
private
static
final
String CARACTERES_AUTORISES =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789,.'
\"
;:!?-"
;
/**
* REGLE RG023, RG023.3, RG023.4
*
*
{@inheritDoc}
*/
public
final
String generate
(
) {
final
StringBuilder sb =
new
StringBuilder
(
);
final
Random random =
new
Random
(
);
final
int
nb =
random.nextInt
(
5
);
// REGLE RG023.1
final
int
nombreDigit =
6
+
nb;
for
(
int
i =
0
; i <
nombreDigit; i++
) {
// REGLE RG023.4
final
char
digit =
generateOneDigit
(
CARACTERES_AUTORISES);
sb.append
(
digit);
}
return
sb.toString
(
);
}
}
Pour des raisons purement techniques, Sébastien commence par ajouter des constantes (non prévues) dans l'interface. Il crée ensuite une classe abstraite pour factoriser une partie des traitements, et adapte la classe spécifique au cryptage MD5 en fonction. Il n'a plus, finalement, qu'à compléter la nouvelle classe pour SHA-1, ce qui ne prend que quelques instants.
/**
* Outil de cryptage.
*
* REGLE RG024
*
*
@author
Sebastien
*
*/
public
interface
Encryptor {
/**
* MD5
*/
String ALGO_MD5 =
"MD5"
;
/**
* SHA-1
*/
String ALGO_SHA1 =
"SHA-1"
;
/**
* Crypte le message passe en parametre.
<
br/
>
*
* REGLE RG024
*
*
@param
message
* Le message a crypter.
*
@return
une version cryptee du message.
*/
String encrypt
(
String message);
}
package
fr.chiencopain.boutique.util.encryption;
import
java.security.MessageDigest;
import
java.security.NoSuchAlgorithmException;
/**
* Outil de cryptage.
*
* REGLE RG024
*
*
@author
Sebastien
*
*/
public
abstract
class
AbstractSimpleEncryptor implements
Encryptor {
/**
* REGLE RG024
*
*
{@inheritDoc}
*/
protected
final
String doEncrypt
(
final
String message, final
String algo) {
// REGLE RG024.2
if
(
message ==
null
||
message.length
(
) ==
0
) {
throw
new
IllegalArgumentException
(
"Le param 'message' ne peut pas etre vide."
);
}
// REGLE RG024.1, RG024.3
try
{
final
byte
[] uniqueKey =
message.getBytes
(
);
final
byte
[] hash =
MessageDigest.getInstance
(
algo).digest
(
uniqueKey);
final
StringBuilder sb =
new
StringBuilder
(
);
for
(
int
i =
0
; i <
hash.length; i++
) {
String hex =
Integer.toHexString
(
hash[i]);
if
(
hex.length
(
) ==
1
) {
sb.append
(
'0'
);
sb.append
(
hex.charAt
(
hex.length
(
) -
1
));
}
else
{
sb.append
(
hex.substring
(
hex.length
(
) -
2
));
}
}
final
String encrypt =
sb.toString
(
);
return
encrypt;
}
catch
(
NoSuchAlgorithmException e) {
return
null
;
}
}
}
/**
* Outil de cryptage.
*
* REGLE RG024, RG024.1
*
*
@author
Sebastien, John, Sebastien (v2)
*
*/
public
class
MD5Encryptor extends
AbstractSimpleEncryptor implements
Encryptor {
/**
* MD5
*
* REGLE RG024.1
*/
public
static
final
String ALGO_CRYPTAGE =
ALGO_MD5;
/**
* REGLE RG024, RG024.1
*
*
{@inheritDoc}
*/
public
final
String encrypt
(
final
String message) {
return
doEncrypt
(
message, ALGO_CRYPTAGE);
}
}
package
fr.chiencopain.boutique.util.encryption;
/**
* Outil de cryptage.
*
* REGLE RG024, RG024.2, RG024.3
*
*
@author
Sebastien
*
*/
public
class
Sha1Encryptor extends
AbstractSimpleEncryptor implements
Encryptor {
/**
* SHA-1
*
* REGLE RG024.3
*/
public
static
final
String ALGO_CRYPTAGE =
ALGO_SHA1;
/**
* REGLE RG024.3
*
*
{@inheritDoc}
*/
public
final
String encrypt
(
final
String message) {
return
doEncrypt
(
message, ALGO_CRYPTAGE);
}
}
Un des grands avantages de « 3T », et plus particulièrement du travail divisé en temps, est de permettre aux développeurs de se concentrer sur des petites tâches. Par conséquent, durant le troisième temps, ils peuvent consacrer de l'énergie sur du « refactoring continu » et ainsi avoir une qualité qui augmente au fur et à mesure.
Maintenant que tous les développements sont réalisés, tous les nouveaux tests doivent passer au vert. On doit bien penser à vérifier que les anciens tests, limités aux tests non annulés, continuent d'être verts.
IV-C-4. Les Post-It scannés▲
Voici un récapitulatif final de l'ensemble des nouveaux Post-It. Il ne faut pas oublier que le Post-It orange « RG023.2 » est toujours d'actualité pour cette seconde version de la boutique.
|
[Post-It RG023] v2 |
|
[Post-It RG023] v2 VERSO |
|
[Post-It RG023.3] VERSO |
|
[Post-It RG023.3] VERSO |
|
[Post-It RG024] v2 |
|
[Post-It RG024] v2 verso |
|
[Post-It RG024.2] verso (v1) |
|
[Post-It RG024.3] VERSO |
À travers ce récapitulatif des Post-It de la seconde version de « la Boutique du Chien-Copain », on voit un détail que je voulais mettre en avant dans cet article et qui concerne les habitudes de mise à jour des Post-It. Comme pour les Post-It de la « v1 », j'ai utilisé une écriture différente pour chaque développeur. Pour le coup, sur cette « v2 », Sébastien est le seul à encore employer des gommettes, car Vanessa, qui est responsable des fournitures, n'a pas renouvelé le stock. En outre, on constate que Sébastien, qui est le seul rescapé de l'équipe initiale et qui a présenté « 3T » aux nouveaux arrivants, a transmis ses propres habitudes et ses propres notations à la nouvelle équipe. Je crois que c'est un point important à prendre en compte. On peut se demander comment ces habitudes auraient été transmises si Sébastien n'avait pas été seul.
IV-D. Reporting▲
Michel (le chef de projet) va être content en fin de projet. Les rapports fournissent des métriques excellentes. Évidemment, le rapport Surefire résumant les tests JUnit indique 100 % de réussite. Le contrat est donc rempli.
IV-E. Qualification▲
S'étant déjà fait surprendre l'an passé, lors de la phase de qualification de la « v1 », Bernard a préparé son affaire. Il a suivi le développement du coin de l'œil pour être prêt le jour J. Il a donc mis en place une batterie de tests conforme au cahier des charges, mais il a ajouté un ensemble de critères qualité, en accord avec Michel (le chef de projet), pour aller bien plus loin que les demandes du client. Ainsi le projet sera tiré vers le haut.
Sans grosse surprise, désormais, la qualification se passe sans encombre. Bernard ne trouve à redire que sur certains détails relatifs aux nouveaux critères avancés qu'il a ajoutés. C'est tellement négligeable, et hors périmètre, qu'il accepte la livraison sans discuter plus que ça.
V. Conclusion▲
Comme on l'a vu à travers cette petite fiction sur « la Boutique du Chien-Copain », un projet qui s'étale sur plusieurs années et versions, avec des équipes et des besoins qui évoluent, écrire des tests n'est pas synonyme de perte de temps. En effet, les TDD sont accusés à tort de couter cher, or, une version simplifiée des TDD, comme le propose « 3T », conduit non seulement à une forte qualité, mais également à des économies.
Les gains les plus évidents concernent les phases de recette et/ou de qualification pour lesquelles on ne connait que trop bien le coût d'une non-validation. Mais « 3T » permet également d'accélérer les développements, en les décomposant en tâches simples et cadrées, qui s'intègrent facilement avec des méthodes agiles comme Scrum. Finalement, « 3T » propose de mécaniser les développements et les tests, sans créer de surcoût, mais au contraire en diminuant les charges des projets.
Reste que « 3T » n'est qu'une proposition et ne se réclame de rien d'autre. En l'utilisant, les membres d'une équipe normalisent/formalisent ce qu'ils faisaient déjà de manière instinctive.
VI. Remerciements▲
Je tiens à remercier, en tant qu'auteur de ce miniroman à propos des Tests en Trois Temps (3T), toutes les personnes qui m'ont aidé et soutenu. Je pense tout d'abord à mes collègues qui subissent mes questions au quotidien, mais aussi à mes contacts et amis du web, dans le domaine de l'informatique ou non, qui m'ont fait part de leurs remarques et critiques. Bien entendu, je n'oublie pas l'équipe de developpez.com qui m'a guidé dans la rédaction de cet article et m'a aidé à le corriger et le faire évoluer, principalement sur le forum.
Plus particulièrement j'adresse mes remerciements, par ordre alphabétique, à djibril, Hing, Karyne, et keulkeul
VII. Annexes▲
VII-A. Conversations▲
Dans cette partie de l'article, je propose plusieurs discussions fictives entre les acteurs de l'histoire pour comprendre leurs choix.
VII-A-1. Le goût de « 3T »▲
Michel (le chef de projet) et Laurent (l'architecte) sont à la cantine et discutent du cahier des charges de « la boutique du Chien-Copain » que Claire (la cliente) vient de leur envoyer. Laurent voudrait mettre en place un plan qualité performant et strict, mais Michel recherche une méthode plus simple.
|
J'ai lu les « specs » de « Chien-Copain ». Ça a l'air sympa comme projet. |
|
Ouais. La responsable, chez eux, est super ouverte et on travaille bien avec elle. En plus ils sont super contents du site qu'on leur a fait l'année dernière. |
|
Il faudrait que ça devienne un client de référence. On va leur faire une appli aux petits oignons. Tu dis aux gars de « booster » les aspects qualité. J'veux voir des tests bien faits et une couverture de code maximale. Ensuite on capitalisera dessus dans les plaquettes et sur le Wiki. |
|
Bof, z'ont aucun goût. Et pour les tests, je pensais y aller doucement. La dernière fois, sur le projet Machin, quand on avait fait du TDD, ça a fini en catastrophe, avec tout le monde qui se tapait dessus. Et la fois d'avant, avec Truc, il n'y avait même pas de budget. |
|
Normal, le contact chez Truc, il avait des neurones en moins. Et avec Machin, c'était un petit manque d'organisation au début. |
|
Tout de même, c'est super complexe de faire du TDD, surtout que la plupart des points ne nous servent à rien. Et quand on utilise des choses utiles, on se mélange les pinceaux et on se pose mille questions. |
|
C'est pas faux. Mais c'est une démarche qualité. C'est hyper important. Soit tu fais du TDD, soit t'en fais pas. On n'est plus dans la bulle. |
|
Justement, j'ai trouvé un article intéressant sur developpez.com. Il y a un petit gars qui propose une alternative à nos méthodes. Il dit que c'est du TDD simplifié. Et dans ses exemples, ça n'a pas l'air de faire grand-chose, mais ça couvre 100 % de ce que j'ai envie de coller sur le projet. |
|
Faut voir. Tu m'enverras le lien. |
|
OK, pas de soucis, dès qu'on remonte, je l'ai mis en bookmark. En plus c'est facile à lire ; ça tient sur une poignée de pages. Je crois que ça s'appelle « 3T », au pire tu le cherches sur Google. |
|
Au moins, ton truc là, ton « 3T », ça fait des tests ? |
|
Oui, oui, c'est des tests. Ce qui change, c'est seulement la manière de les écrire. Quand on le lit, ça semble vraiment simple. Et question budget, c'est si bidon que c'est presque gratuit. |
|
Bon on verra. Déjà faut que je le lise. Mais t'as pas l'air sûr de ton coup. |
|
C'est vrai. J'ai encore un peu de mal à voir comment on va pouvoir intégrer ça avec Scrum d'une part, et puis avec Hudson pour l'intégration continue. |
|
Tu peux toujours envoyer un email à l'auteur. Les mecs de developpez.com, ils ont la réputation d'être sympas et de répondre aux questions, donc profites-en. |
|
Bonne idée ; je fais ça et je te tiens au courant. |
VII-A-2. Les Post-It de « 3T » collent à Scrum▲
Ayant aimé l'article de présentation de « 3T » sur developpez.com, Michel souhaite échanger quelques mots et idées avec l'auteur dont il a trouvé les coordonnées.
|
Bonjour et merci d'accepter de répondre à mes questions sur « 3T ». |
|
Bonjour Michel. Tout le plaisir est pour moi. |
|
J'ai lu votre article sur developpez.com et ça a l'air de correspondre avec ce que je recherche depuis quelque temps. En effet, je trouve que les tests sont indispensables. Toutefois je n'arrive pas à imposer une méthode comme TDD, car les équipes trouvent ça trop complexe, en particulier pour faire échouer les tests, et ma hiérarchie dit que ça coute trop cher. |
|
J'ai rencontré les mêmes difficultés durant mes missions. J'ai longtemps cherché un bon compromis, qui contente à la fois mes collègues, mon chef et la MOA, mais sans jamais y arriver vraiment. Quand le DSI imposait les TDD, ça devenait tellement complexe qu'on finissait par abandonner. Et à l'inverse, quand on faisait trop simple, c'était tellement « light » que ça ne servait à rien, ou alors à faire joli. Et puis un jour, en discutant avec un collègue, « 3T » m'est tombé dessus comme un éclair. |
|
Effectivement, ça semble magique et tellement simple quand on y pense. Il suffit de faire exactement ce qui est demandé si je comprends bien. Et en fait les développeurs apportent de la plus-value avant de coder quoi que ce soit. |
|
Oui c'est ça. Du coup les membres de l'équipe peuvent utiliser leur tête pour de vrai et ne pas se contenter de mettre en application des compétences purement techniques, sur telle ou telle spécificité du langage Java ou de la base de données. C'est bien plus gratifiant. Le point important de « 3T », c'est le deuxième temps ; celui durant lequel on écrit les tests, or c'est dans les tests que toute l'intelligence est concentrée. Et encore, ce n'est qu'une recopie des spécifications. |
|
Dans votre article, vous utilisez des Post-It. Est-ce que c'est obligatoire ? |
|
Rien n'est vraiment imposé dans « 3T », mis à part de bien travailler en trois temps. En ce qui concerne les Post-It, vous devez les voir comme un support de travail, simple et rapide. Bien entendu, vous devez faire évoluer le cahier des charges avec les Post-It que vous utilisez. Un peu de formalisme, à un moment ou un autre ne peut pas faire de mal ; vos clients n'en seront que plus satisfaits. |
|
C'est vrai que certains clients nous envoient des cahiers des charges succincts. Justement, mon équipe va commencer un projet pour une animalerie et les spécifications sont vraiment légères. |
|
Je vois qu'on est sur la même longueur d'onde. Avec « 3T », c'est du gagnant-gagnant ; on travaille main dans la main avec les clients. Ça me fait penser que j'ai vu sur votre site Web que vous accordez une grande importance aux méthodes agiles, notamment à Scrum. Vous avez donc l'habitude de griffonner des Post-It. Et donc vous faites déjà une grosse partie du boulot. |
|
Oui c'est vrai. Vu sous cet angle, franchir le pas de « 3T » a l'air encore plus facile. Du coup, si on part du principe que nos Post-It Scrum et nos Post-It « 3T » fonctionnent de pair, voire sont les mêmes, alors on peut s'en servir sur le « dashboard ». Il suffit d'ajouter des colonnes. |
|
Oui et non. C'est une très bonne idée d'utiliser les Post-It de « 3T » en remplacement de ceux de Scrum. Par contre il ne faut pas adapter le « dashboard ». Ce qu'il faut faire, c'est adapter les Post-It. Chaque Post-It doit traverser trois fois le « dashboard ». La première fois, c'est pour écrire les interfaces. La deuxième fois, c'est pour écrire les tests. Et enfin la troisième fois, c'est pour écrire le code. Ce sont les trois temps de « 3T ». |
|
Ça revient au même que d'ajouter des colonnes ? |
|
Pas tout à fait, car lorsqu'un Post-It revient dans le « sprint backlog », tu sais la colonne de gauche dans le « dashboad », n'importe quel membre de l'équipe peut potentiellement en prendre possession. Ça signifie que, dans l'idéal, chaque temps de « 3T » peut être pris en charge par une personne différente et que le processus reste fluide. |
|
Ah oui !… Excellent. |
VII-A-3. Ragot « 3T »▲
Vanessa apporte des fournitures (blocs, Post-It, stylo, gommettes, agrafes, etc.) dans le bureau des développeurs et en profite pour discuter des derniers ragots avec Julie. Durant la discussion, Vanessa va demander à quoi correspondent les Post-It sur le mur.
|
Ça sert à quoi les Post-It sur le tableau ? |
|
Ah ça… Heu… C'est notre méthode de travail. On note les tâches à faire sur des Post-It et, selon la colonne dans laquelle est le Post-It, on sait si la tâche est en attente, en cours de réalisation ou finie. |
|
Ça a une importance les couleurs ? Parce que je peux commander uniquement des jaunes chez Métro si ça vous arrange. |
|
Heu… ouais ! les couleurs et les tailles indiquent si le Post-It contient des informations d'organisation, ou fonctionnelle ou encore technique. Par exemple, les Post-It orange donnent des précisions sur des éléments super techniques qui ne sont même pas dans le cahier des charges. |
|
Je crois que je comprends. Mais alors, pourquoi vous avez dessiné une colonne qui porte le titre « 3T » sur les grands Post-It jaunes, ceux sur lesquels vous avez collé des gommettes de gamin ? |
|
Heu… Ça fait partie de la méthode. Et la colonne « 3T », heu… C'est encore autre chose. C'est un truc qu'est venu nous montrer un consultant pour nous aider à faire des tests plus efficaces, ou si tu préfères, à faire du code de meilleure qualité et plus facilement. |
|
Tu parles du beau brun qui est venu la semaine dernière et qui a passé la matinée avec vous ? |
|
Heu… Je n'irais pas jusqu'à dire qu'il est beau, mais, effectivement, c'est bien lui. |
|
Arrête, il est trop mignon. En tout cas j'en ferais bien mon quatre heures. |
|
Heu… Comme tu veux. Disons que ce n'est pas mon style. |
|
Et donc, c'est bien ce qu'il vous a présenté, le consultant ? |
|
Heu… Je ne sais pas trop. Apparemment Laurent (l'architecte, fiancé de Julie) trouve que c'est tellement simple que c'est génial. Perso je ne vois pas très bien où ça conduit, mais j'ai l'impression que ça nous aide un peu. Ça a le mérite de formaliser ce qu'on faisait déjà avant instinctivement. |
|
Je crois que je comprends. Donc c'est un peu du pipeau. |
|
Heu… Je ne sais pas encore. On doit essayer durant plusieurs semaines pour voir ce que ça donne. En tous cas, les autres ont l'air de bien aimer. |
|
À propos de bien aimer, tu as vu comment le mec de la compta reluquait mon décolleté à la cantine ?… |
VII-A-4. Le choc de « 3T »▲
Le développement de la seconde version de la boutique est sur le point de démarrer. Sébastien a été rejoint par Nathalie et William, à qui il va présenter « 3T » à sa manière. Luc, quant à lui n'est pas encore arrivé.
|
Bon les bleus. On va se poser en salle de réunion pendant une petite heure pour que je vous présente « 3T ». |
|
Oui chef !… |
|
Dis donc Man, tu te la racontes. |
|
Alors, comme je disais, Michel voudrait que je vous explique comment « 3T » fonctionne. |
|
C'est quoi d'abord ton « 3T machin » ? |
|
Bonne question ; en fait c'est même « TTT » et c'est le sigle de « Tests en Trois Temps ». C'est grosso modo une version simplifiée des TDD. |
|
Well. C'est une méthode officielle avec un web site ? |
|
Je ne crois pas que ce soit vraiment quelque chose de bien cadré. C'est Michel qui avait trouvé un article sur developpez.com et qui a fait venir un consultant pour nous expliquer en quoi ça consiste. |
|
Bon d'accord. Donc c'est comme les TDD, mais en plus simple. |
|
Les TDD, c'est bien. On connait. On sait faire. Mais c'est very long. |
|
Avec « 3T », ça devient un peu moins long et, surtout, c'est plus simple. |
|
C'est quoi la différence avec les TDD ? |
|
Heu, en fait je ne connais pas très bien les TDD donc je ne peux pas vraiment citer avec précision les différences, mais je peux déjà dire que ça simplifie la manière d'écrire les tests et de les faire planter au départ. |
|
Tu parles. C'est toi le « stroumph » tout bleu. |
|
OK, je vous explique et vous me direz au fur et à mesure les différences que vous notez. Ça vous va ? |
|
Well, très bien. |
|
D'abord, avec « 3T » on travaille toujours en trois temps, d'où le nom de la méthode. D'abord on doit écrire des interfaces pour les fonctionnalités demandées. |
|
Il y a déjà une différence avec les TDD là, parce que normalement on commence par les tests. |
|
Oui, ça j'avais vu. Mais en fait, dans le premier temps, on ne fait que recopier les spécifications en les traduisant sous forme d'interface. C'est pas vraiment du code, mais plutôt de la reformulation. D'ailleurs ça va super vite si on part du fichier Word pour écrire la Javadoc. |
|
Well. Les interfaces c'est rapide. |
|
Ensuite on écrit les tests, comme avec les TDD, sauf que pour les tests, on doit aussi recopier les spécs. L'idée est de ne pas se poser de question. Et chaque test doit avoir un numéro d'identification qui ramène au cahier des charges. Et inversement pour chaque point du cahier des charges, il doit y avoir un test. |
|
D'accord, c'est une sorte de bijection. |
|
Et s'il y a un trou dans les spécifications ? |
|
En fait, s'il y a un trou dans les spécs, il faut aller voir Michel et demander à combler le trou. C'est les spécs qui font foi. |
|
D'accord, mais c'est comme avec les TDD. |
|
Pas tout à fait parce qu'avec les TDD, tu passes beaucoup de temps à te demander quoi tester. Du coup, tu testes souvent trop de choses ou pas assez. Et puis surtout tu perds beaucoup de temps à faire des plans sur la comète. Le principe de « 3T », c'est que tout est déjà écrit et qu'il suffit de recopier. |
|
Well, c'est comme une notice des Lego. |
|
Je crois qu'on peut dire ça. |
|
Good… |
|
Et pour faire échouer les tests, on fait comment ? Parce qu'avec les TDD, c'est hyper compliqué quand tu veux faire ça bien. Je suppose que ta super méthode propose quelque chose… |
|
Exactement. Avec « 3T » on simplifie les échecs. On part du principe que le code n'est pas développé et que ça renvoie un « null » ou une exception. Et quand tu testes, c'est tout rouge. |
|
C'est pas du tout comme les TDD alors. On ne peut pas vraiment dire qu'on fait échouer le test initial. |
|
Oui je sais. Mais comme tu l'as toi-même remarqué, on écrit une bijection entre les tests et les spécs. Et « 3T » dit qu'un petit échec rapide, mais avec une couverture forte, c'est mieux que des vraies erreurs qui prennent du temps et que, de toute manière, tu vas effacer dans dix minutes. |
|
C'est sûr que si tu fais comme ça, tu gagnes un sacré paquet de temps. Sans jeu de mots, hi hi hi. |
|
Et puis il y a le troisième et dernier temps durant lequel on va écrire le code à proprement dit. Et là ça marche comme les TDD. Tu utilises les tests, de manière incrémentale, pour savoir quoi développer. |
|
Well, je comprends. Donc, avec « 3T », quand tous les tests passent au vert dans Eclipse, ça veut dire que tout est développé, car il y a la bijection avec les spécifications. |
|
En théorie, c'est ça. C'est ce que j'allais dire. Dans la pratique, c'est presque ça. Dans la « v1 » de la boutique, il n'y a qu'une ou deux fois où ça ne s'est pas vérifié, mais c'était parce qu'on avait mal identifié une problématique. |
|
D'accord, donc, effectivement ça doit aller très vite. C'est beaucoup plus light que les TDD, mais ça reprend une partie des points importants. |
VII-A-5. Motivation▲
Michel (le chef de projet) a découvert que Luc, un consultant en mission chez un client, est assez mal noté et que sa mission va rapidement prendre fin. Michel, qui avait déjà travaillé avec Luc et qui était très satisfait de ses prestations, est relativement surpris. Puisque Luc va revenir au siège de « Green Soft », il voudrait lui proposer de rejoindre ses équipes. Mais avant cela, Michel passe un coup de téléphone à Luc pour comprendre ce qui se passe.
|
Allo !… |
|
Bonjour Luc. C'est Michel. Tu te souviens de moi. |
|
Salut Michel. Ça faisait longtemps. Comment vas-tu ? |
|
Ça va très bien. Beaucoup de travail, mais j'arrive à gérer. Et toi, ça roule ? J'ai cru comprendre que ça n'allait pas fort. |
|
Effectivement, ma mission chez « Banque Machin » va s'arrêter. |
|
C'est bien ce que j'avais entendu dire. Que se passe-t-il ? |
|
Bof rien, justement. Je prends de plus en plus de pauses clope pour me changer les idées et m'échapper de ce projet pourri. |
|
Mais tu ne fumais pas avant ? |
|
Ouais, mais comme je te dis, le projet est vraiment pourri. |
|
Ça avait l'air bien pourtant chez « Machin ». |
|
Bah ouais. Au début c'était pas mal. Mais très rapidement, les mecs de la MOA ont commencé à nous demander n'importe quoi. Et notre chef dit oui à tout. Du coup on fait tout dans l'urgence et ça devient le bordel. |
|
Vous aviez une démarche qualité pourtant en janvier… |
|
Ouais, bah… Il y a longtemps que c'est enterré. Ça sentait le sapin dès le départ de toute manière. Au début les chefs ont joué le jeu, mais, à la mi-mars, ils ont décrété que ça coutait trop cher et que le métier ne payait pas pour ça. |
|
C'est étrange. Le commercial avait l'air de dire que « Banque Machin » était convertie. |
|
Les choses changent. Et maintenant, on continue de faire des tests, de la « qualif » et tout plein de trucs, mais après coup. Là on en est à écrire des tests sur du code qui a déjà été livré en production. Tu vois le genre. |
|
Oui. C'est des tests de complaisance. |
|
Les clients sont tous les mêmes. Au début ils veulent se démarquer et produire des outils de qualité, mais à la fin c'est toujours la même bouse. Je me demande si je ne vais pas changer de métier, tellement ça me déprime. |
|
Attends justement j'ai un truc à te proposer. L'année dernière on a lancé un site de vente en ligne pour « Chien-Copain », tu sais le fabricant d'accessoires pour les animaux. Et là on vient de commencer la « v2 ». Ça te dirait de nous rejoindre dans l'équipe, vu que tu reviens au siège de « Green » ? |
|
Bof, au siège ou en régie chez le client, ça revient au même. |
|
Attends parce que ce n'est pas tout. Depuis un peu plus d'un an, on applique une nouvelle méthode qui simplifie les TDD et qui permet de faire de la qualité pour de vrai. La boutique était justement un projet pilote. Ça a super bien marché et on continue sur la lancée. |
|
Ouais, c'est ça, jusqu'au jour où un mec de la compta dit que ça coute trop cher… |
|
Justement non. Un des avantages de la méthode, ça s'appelle « 3T » au fait, c'est qu'elle rend les « dév » plus rapides. Du coup tout le monde est content. Pour l'équipe, c'est l'occasion de créer des produits avec une forte qualité. Pour le client ça coute moins cher et c'est plus rapidement prêt. Et pour la compta, ça permet de dégager plus de marges (plus rapide, moins de bogues) et de faire des volumes supplémentaires. Et pour la DSI, ça relève le niveau de la société. Du coup tout le monde est à fond ici. |
|
Ouais, bon, je veux bien essayer pour voir. Je commence quand ? |
|
Ça y est ! Tu as commencé quand tu as décroché le téléphone. C'est magique. C'est comme suivre le lapin blanc. |
VII-B. Maven et Eclipse▲
Pour écrire cet article, j'ai créé un nouveau projet Maven 3 en écrivant le fichier pom (proposé ci-dessous) dans le dossier « boutique-chien-copain ».
<project
xmlns
=
"http://maven.apache.org/POM/4.0.0"
xmlns
:
xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xsi
:
schemaLocation
=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0</modelVersion>
<groupId>
fr.chien-copain</groupId>
<artifactId>
boutique</artifactId>
<version>
1.0-SNAPSHOT</version>
<packaging>
jar</packaging>
<name>
Boutique du Chien-Copain</name>
<description>
Projet de la Boutique du Chien-Copain</description>
<url>
http://www.thierryler.com</url>
<licenses>
<license>
<name>
Copyright ©1995-2011 thierryler.com et Copyright ©2011 Developpez.com</name>
<comments>
Les sources présentés sur cette page sont [..] Cette page est déposée à la SACD.</comments>
</license>
</licenses>
<developers>
<!-- Michel -->
<developer>
<name>
Michel</name>
<roles>
<role>
Chef de projet</role>
</roles>
<organization>
Green Soft</organization>
</developer>
<!-- Laurent -->
<developer>
<name>
Laurent</name>
<roles>
<role>
Architecte</role>
<role>
Developpeur</role>
</roles>
<organization>
Green Soft</organization>
</developer>
<!-- Julie -->
<developer>
<name>
Julie</name>
<roles>
<role>
Developpeur</role>
</roles>
<organization>
Green Soft</organization>
</developer>
<!-- Sébastien -->
<developer>
<name>
Sébastien</name>
<roles>
<role>
Developpeur</role>
</roles>
<organization>
Green Soft</organization>
</developer>
<!-- John -->
<developer>
<name>
John</name>
<roles>
<role>
Developpeur</role>
</roles>
<organization>
Green Soft</organization>
</developer>
</developers>
<properties>
<project.build.sourceEncoding>
UTF-8</project.build.sourceEncoding>
<maven-compiler-plugin.version>
2.3.1</maven-compiler-plugin.version>
<junit.version>
4.8.1</junit.version>
<maven-site-plugin.version>
3.0-beta-3</maven-site-plugin.version>
<maven-javadoc-plugin.version>
2.8</maven-javadoc-plugin.version>
<maven-checkstyle-plugin.version>
2.7</maven-checkstyle-plugin.version>
<maven-pmd-plugin.version>
2.5</maven-pmd-plugin.version>
<maven-jxr-plugin.version>
2.3</maven-jxr-plugin.version>
<taglist-maven-plugin.version>
2.4</taglist-maven-plugin.version>
<cobertura-maven-plugin.version>
2.5.1</cobertura-maven-plugin.version>
<maven-surefire-plugin.version>
2.9</maven-surefire-plugin.version>
<maven-surefire-report-plugin>
2.9</maven-surefire-report-plugin>
<log4j.version>
1.2.13</log4j.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- JUnit -->
<dependency>
<groupId>
junit</groupId>
<artifactId>
junit</artifactId>
<version>
${junit.version}</version>
<scope>
test</scope>
</dependency>
<!-- JAX WS RT -->
<dependency>
<groupId>
com.sun.xml.ws</groupId>
<artifactId>
jaxws-rt</artifactId>
<version>
${jaxws-rt.version}</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>
log4j</groupId>
<artifactId>
log4j</artifactId>
<version>
${log4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>
junit</groupId>
<artifactId>
junit</artifactId>
<scope>
test</scope>
</dependency>
</dependencies>
<build>
<finalName>
Boutique du Chien-Copain</finalName>
<plugins>
<plugin>
<artifactId>
maven-compiler-plugin</artifactId>
<version>
${maven-compiler-plugin.version}</version>
<configuration>
<source>
1.5</source>
<target>
1.5</target>
<encoding>
${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins</groupId>
<artifactId>
maven-site-plugin</artifactId>
<version>
${maven-site-plugin.version}</version>
</plugin>
<!-- Surefire -->
<plugin>
<groupId>
org.apache.maven.plugins</groupId>
<artifactId>
maven-surefire-plugin</artifactId>
<version>
${maven-surefire-plugin.version}</version>
</plugin>
</plugins>
</build>
<reporting>
<plugins>
<!-- javadoc -->
<plugin>
<groupId>
org.apache.maven.plugins</groupId>
<artifactId>
maven-javadoc-plugin</artifactId>
<version>
${maven-javadoc-plugin.version}</version>
</plugin>
<!-- checkstyle -->
<plugin>
<groupId>
org.apache.maven.plugins</groupId>
<artifactId>
maven-checkstyle-plugin</artifactId>
<version>
${maven-checkstyle-plugin.version}</version>
<!-- <configuration> <configLocation>checkstyle.xml</configLocation>
</configuration> -->
</plugin>
<!-- PMD -->
<plugin>
<groupId>
org.apache.maven.plugins</groupId>
<artifactId>
maven-pmd-plugin</artifactId>
<version>
${maven-pmd-plugin.version}</version>
</plugin>
<!-- JXR : pour lier les sources -->
<plugin>
<groupId>
org.apache.maven.plugins</groupId>
<artifactId>
maven-jxr-plugin</artifactId>
<version>
${maven-jxr-plugin.version}</version>
</plugin>
<!-- taglist -->
<plugin>
<groupId>
org.codehaus.mojo</groupId>
<artifactId>
taglist-maven-plugin</artifactId>
<version>
${taglist-maven-plugin.version}</version>
<configuration>
<tagListOptions>
<tagClasses>
<tagClass>
<displayName>
Todo Work</displayName>
<tags>
<tag>
<matchString>
todo</matchString>
<matchType>
ignoreCase</matchType>
</tag>
<tag>
<matchString>
FIXME</matchString>
<matchType>
exact</matchType>
</tag>
</tags>
</tagClass>
<tagClass>
<displayName>
Regles</displayName>
<tags>
<tag>
<matchString>
REGLE</matchString>
<matchType>
ignoreCase</matchType>
</tag>
</tags>
</tagClass>
</tagClasses>
</tagListOptions>
</configuration>
</plugin>
<!-- Cobertura : couverture de code -->
<plugin>
<groupId>
org.codehaus.mojo</groupId>
<artifactId>
cobertura-maven-plugin</artifactId>
<version>
${cobertura-maven-plugin.version}</version>
</plugin>
<!-- Surefire (junit) -->
<plugin>
<groupId>
org.apache.maven.plugins</groupId>
<artifactId>
maven-surefire-report-plugin</artifactId>
<version>
${maven-surefire-report-plugin}</version>
</plugin>
</plugins>
</reporting>
</project>
Dans ce fichier « pom.xml », j'utilise un ensemble de plugins qui me semblent constituer l'arsenal minimum à mettre en œuvre sur un projet.
Ensuite, en ligne de commande, dans le répertoire « boutique-chien-copain », j'ai fabriqué la structure du projet Eclipse à l'aide de la commande Maven suivante.
mvn clean install eclipse:eclipse
Si on vient tout juste d'installer Maven, celui-ci va commencer par rapatrier un nombre assez important de bibliothèques, dont JUnit, nécessaires à son fonctionnement. Donc, il est important d'avoir une connexion Internet active à ce moment-là.
La commande crée en particulier le dossier « target » et les fichiers Eclipse « .classpath » et « .project ». Il ne reste plus qu'à importer le projet dans Eclipse (via le menu « File>Import>General>Existing Projects into Workspace »). Maintenant on peut travailler.
Eclipse et Maven ne sont utilisés ici qu'à titre pratique. Ils n'ont rien à voir avec « 3T ».
VII-C. Le Dashboard Scrum et 3T en bref▲
Le « dashboard » est un outil visuel de Scrum, qui ressemble aux illustrations ci-dessous. Le « dashboard Scrum » se présente le plus souvent sous la forme d'un tableau avec trois colonnes, dans lesquelles les développeurs collent des Post-It. Chaque Post-It correspond, grosso modo, à une tâche à accomplir. Les colonnes indiquent si la tâche est en attente de traitement, en cours de traitement ou terminée. En fonction de l'avancée de l'équipe, les Post-It changent progressivement de colonne.
Normalement, en début de projet (ou de « sprint ») tous les Post-It sont dans la colonne de gauche (« sprint backlog »). À la fin du projet, tous les Post-It doivent être dans la colonne de droite. Durant les développements, les Post-It transitent, en toute logique, par la colonne centrale.
Dans cet article, les développeurs de « Green Soft », mélangent les Post-It de Scrum et les Post-It de « 3T ».
VII-D. Le sprint Scrum et 3T▲
Dans cet article, je m'autorise beaucoup de libertés vis-à-vis de Scrum et des TDD. Dans Scrum, les Post-It vont du « sprint backlog » (c'est-à-dire la colonne de gauche du « dashboard ») vers la colonne de droite en fonction de la réalisation des tâches. Un « sprint » est une durée (généralement 2 ou 3 semaines) durant laquelle l'équipe va se concentrer sur un ensemble de Post-It bien identifiés.
Dans le cadre de « 3T », les Post-It doivent traverser trois fois le « dashboard » durant le sprint. Chaque passage correspond à un temps de « 3T » : écriture des interfaces, écriture des tests et écriture du code. J'entends déjà les puristes qui crient au scandale. Gardons à l'esprit que ce n'est qu'une proposition.
VII-E. Digression sur la confiance versus les tests▲
Pour finir cet article, je me permets une petite analyse personnelle à propos de la confiance. Vous souvenez-vous lorsque votre médecin vous affirmait que « ça n'allait pas faire mal » juste avant de vous infliger une piqure ? Sacré menteur !… Ma mère avait l'habitude de me dire de ne « jamais faire confiance à personne sauf à ta maman » et j'ajoute qu'il ne faut jamais faire confiance à quelqu'un qui vous demande de lui faire confiance.
Comment cela se traduit-il en informatique et plus particulièrement dans le cadre du développement logiciel ? À l'intérieur d'une application, cela implique l'utilisation de techniques de défense (copie de défense, assertion, etc.), mais ce n'est pas l'objet de cet article. Dans la communication, c'est encore plus simple : il ne faut jamais faire confiance à un développeur ou à une équipe et encore moins à un logiciel. Ce que je demande à mes clients, c'est de ne jamais croire à mes promesses (je n'en fais jamais), mais, au contraire, de toujours exiger des preuves.
Plus concrètement, et sous réserve qu'on m'en donne les moyens, je crois que « 3T » est une bonne piste pour arriver à cet objectif. Avec « 3T », on écrit d'abord les tests qui prouveront au client que le produit en création sera conforme au cahier des charges. J'insiste sur le fait que les tests doivent être écrits en amont, et non après les développements comme c'est encore trop souvent le cas malheureusement (car cela favorise la multiplication de tests de complaisance). En procédant de cette manière, je crois qu'une équipe gagne bien plus que de la « confiance » ; elle acquiert de la « crédibilité »…