Vous êtes sur la page 1sur 234

Programmeur

Programmeur pragmatique,
pragmatique, Le
Le :: de
de compagnon
compagnon àà maître
maître

Andrew Hunt
David Thomas
Editeur : Addison Wesley
Première édition le 13 octobre 1999
ISBN : 0-201-61622-X, 352 pages

Tout droit sorti des tranchées de programmation, The Pragmatic


Le programmeur coupe à travers la spécialisation croissante et
technicités du développement de logiciels modernes pour examiner les
processus de base - prendre une exigence et produire un travail,
code maintenable qui ravit ses utilisateurs. Il couvre des sujets
allant de la responsabilité personnelle au développement de carrière
aux techniques architecturales pour garder votre code flexible et
facile à adapter et à réutiliser. Lisez ce livre et vous apprendrez comment
pour:

Lutte contre la pourriture logicielle ;

Evitez le piège de la duplication des connaissances ;

Écrire du code flexible, dynamique et adaptable ;

Évitez la programmation par coïncidence;

Protégez votre code avec des contrats, des assertions et


des exceptions;

Capturez les exigences réelles ;

Testez impitoyablement et efficacement;

Faites plaisir à vos utilisateurs ;

Construire des équipes de programmeurs pragmatiques ; et

Rendez vos développements plus précis grâce à l'automatisation.

Écrit comme une série de sections autonomes et rempli de


anecdotes divertissantes, exemples réfléchis et intéressants

analogies, le programmeur pragmatique illustre le meilleur


pratiques et les principaux écueils de nombreux aspects différents de
développement de logiciels. Que vous soyez un nouveau codeur, un
programmeur expérimenté, ou un gestionnaire responsable de
projets logiciels, utilisez ces leçons quotidiennement et vous comprendrez rapidement
voir des améliorations dans la productivité personnelle, la précision et le travail
satisfaction. Vous acquerrez des compétences et développerez des habitudes et
attitudes qui constituent la base du succès à long terme dans
votre carrière. Vous deviendrez un programmeur pragmatique.
Préface .......................................................................................................................12
Qui devrait lire ce livre ? ...............................................................12
Qu'est-ce qui fait un programmeur pragmatique ? ...............................................13
Pragmatiques Individuels, Grandes Equipes..................................................14
C'est un processus continu ......................................................................15
Comment le livre est organisé ................................................................15
Qu'est-ce qu'il y a dans un nom? ..................................................................................15
Code source et autres ressources .......................................................16
Envoyez-nous vos commentaires..............................................................................16
Remerciements .......................................................................................16
Qu'est-ce qu'il y a dans un nom? ..................................................................................18
Code source et autres ressources .......................................................18
Envoyez-nous vos commentaires..............................................................................18
Remerciements .......................................................................................19
Le chat a mangé mon code source ................................................................19
Assumer ses responsabilités ..................................................................20
Les sections connexes incluent : ..................................................................21
Défis ......................................................................................................21
Entropie logicielle .......................................................................................21
Éteindre les incendies..............................................................................22
Les sections connexes incluent : ..................................................................23
Défis..................................................................................................23
Soupe aux cailloux et grenouilles bouillies ................................................................23
Du côté des villageois ..................................................................................24
Les sections connexes comprennent : ..................................................................25
Défis ..................................................................................................25
Logiciels suffisamment performants ..................................................................25
Impliquez vos utilisateurs dans le compromis ......................................26
Savoir quand s'arrêter ..................................................................................26
Les sections connexes comprennent : ..................................................................27
Défis ..................................................................................................27
Votre portefeuille de connaissances .......................................................................27
Votre portefeuille de connaissances ..................................................................28
Construire votre portefeuille..............................................................................28
Objectifs..................................................................................................29
Opportunités d'apprentissage ...............................................................30
Pensée critique .......................................................................................30
Soin et culture des gourous ..................................................................30
Défis ..................................................................................................31
Communiquez !................................................................................................31
Sachez ce que vous voulez dire..............................................................32
Connaissez votre public ..................................................................................32
Illustration 1.1. L'acrostiche de la sagesse - comprendre un public ...32

Choisissez votre moment..............................................................................33


Choisir un Style..................................................................................33
Faites en sorte que ça paraisse bien ..................................................33
Impliquez votre public........................................................................34
Être à l'écoute.................................................................................................34
Revenir aux gens..............................................................................34
Communication par e-mail..............................................................................34
Résumé .................................................................................................................35
Les sections connexes comprennent : ..................................................................35
Défis..................................................................................................35
Chapitre 2. Une approche pragmatique ......................................................37
Les maux de la duplication............................................................................37
Comment se produit la duplication ? ..................................................................38
Duplication imposée..................................................................................39
Duplication par inadvertance ..................................................................40
Duplication impatiente .......................................................................................42
Duplication inter-développeurs ..................................................................42
Les sections connexes incluent : ..................................................................43
Orthogonalité ..................................................................................................43
Qu'est-ce que l'orthogonalité ? .....................................................................43
Un système non orthogonal ..................................................................44
Avantages de l'orthogonalité ..................................................................44
Gagnez en productivité ..................................................................45
Réduire les risques ..................................................................................45
Equipes de projet ..................................................................................45
Conception..............................................................................................46
Illustration 2.1. Diagramme de couche typique ..................................................46
Boîtes à outils et bibliothèques .......................................................................47
Codage ..................................................................................................48
Tests..................................................................................................49
Documentation..................................................................................49
Vivre avec l'orthogonalité.................................................................49
Les sections connexes comprennent :................................................................50
Défis ..................................................................................................50
Exercices ..................................................................................................50
Réversibilité .......................................................................................................51
Réversibilité .......................................................................................51
Architecture flexible ..................................................................................52
Les sections connexes incluent :................................................................53
Défis ......................................................................................................53
Balles traçantes .......................................................................................53
Un code qui brille dans le noir............................................................54
Les balles traçantes n'atteignent pas toujours leur cible..............56
Code traceur versus prototypage............................................................56

Les sections connexes incluent : ..................................................................57


Prototypes et Post-it ..................................................................................57
Choses à prototyper ..................................................................................58
Comment
Architecture utiliser les prototypes ..................................................................58
de prototypage..................................................................59
Comment ne pas utiliser de prototypes .......................................................59
Les sections connexes incluent : ..................................................................60
Exercices ..................................................................................................60
Langues du domaine..................................................................................60
Erreurs spécifiques au domaine ......................................................................62
Implémenter un Mini-Langage .......................................................62
Langages de données et langages impératifs ................................63
Illustration 2.2. Fichier Windows .rc ..................................................63
Langages autonomes et intégrés .......................................65
Développement facile ou maintenance facile ? .......................................65
Les sections connexes incluent : ..................................................................65
Défis ..................................................................................................65
Exercices ..................................................................................................66
Estimation ..................................................................................................66
Dans quelle mesure la précision est-elle suffisante ?.........................................67
D'où viennent les estimations ? .......................................................68
Comprendre ce qui est demandé ..................................................................68
Construire un modèle du système................................................................68
Décomposer le modèle en composants ..................................................68
Attribuez une valeur à chaque paramètre .......................................69
Calculer les réponses .................................................................................69
Gardez une trace de vos prouesses en matière d'estimation ......69
Estimation des échéanciers de projet ..................................................70
Que dire lorsqu'on lui demande un devis ................................................70
Les sections connexes comprennent : ..................................................................70
Défis ..................................................................................................70
Exercices ..................................................................................................71
Chapitre 3. Les outils de base.................................................................................72
La puissance du texte brut..............................................................................73
Qu'est-ce que le texte brut ? ..................................................................................73
Inconvénients..................................................................................................74
Le pouvoir du texte ..................................................................................74
Assurance contre l'obsolescence ..................................................74
Effet de levier ..................................................................................75
La philosophie Unix..................................................................................75
Tests plus faciles ..................................................................................76
Plus petit dénominateur commun................................................................76
Les sections connexes incluent : ..................................................................76
Défis ..................................................................................................76

Jeux de coquillages..................................................................................77
Utilitaires Shell et systèmes Windows ................................................79
Utilisation des outils Unix sous Windows ................................................79
Les sections connexes incluent : ..................................................................80
Défis ..................................................................................................80
Édition avancée ..................................................................................................80
Un seul éditeur.............................................................................................80
Fonctionnalités de l'éditeur..............................................................................81
Productivité.................................................................................................82
Illustration 3.1. Trier les lignes dans un éditeur .......................................82
Où aller à partir d'ici ..................................................................82
Quels éditeurs sont disponibles ?................................................................83
Défis ..................................................................................................83
Contrôle du code source ..................................................................................83
Contrôle du code source et constructions .......................................................85
Mais mon équipe n'utilise pas le contrôle du code source ......................85
Produits de contrôle du code source ..................................................85
Les sections connexes comprennent : ..................................................................85
Défis..................................................................................................85
Débogage..................................................................................................86
Psychologie du débogage ..................................................................86
Un état d'esprit de débogage ..................................................................87
Par où commencer ..................................................................................87
Stratégies de débogage .......................................................................88
Reproduction desvos
Visualisez bogues
données ..................................................................................88
.......................................................................88
Illustration 3.2. Exemple de diagramme de débogueur d'une liste chaînée circulaire. Le
les flèches représentent des pointeurs vers des nœuds. ...............................................89
Traçage..............................................................................................89
Variables corrompues ? Vérifiez leur voisinage ..................................90
Ducking en caoutchouc ..................................................................................90
Processus d'élimination ....................................................................90
L'élément de surprise ..................................................................91
Liste de contrôle de débogage..............................................................92
Les sections connexes comprennent : ..................................................................92
Défis ..................................................................................................92
Manipulation de texte..................................................................................93
Les sections connexes comprennent : ..................................................................95
Exercices ..................................................................................................95
Générateurs de codes ....................................................................................95
Générateurs de code passifs ..................................................................96
Générateurs de code actifs .................................................................................97
Illustration 3.3. Le générateur de code actif crée du code à partir d'une base de données
schéma .......................................................................................................97

Illustration 3.4. Génération de code à partir d'un langage neutre


représentation. Dans le fichier d'entrée, les lignes commençant par 'M' marquent le
début d'une définition de message, les lignes 'F' définissent les champs et 'E' est le
fin du message. .......................................................................98
Les générateurs de code n'ont pas besoin d'être complexes..............................98
Les générateurs de code n'ont pas besoin de générer de code ..................98
Les sections connexes comprennent : ..................................................................98
Exercices ..................................................................................................99
Chapitre 4. Paranoïa pragmatique................................................................100
Conception par contrat..............................................................................101
CDB ..................................................................................................101
DBC et paramètres constants..................................................................102
Mise en œuvre de DBC..................................................................................104
Assertions .......................................................................................................104
Prise en charge de la langue .......................................................................105
DBC et plantage précoce ..................................................................105
Qui est responsable ? ..................................................................................105
Autres utilisations des invariants ..................................................................106
Invariants de boucle ..................................................................................106
Invariants sémantiques............................................................................107
Contrats dynamiques et agents ..................................................................108
Les sections connexes incluent : ..................................................................108
Défis ....................................................................................................108
Exercices ..................................................................................................108
Les programmes morts ne mentent pas ..................................................................110
Crash, ne pas jeter ..................................................................110
Les sections connexes comprennent : ..................................................................111
Programmation assertive ..................................................................111
Laisser les assertions activées.........................................................113
Assertion et effets secondaires..............................................................................113
Les sections connexes incluent : ..................................................................114
Exercices ..................................................................................................114
Quand utiliser les exceptions ..................................................................114
Qu'est-ce que l'exceptionnel ?.........................................................................115
Les gestionnaires d'erreurs sont une alternative................................................116
Les sections connexes incluent : ..................................................................117
Défis ....................................................................................................117
Exercices ..................................................................................................117
Comment équilibrer les ressources .......................................................117
Allocations d'imbrication .......................................................................120
Objets et exceptions .......................................................................................120
Équilibrage et exceptions................................................................................121
Équilibrage des ressources avec des exceptions C++ .......................121
Équilibrage des ressources en Java............................................................122
Lorsque vous ne parvenez pas à équilibrer les ressources ..................................123
Vérification de la balance..............................................................................123
Les sections associées incluent : ..................................................................124
Défis..............................................................................................124
Exercices ..................................................................................................124
Chapitre 5. Plier ou casser............................................................................125
Le découplage et la loi de Déméter ..................................................................125
Minimiser le couplage ..................................................................................126
La loi de Déméter pour les fonctions ..................................................127
Figure 5.1. Loi de Déméter pour les fonctions ..................................127
Cela fait-il vraiment une différence ? ..................................................128
Découplage physique.................................................................................128
Les sections associées incluent : ..................................................................129
Défis ....................................................................................................129
Exercices ..................................................................................................129
Métaprogrammation..............................................................................130
Configuration dynamique ....................................................................130
Applications basées sur les métadonnées ..................................................131
Logique métier ..................................................................................132
Quand configurer .......................................................................................132
Un exemple : Enterprise Java Beans ................................................133
Configuration coopérative................................................................133
Ne pas écrire de Dodo-Code ................................................................134
Les sections connexes incluent : ..................................................................134
Défis ....................................................................................................134
Exercices ..................................................................................................134
Couplage temporel.................................................................................134
Flux de travail .......................................................................................135
Figure 5.2. Diagramme d'activité UML : faire une piña colada .........136
Architecture ..................................................................................137
Figure 5.3. Présentation de l'architecture OLTP.................................137
Conception pour la simultanéité ..................................................................138
Interfaces plus propres ......................................................................138
Déploiement ......................................................................................140
Les sections connexes incluent : ..................................................................140
Défis ....................................................................................................140
Ce n'est qu'une vue ......................................................................................140
Publier/S'abonner .................................................................................141
Figure 5.4. Protocole de publication/abonnement .......................................141
Modèle-Vue-Contrôleur ......................................................................142
Le service d'événements CORBA ..................................................................142
Arborescence Java................................................................................143
Au-delà des interfaces graphiques ...............................................................................144
Figure 5.5. Reportage de baseball, les téléspectateurs s'abonnent aux modèles. ...145

Toujours en couple (après toutes ces années) ................................................146


Les sections connexes incluent : ..................................................................146
Exercices ..................................................................................................146
Tableaux ..................................................................................................146
Illustration 5.6. Quelqu'un a trouvé un lien entre Humpty's
les dettes de jeu et les journaux téléphoniques. Peut-être recevait-il
appels téléphoniques menaçants. ...............................................................147
Implémentations du tableau noir ..................................................148
Organisation de votre tableau..................................................................148
Exemple d'application .......................................................................149
Les sections connexes comprennent : ..................................................................150
Défis ....................................................................................................150
Exercices ..................................................................................................150
Chapitre 6. Pendant que vous codez .......................................................151
Programmation par Coïncidence ..................................................................151
Comment programmer par coïncidence ..................................................152
Accidents de mise en œuvre .......................................................152
Accidents de contexte..............................................................................153
Hypothèses implicites ......................................................................153
Comment programmer délibérément..............................................154
Les sections connexes incluent : ..................................................................154
Exercices ..................................................................................................155
Vitesse de l'algorithme ..................................................................................155
Qu'entendons-nous par estimation d'algorithmes ? .............................155
La notation O() ..................................................................................156
Figure 6.1. Exécutions de divers algorithmes ..................................156
Estimation de bon sens ..................................................................157
Vitesse de l'algorithme en pratique............................................................158
Le meilleur n'est pas toujours le meilleur ..................................................159
Les sections connexes incluent : ..................................................................159
Défis ....................................................................................................160
Exercices ..................................................................................................160
Refactorisation .......................................................................................160
Quand devriez-vous refactoriser ? ..................................................................161
Complications du monde réel ..................................................162
Comment refactoriser ? .....................................................................162
Refactoring automatique ................................................................................163
Les sections connexes incluent : ..................................................................163
Exercices ..................................................................................................164
Code facile à tester..............................................................................165
Tests unitaires .......................................................................................165
Test par rapport au contrat ..................................................................166
Rédaction de tests unitaires..............................................................................167
Utilisation des harnais de test..............................................................169

Tests ad hoc..............................................................................................169
Construire une fenêtre de test .......................................................................170
Une culture de test ..................................................................................171
Les sections connexes incluent : ..................................................................171
Exercices ..................................................................................................172
Sorciers maléfiques ..................................................................................172
Les sections associées incluent : ..................................................................173
Défis..............................................................................................173
Chapitre 7. Avant le projet ......................................................................174
La fosse aux exigences ..................................................................................174
Creuser pour les besoins ..................................................................175
Exigences en matière de documentation..................................................176
Parfois, l'interface est le système ..................................................176
Illustration 7.1. Modèle de cas d'utilisation de Cockburn ......................177
Illustration 7.2. Exemple de cas d'utilisation................................................178
Diagrammes de cas d'utilisation .......................................................179
Illustration 7.3. Cas d'utilisation d'UML—si simple qu'un enfant pourrait le faire !.........180
Surspécification .......................................................................................180
Voir plus loin ....................................................................................180
Juste une menthe ultra-mince de plus…................................................181
Maintenir un glossaire ..................................................................................181
Faites passer le mot .................................................................................182
Les sections connexes incluent : ..................................................................182
Défis ....................................................................................................182
Exercices ..................................................................................................182
Résoudre des énigmes impossibles ..................................................................183
Degrés de liberté ..................................................................................183
Il doit y avoir un moyen plus simple ! .......................................................184
Défis..............................................................................................185
Pas tant que vous n'êtes pas prêt ..................................................................185
Bon jugement ou procrastination ? ...............................................186
Défis ....................................................................................................186
Le piège des spécifications .......................................................................187
Les sections associées incluent : ..................................................................188
Défis..............................................................................................189
Cercles et flèches ...............................................................................189
Les méthodes sont-elles payantes ? .......................................................................190
Doit-on utiliser des méthodes formelles ? .......................................................190
Les sections connexes incluent : ..................................................................191
Défis ....................................................................................................191
Chapitre 8. Projets pragmatiques ..................................................................192
Des équipes pragmatiques ..................................................................................192
Pas de fenêtres cassées ..................................................................193
Grenouilles bouillies .......................................................................................193

Communiquer ....................................................................................193
Ne vous répétez pas.................................................................................194
Orthogonalité .......................................................................................194
Automatisation .......................................................................................196
Savoir quand arrêter d'ajouter de la peinture ..................................196
Les sections connexes incluent : ..................................................................196
Défis ....................................................................................................196
Automatisation ubiquitaire..............................................................................197
Tout en automatique ..................................................................................197
Compilation du projet ......................................................................198
Génération de code..............................................................................198
Tests de régression..............................................................................199
Marque récursive .......................................................................................199
Automatisation de la construction .......................................................................199
Versions finales ....................................................................................200
Administrivia automatique..................................................................200
Génération de sites Web ......................................................................200
Procédures d'approbation ......................................................................201
Les enfants du cordonnier .......................................................................201
Les sections connexes incluent : ..................................................................201
Défis ....................................................................................................202
Tests impitoyables..................................................................................202
Quoi tester..............................................................................................203
Tests unitaires ..................................................................................203
Tests d'intégration .......................................................................204
Validation et vérification .......................................................................204
Épuisement des ressources, erreurs et récupération..............204
Tests de performances ....................................................................205
Tests d'utilisabilité.........................................................................205
Regardez la convivialité en termes de facteurs humains. Y avait-il des miC'est tout
Rédaction..................................................................................................205
Commentaires dans le code..................................................................206
Documents exécutables ....................................................................208
Que faire si mon document n'est pas en texte brut ? ..................................................208
Rédacteurs techniques .......................................................................209
Imprimez-le ou tissez-le ..................................................................209
Langages de balisage.........................................................................210
Les sections connexes incluent : ..................................................................210
Défis ....................................................................................................211
Comment tester ......................................................................................211
Essais de conception/méthodologie ..................................................211
Tests de régression .......................................................................212
Données d'essai ......................................................................................212
Exercer les systèmes GUI ..................................................................213
Tester les tests..............................................................................213
Tester à fond ..................................................................................214
Quand tester ..................................................................................................214
Serrage du filet ..................................................................................215
Les sections connexes comprennent : ..................................................................215
Défis ....................................................................................................215
De grandes attentes.................................................................................216
Communiquer les attentes ..................................................................216
Le mille supplémentaire..............................................................................217
Les sections connexes comprennent : ..................................................................217
Défis ....................................................................................................218
Orgueil et préjugés ...............................................................................218
Annexe A. Ressources ..................................................................................220
Sociétés professionnelles .......................................................................220
Construire une bibliothèque..................................................................................221
Périodiques..............................................................................................221
Documents commerciaux hebdomadaires..............................................................221
Livres ..................................................................................................221
Analyse et conception ..................................................................................222
Equipes et Projets.................................................................................222
Environnements spécifiques.................................................................................222
Le Web ..................................................................................................223
Ressources Internet .......................................................................223
Rédacteurs ...............................................................................................223
Emacs ..................................................................................................223
[URL l] L'éditeur Emacs ................................................................223
[URL 2] L'éditeur XEmacs .............................................................224
vi .......................................................................................................................224
[URL 3] L'éditeur Vim................................................................224
[URL 4] L'éditeur elvis................................................................224
[URL 5] Mode Emacs Viper .........................................................224
Compilateurs, langages et outils de développement .......................224
[URL 6] Le compilateur GNU C/C++................................................224
[URL 7] Le langage Java de Sun .......................................224
[URL 8] Page d'accueil du langage Perl ................................225
[URL 9] Le langage Python................................................................225
[URL 10] PetitEiffel............................................................................225
[URL 11] ISE Eiffel ......................................................................225
[URL 12] Sather ................................................................................225
[URL 13] VisualWorks ................................................................225
[URL 14] L'environnement du langage Squeak ..................225
[URL 15] Le langage de programmation TOM .......................226
[URL 16] Le projet Beowulf ......................................................226
[URL 17] iContract—Outil de conception par contrat pour Java............226

[URL 18] Nana—Journalisation et Assertions pour C et C++............226


[URL 19] DDD–Débogueur d'affichage de données ......................226
[URL 20] Navigateur de refactorisation de John Brant ......................226
[URL 21 ] Générateur de documentation DOC++............226
[URL 22] Cadre de test xUnit–Unit.........................................227
[URL 23] Le langage Tcl ................................................................227
[URL 24] Attendez-vous à Automatiser l'Interaction avec les Programmes .........227
[URL 25] Espaces T.............................................................................227
[URL 26] javaCC—Compilateur-compilateur Java ......................227
[URL 27] Le bison Parser Generator ................................................227
[URL 28] SWIG—Enveloppe simplifiée et générateur d'interface228
[URL 29] Le groupe de gestion d'objets, Inc. ......................228
Outils Unix sous DOS ..................................................................228
[URL 30] Les outils de développement UWIN..................................228
[URL 31 ] Les outils Cygnus Cygwin ................................................228
[URL 32] Outils électriques Perl .......................................................228
Outils de contrôle du code source ..................................................229
[URL 33] RCS—Système de contrôle de révision..............229
[URL 34] CVS—Système de versions simultanées............................229
[URL 35] Gestion de la configuration basée sur les transactions Aegis
..................................................................................................................229
[URL 36] ClearCase ......................................................................229
[URL 37] Intégrité de la source MKS ................................................229
[URL 38] Gestion de la configuration PVCS............................229
[URL 39] Visual SourceSafe ......................................................229
[URL 40] Forcément........................................................................229
Autres outils..............................................................................................230
[URL 41] WinZip—Utilitaire d'archivage pour Windows ......230
[URL 42] Le Z Shell ................................................................................230
[URL 43] Un client SMB gratuit pour les systèmes Unix ......230
Articles et publications ..................................................................230
[URL 44] La FAQ comp.object .........................................................230
[URL 45] Programmation extrême ................................................230
[URL 46] Page d'accueil d'Alistair Cockburn............................231
[URL 47] Page d'accueil de Martin Fowler ......................................231
[URL 48] Page d'accueil de Robert C. Martin.................................231
[URL 49] Programmation orientée aspect..................................231
[URL 50] Spécification JavaSpaces ................................................231
[URL 51] Code source Netscape.........................................................231
[URL 52] Le fichier Jargon ................................................................231
[URL 53] Papiers d'Eric S. Raymond............................................232
[URL 54] L'environnement de bureau K............................................232
[URL 55] Le programme de manipulation d'images GNU ......232
[URL 56] Le projet Demeter ................................................................232

Divers..............................................................................................232
[URL 57] Le projet GNU................................................................232
[URL 58] Informations sur le serveur Web .......................232
Bibliographie ..................................................................................................234
Annexe B. Réponses aux exercices ..................................................................237
Préface

Ce livre vous aidera à devenir un meilleur programmeur.

Peu importe que vous soyez un développeur solitaire, membre d'un grand
équipe de projet ou un consultant travaillant avec plusieurs clients à la fois. Ce livre
vous aidera, en tant qu'individu, à faire un meilleur travail. Ce livre n'est pas
théorique - nous nous concentrons sur des sujets pratiques, sur l'utilisation de votre expérience pour
prendre des décisions plus éclairées. Le mot pragmatique vient du latin
pragmaticus — « compétent en affaires » — lui-même dérivé du grec
, signifiant "faire". C'est un livre sur le faire.

La programmation est un métier. Dans sa forme la plus simple, il s'agit d'obtenir un


ordinateur pour faire ce que vous voulez qu'il fasse (ou ce que votre utilisateur veut qu'il fasse). Comme
un programmeur, vous êtes en partie auditeur, en partie conseiller, en partie interprète et
en partie dictateur. Vous essayez de capturer des exigences insaisissables et de trouver un moyen de
les exprimer pour qu'une simple machine puisse leur rendre justice. Vous essayez de
documentez votre travail pour que les autres puissent le comprendre, et vous essayez de
concevoir votre travail afin que d'autres puissent s'en inspirer. De plus, vous essayez de faire
tout cela contre le tic-tac implacable de l'horloge du projet. Vous travaillez petit
miracles chaque jour.

C'est un travail difficile.

De nombreuses personnes vous proposent leur aide. Les vendeurs d'outils vantent les miracles
leurs produits sont performants. Les gourous de la méthodologie promettent que leurs techniques
garantir les résultats. Tout le monde prétend que son langage de programmation est le
mieux, et chaque système d'exploitation est la réponse à tous les maux imaginables.

Bien sûr, rien de tout cela n'est vrai. Il n'y a pas de réponses faciles. Il n'y a pas de
chose comme meilleure solution, qu'il s'agisse d'un outil, d'un langage ou d'un système d'exploitation.
Il ne peut y avoir que des systèmes plus appropriés dans un ensemble particulier de
circonstances.

C'est là que le pragmatisme entre en jeu. Vous ne devriez pas être marié à
technologie particulière, mais avoir une expérience et une expérience suffisamment larges
base pour vous permettre de choisir de bonnes solutions dans des situations particulières. Ton
l'arrière-plan découle d'une compréhension des principes de base de
l'informatique, et votre expérience provient d'un large éventail de domaines pratiques
projets. La théorie et la pratique se combinent pour vous rendre fort.

Vous adaptez votre approche aux circonstances actuelles et


environnement. Vous jugez de l'importance relative de tous les facteurs affectant une

projet et utilisez votre expérience pour produire des solutions appropriées. Et toi
le faire en continu au fur et à mesure de l'avancement des travaux. Les programmeurs pragmatiques obtiennent
le travail est fait et faites-le bien.

Qui
Qui devrait
devrait lire
lire ce
ce livre
livre ??

Ce livre s'adresse aux personnes qui veulent devenir plus efficaces et plus
programmeurs productifs. Peut-être vous sentez-vous frustré de ne pas avoir l'air
réaliser votre potentiel. Peut-être regardez-vous des collègues qui semblent
utiliser des outils pour se rendre plus productifs que vous. Peut-être que votre
le travail actuel utilise des technologies plus anciennes et vous voulez savoir comment les nouvelles idées
peut être appliqué à ce que vous faites.

Nous ne prétendons pas avoir toutes (ou même la plupart) des réponses, et tous nos
des idées applicables dans toutes les situations. Tout ce que nous pouvons dire, c'est que si vous suivez notre
approche, vous acquerrez rapidement de l'expérience, votre productivité augmentera,
et vous aurez une meilleure compréhension de l'ensemble du processus de développement.
Et vous écrirez de meilleurs logiciels.

Qu'est-ce
Qu'est-ce qui
qui fait
fait un
un programmeur
programmeur pragmatique
pragmatique ??

Chaque développeur est unique, avec ses propres forces et faiblesses,


préférences et aversions. Au fil du temps, chacun créera son propre
environnement. Cet environnement reflétera l'individualité du programmeur
avec autant de force que ses passe-temps, ses vêtements ou sa coupe de cheveux. Toutefois, si
vous êtes un programmeur pragmatique, vous partagerez bon nombre des éléments suivants
caractéristiques:

• • Adopteur précoce/adaptateur rapide. Vous avez l'instinct de


technologies et techniques, et vous aimez essayer des choses. Quand
donné quelque chose de nouveau, vous pouvez le saisir rapidement et l'intégrer avec
le reste de vos connaissances. Votre confiance naît de l'expérience.
• • Curieux. Vous avez tendance à poser des questions. C'est chouette—comment avez-vous
vous faites cela? Avez-vous eu des problèmes avec cette bibliothèque ? Qu'est-ce que c'est ça
BeOS dont j'ai entendu parler ? Comment les liens symboliques sont-ils implémentés ? Toi
êtes un rat de meute pour de petits faits, dont chacun peut affecter une décision
il y a des années.
• • Penseur critique. Vous prenez rarement les choses comme données sans d'abord
obtenir les faits. Quand les collègues disent « parce que c'est comme ça
fait », ou un fournisseur promet la solution à tous vos problèmes, vous
sentir un défi.
• • Réaliste. Vous essayez de comprendre la nature sous-jacente de chaque
problème auquel vous faites face. Ce réalisme vous donne une bonne idée de la difficulté
les choses sont, et combien de temps les choses prendront. Comprendre par soi-même

qu'un processus devrait être difficile ou prendra du temps à se terminer


vous donne l'endurance nécessaire pour continuer.
• • Homme à tout faire. Vous vous efforcez de vous familiariser avec un large
gamme de technologies et d'environnements, et vous travaillez pour garder
au courant des nouveautés. Même si votre emploi actuel peut exiger
vous d'être un spécialiste, vous pourrez toujours passer à de nouveaux domaines
et de nouveaux défis.

Nous avons laissé les caractéristiques les plus élémentaires pour la fin. Tout pragmatique
Les programmeurs les partagent. Ils sont assez basiques pour être cités comme conseils :

Astuce
Astuce 11

Prenez soin de votre métier

Nous estimons qu'il ne sert à rien de développer un logiciel si vous ne vous souciez pas de
le faire bien.

Astuce
Astuce 22

Penser! À propos de votre travail

Afin d'être un programmeur pragmatique, nous vous mettons au défi de penser


sur ce que vous faites pendant que vous le faites. Il ne s'agit pas d'un audit ponctuel de
pratiques actuelles - il s'agit d'une évaluation critique continue de chaque décision que vous
faire, chaque jour, et sur chaque développement. Ne faites jamais fonctionner le pilote automatique.
Pensez
La constamment,
devise critiquez
de l'entreprise, THINK!,votre
est letravail
mantraen du
temps réel. L'ancien
programmeur IBM
pragmatique.

Si cela vous semble être un travail acharné, alors vous faites preuve de réalisme
caractéristique. Cela va prendre une partie de votre temps précieux—du temps
qui est probablement déjà sous une pression énorme. La récompense est un plus
une implication active dans un travail que vous aimez, un sentiment de maîtrise sur un
gamme croissante de sujets, et le plaisir d'un sentiment de
amélioration. À long terme, votre investissement en temps sera remboursé comme
vous et votre équipe devenez plus efficaces, écrivez du code plus facile à
maintenir et passer moins de temps en réunion.

Pragmatistes
Pragmatistes individuels,
individuels, grandes
grandes équipes
équipes

Certaines personnes pensent qu'il n'y a pas de place pour l'individualité dans les grandes équipes ou
projets complexes. "La construction de logiciels est une discipline d'ingénierie", ont-ils

dire, "qui tombe en panne si les membres individuels de l'équipe prennent des décisions pour
eux-mêmes."

Nous ne sommes pas d'accord.

La construction de logiciels devrait être une discipline d'ingénierie. Cependant,


cela n'empêche pas l'artisanat individuel. Pensez au grand
cathédrales construites en Europe au Moyen Âge. Chacun a pris des milliers de
années-personnes d'effort, réparties sur plusieurs décennies. Les leçons apprises ont été
transmis au prochain ensemble de constructeurs, qui ont fait progresser l'état de
l'ingénierie structurelle avec leurs réalisations. Mais les charpentiers,
tailleurs de pierre, sculpteurs et verriers étaient tous des artisans, interprétant
les exigences d'ingénierie pour produire un ensemble qui transcende le
côté purement mécanique de la construction. C'était leur croyance en leur
contributions individuelles qui ont soutenu les projets :

Nous qui ne taillons que des pierres devons toujours envisager des cathédrales.

-- Credo
Credo du
du travailleur
travailleur de
de la
la carrière
carrière

Dans la structure globale d'un projet, il y a toujours de la place pour


individualité et savoir-faire. Cela est particulièrement vrai compte tenu du contexte actuel
état du génie logiciel. Dans cent ans, notre
l'ingénierie peut sembler aussi archaïque que les techniques utilisées par l'époque médiévale
les constructeurs de cathédrales semblent aux ingénieurs civils d'aujourd'hui, tandis que notre savoir-faire
sera toujours honoré.

C'est
C'est un
un processus
processus continu
continu

Un touriste visitant l'Eton College en Angleterre a demandé au jardinier comment il avait obtenu le
pelouses si parfaites. « C'est facile », répondit-il, « Il suffit d'enlever la rosée tous les
matin, tondez-les tous les deux jours et roulez-les une fois par semaine."

"Est-ce tout?" demanda le touriste.

« Absolument », répondit le jardinier. "Fais ça pendant 500 ans et tu auras un


belle pelouse aussi."

Les grandes pelouses ont besoin de petites quantités de soins quotidiens, et elles sont donc excellentes
programmeurs. Les consultants en gestion aiment laisser tomber le mot kaizen dans
conversations. "Kaizen" est un terme japonais qui résume le concept de
apporter continuellement de nombreuses petites améliorations. Il était considéré comme
l'une des principales raisons des gains spectaculaires de productivité et de qualité
dans la fabrication japonaise et a été largement copié dans le monde entier.
Kaizen s'applique aussi aux particuliers. Chaque jour, travaillez pour affiner les compétences que vous
avoir et d'ajouter de nouveaux outils à votre répertoire. Contrairement aux pelouses d'Eton, vous
commencer à voir des résultats en quelques jours. Au fil des ans, vous serez étonné de
comment votre expérience s'est épanouie et vos compétences ont grandi.

Comment
Comment le
le livre
livre est
est organisé
organisé

Ce livre est écrit comme une collection de courtes sections. Chaque rubrique est
autonome et aborde un sujet particulier. Vous trouverez de nombreuses croix
références, qui aident à mettre chaque sujet en contexte. N'hésitez pas à lire le
sections dans n'importe quel ordre - ce n'est pas un livre que vous devez lire d'un bout à l'autre.

De temps à autre, vous rencontrerez une case intitulée Conseil nn (telle que Conseil 1, "Soin
À propos de votre métier" à la page xix). En plus de souligner des points dans le texte,
nous pensons que les pourboires ont leur propre vie - nous les suivons quotidiennement. Vous trouverez un
résumé de tous les conseils sur une carte détachable à l'intérieur de la couverture arrière.

L'annexe A contient un ensemble de ressources : la bibliographie du livre, une liste de


URL vers des ressources Web et une liste de périodiques, livres et
organisations professionnelles. Tout au long du livre, vous trouverez des références à
la bibliographie et la liste des URL, telles que [ KP99 ] et [URL 18],
respectivement.

Nous avons inclus des exercices et des défis, le cas échéant. Des exercices
ont normalement des réponses relativement simples, tandis que les défis sont
plus ouvert. Pour vous donner une idée de notre réflexion, nous avons inclus notre
réponses aux exercices de l'annexe B , mais très peu ont une seule réponse correcte.
solution. Les défis peuvent former la base de discussions de groupe ou d'essais
travailler dans des cours de programmation avancés.

Qu'est-ce
Qu'est-ce qu'il
qu'il yy aa dans
dans un
un nom?
nom?

"Quand j'utilise un mot," dit Humpty Dumpty, d'un ton plutôt méprisant, "il
signifie exactement ce que je choisis qu'il signifie - ni plus ni moins."

Lewis
Lewis Carroll,
Carroll, De
De l'autre
l'autre côté
côté du
du miroir
miroir

Dispersés tout au long du livre, vous trouverez divers morceaux de jargon—soit


parfaitement bons mots anglais qui ont été corrompus pour signifier quelque chose
mots inventés techniques ou horribles auxquels on a attribué des significations
par des informaticiens qui en veulent au langage. La première fois
nous utilisons chacun de ces mots de jargon, nous essayons de le définir, ou au moins de donner un indice
à sa signification. Cependant, nous sommes sûrs que certains sont tombés à travers le
les fissures, et d'autres, telles que l'objet et la base de données relationnelle, sont en commun
assez d'utilisation qu'ajouter une définition serait ennuyeux. Si tu viens
sur un terme que vous n'avez jamais vu auparavant, ne le sautez pas. Prendre

le temps de le chercher, peut-être sur le Web, ou peut-être dans une informatique


cahier de texte. Et, si vous en avez l'occasion, envoyez-nous un e-mail et portez plainte, afin que nous
peut ajouter une définition à la prochaine édition.

Après avoir dit tout cela, nous avons décidé de nous venger de l'ordinateur
scientifiques. Parfois, il existe de très bons mots de jargon pour les concepts,
mots que nous avons décidé d'ignorer. Pourquoi? Parce que le jargon existant est
normalement limité à un domaine de problème particulier, ou à une phase particulière
de développement. Cependant, l'une des philosophies de base de ce livre est que
la plupart des techniques que nous préconisons sont universelles : modularité
s'applique au code, aux conceptions, à la documentation et à l'organisation de l'équipe, par
exemple. Lorsque nous avons voulu utiliser le mot du jargon conventionnel dans un sens plus large
contexte, c'est devenu déroutant - nous ne semblions pas pouvoir surmonter les bagages
terme original apporté avec lui. Lorsque cela s'est produit, nous avons contribué au
déclin de la langue en inventant nos propres termes.

Code
Code source
source et
et autres
autres ressources
ressources
La plupart du code présenté dans ce livre est extrait d'une source compilable
fichiers, disponibles en téléchargement sur notre site Web :

http://www.pragmaticprogrammer.com

Vous y trouverez également des liens vers des ressources que nous jugeons utiles, ainsi que des mises à jour
au livre et aux nouvelles des autres développements du programmeur pragmatique.

Envoyez-nous
Envoyez-nous vos
vos commentaires
commentaires

Nous apprécierions avoir de vos nouvelles. Commentaires, suggestions, erreurs dans le


texte, et les problèmes dans les exemples sont tous les bienvenus. Envoyez-nous un courriel à

ppbook@pragmaticprogrammer.com

Remerciements
Remerciements

Quand nous avons commencé à écrire ce livre, nous n'avions aucune idée du degré d'équipe
effort qu'il finirait par être.

Addison-Wesley a été brillant, prenant quelques mouillages derrière les oreilles


hackers et nous guidant tout au long du processus de production de livres, de
idée de copie prête à photographier. Un grand merci à John Wait et Meera
Ravindiran pour leur soutien initial, Mike Hendrickson, notre enthousiaste

rédacteur en chef (et un concepteur de couverture moyen!), Lorraine Ferrier et John Fuller pour
leur aide à la production, et l'infatigable Julie DeBaggis pour
nous gardant tous ensemble.

Ensuite, il y avait les critiques : Greg Andress, Mark Cheers, Chris


Cleeland, Alistair Cockburn, Ward Cunningham, Martin Fowler, Thanh T.
Giang, Robert L. Glass, Scott Henninger, Michael Hunter, Brian Kirby,
John Lakos, Pete McBreen, Carey P. Morris, Jared Richardson, Kevin
Ruland, Eric Starr, Eric Vought, Chris Van Wyk et Deborra Zukowski.
Sans leurs commentaires attentifs et leurs précieuses idées, ce livre serait
moins lisible, moins précis et deux fois plus long. Merci à tous pour votre temps
et la sagesse.

La deuxième impression de ce livre a grandement bénéficié des yeux d'aigle de nos


lecteurs. Un grand merci à Brian Blank, Paul Boal, Tom Ekberg, Brent
Fulgham, Louis Paul Hébert, Henk-Jan Olde Loohuis, Alan Lund, Gareth
McCaughan, Yoshiki Shibata et Volker Wurst, tous deux pour avoir trouvé le
erreurs et d'avoir eu la grâce de les signaler avec douceur.

Au fil des ans, nous avons travaillé avec un grand nombre de clients progressistes,
où nous avons acquis et affiné l'expérience dont nous parlons ici. Récemment,
nous avons eu la chance de travailler avec Peter Gehrke sur plusieurs grands projets.
Son soutien et son enthousiasme pour nos techniques sont très appréciés.

Ce livre a été produit en utilisant LATEX, pic, Perl, dvips, ghostview, ispell,
Marque GNU, CVS, Emacs, XEmacs, EGCS, GCC, Java, iContract et
SmallEiffel, utilisant les shells Bash et zsh sous Linux. Le stupéfiant
Le fait est que tous ces logiciels formidables sont disponibles gratuitement. Nous devons une
un immense "merci" aux milliers de programmeurs pragmatiques du monde entier
qui ont contribué à ces travaux et à d'autres pour nous tous. Nous aimerions particulièrement
remercier Reto Kramer pour son aide avec iContract.

Enfin, mais non des moindres, nous avons une énorme dette envers nos familles. Non seulement ont
ils supportent des dactylographies tardives, d'énormes factures de téléphone et nos permanents
air de distraction, mais ils ont eu la grâce de lire ce que nous avons écrit,
fois après fois. Merci de nous faire rêver.

Andy Chasse
David Thomas

Qu'est-ce
Qu'est-ce qu'il
qu'il yy aa dans
dans un
un nom?
nom?

"Quand j'utilise un mot," dit Humpty Dumpty, d'un ton plutôt méprisant, "il
signifie exactement ce que je choisis qu'il signifie - ni plus ni moins."

Lewis
Lewis Carroll,
Carroll, De
De l'autre
l'autre côté
côté du
du miroir
miroir

Dispersés tout au long du livre, vous trouverez divers morceaux de jargon—soit


parfaitement bons mots anglais qui ont été corrompus pour signifier quelque chose
mots inventés techniques ou horribles auxquels on a attribué des significations
par des informaticiens qui en veulent au langage. La première fois
nous utilisons chacun de ces mots de jargon, nous essayons de le définir, ou au moins de donner un indice
à sa signification. Cependant, nous sommes sûrs que certains sont tombés à travers le
les fissures, et d'autres, telles que l'objet et la base de données relationnelle, sont en commun
assez d'utilisation qu'ajouter une définition serait ennuyeux. Si tu viens
sur un terme que vous n'avez jamais vu auparavant, ne le sautez pas. Prendre
le temps de le chercher, peut-être sur le Web, ou peut-être dans une informatique
cahier de texte. Et, si vous en avez l'occasion, envoyez-nous un e-mail et portez plainte, afin que nous
peut ajouter une définition à la prochaine édition.

Après avoir dit tout cela, nous avons décidé de nous venger de l'ordinateur
scientifiques. Parfois, il existe de très bons mots de jargon pour les concepts,
mots que nous avons décidé d'ignorer. Pourquoi? Parce que le jargon existant est
normalement limité à un domaine de problème particulier, ou à une phase particulière
de développement. Cependant, l'une des philosophies de base de ce livre est que
la plupart des techniques que nous préconisons sont universelles : modularité
s'applique au code, aux conceptions, à la documentation et à l'organisation de l'équipe, par
exemple. Lorsque nous avons voulu utiliser le mot du jargon conventionnel dans un sens plus large
contexte, c'est devenu déroutant - nous ne semblions pas pouvoir surmonter les bagages
terme original apporté avec lui. Lorsque cela s'est produit, nous avons contribué au
déclin de la langue en inventant nos propres termes.

Code
Code source
source et
et autres
autres ressources
ressources

La plupart du code présenté dans ce livre est extrait d'une source compilable
fichiers, disponibles en téléchargement sur notre site Web :

http://www.pragmaticprogrammer.com

Vous y trouverez également des liens vers des ressources que nous jugeons utiles, ainsi que des mises à jour
au livre et aux nouvelles des autres développements du programmeur pragmatique.

Envoyez-nous
Envoyez-nous vos
vos commentaires
commentaires

Nous apprécierions avoir de vos nouvelles. Commentaires, suggestions, erreurs dans le


texte, et les problèmes dans les exemples sont tous les bienvenus. Envoyez-nous un courriel à
ppbook@pragmaticprogrammer.com

Remerciements
Remerciements

Quand nous avons commencé à écrire ce livre, nous n'avions aucune idée du degré d'équipe
effort qu'il finirait par être.

Addison-Wesley a été brillant, prenant quelques mouillages derrière les oreilles


hackers et nous guidant tout au long du processus de production de livres, de
idée de copie prête à photographier. Un grand merci à John Wait et Meera
Ravindiran pour leur soutien initial, Mike Hendrickson, notre enthousiaste
rédacteur en chef (et un concepteur de couverture moyen!), Lorraine Ferrier et John Fuller pour
leur aide à la production, et l'infatigable Julie DeBaggis pour
nous gardant tous ensemble.

Ensuite, il y avait les critiques : Greg Andress, Mark Cheers, Chris


Cleeland, Alistair Cockburn, Ward Cunningham, Martin Fowler, Thanh T.
Giang, Robert L. Glass, Scott Henninger, Michael Hunter, Brian Kirby,
John Lakos, Pete McBreen, Carey P. Morris, Jared Richardson, Kevin
Ruland, Eric Starr, Eric Vought, Chris Van Wyk et Deborra Zukowski.
Sans leurs commentaires attentifs et leurs précieuses idées, ce livre serait
moins lisible, moins précis et deux fois plus long. Merci à tous pour votre temps
et la sagesse.

La deuxième impression de ce livre a grandement bénéficié des yeux d'aigle de nos


lecteurs. Un grand merci à Brian Blank, Paul Boal, Tom Ekberg, Brent
Fulgham, Louis Paul Hébert, Henk-Jan Olde Loohuis, Alan Lund, Gareth
McCaughan, Yoshiki Shibata et Volker Wurst, tous deux pour avoir trouvé le
erreurs et d'avoir eu la grâce de les signaler avec douceur.

Au fil des ans, nous avons travaillé avec un grand nombre de clients progressistes,
où nous avons acquis et affiné l'expérience dont nous parlons ici. Récemment,
nous avons eu la chance de travailler avec Peter Gehrke sur plusieurs grands projets.
Son soutien et son enthousiasme pour nos techniques sont très appréciés.

Ce livre a été produit en utilisant LATEX, pic, Perl, dvips, ghostview, ispell,
Marque GNU, CVS, Emacs, XEmacs, EGCS, GCC, Java, iContract et
SmallEiffel, utilisant les shells Bash et zsh sous Linux. Le stupéfiant

Le fait est que tous ces logiciels formidables sont disponibles gratuitement. Nous devons une
un immense "merci" aux milliers de programmeurs pragmatiques du monde entier
qui ont contribué à ces travaux et à d'autres pour nous tous. Nous aimerions particulièrement
remercier Reto Kramer pour son aide avec iContract.

Enfin, mais non des moindres, nous avons une énorme dette envers nos familles. Non seulement ont
ils supportent des dactylographies tardives, d'énormes factures de téléphone et nos permanents
air de distraction, mais ils ont eu la grâce de lire ce que nous avons écrit,
fois après fois. Merci de nous faire rêver.

Andy Chasse

David Thomas

Le
Le chat
chat aa mangé
mangé mon
mon code
code source
source

La plus grande de toutes les faiblesses est la peur de paraître faible.

JB
JB Bossuet,
Bossuet, Politique
Politique d'après
d'après les
les Saintes
Saintes Écritures,
Écritures, 1709
1709

L'une des pierres angulaires de la philosophie pragmatique est l'idée de prendre


la responsabilité de vous-même et de vos actions en termes de carrière
votre avancement, votre projet et votre travail au quotidien. Un Pragmatique
Le programmeur prend en charge sa propre carrière et n'a pas peur de l'admettre
ignorance ou erreur. Ce n'est pas l'aspect le plus agréable de la programmation, d'être
bien sûr, mais cela arrivera, même sur le meilleur des projets. Malgré une
tests, une bonne documentation et une automatisation solide, les choses tournent mal.
Les livraisons sont en retard. Des problèmes techniques imprévus surgissent.

Ces choses arrivent, et nous essayons de les gérer avec autant de professionnalisme que nous
peut. Cela signifie être honnête et direct. Nous pouvons être fiers de nos capacités,
mais nous devons être honnêtes à propos de nos défauts - notre ignorance ainsi que
nos erreurs.

Prendre
Prendre la
la responsabilité
responsabilité

La responsabilité est quelque chose que vous acceptez activement. Vous vous engagez
pour s'assurer que quelque chose est bien fait, mais vous n'avez pas nécessairement
contrôle sur tous les aspects de celui-ci. En plus de faire de son mieux,
vous devez analyser la situation pour les risques qui sont hors de votre contrôle. Toi
ont le droit de ne pas assumer la responsabilité d'une situation impossible, ou
celui où les risques sont trop grands. Vous devrez passer l'appel en fonction de
votre propre éthique et votre propre jugement.

Lorsque vous acceptez la responsabilité d'un résultat, vous devez vous attendre à
en être tenu pour responsable. Lorsque vous faites une erreur (comme nous le faisons tous) ou un
erreur de jugement, admettez-la honnêtement et essayez de proposer des options.

Ne blâmez pas quelqu'un ou quelque chose d'autre, et n'inventez pas d'excuse. Ne blâmez pas
tous les problèmes d'un fournisseur, d'un langage de programmation, de gestion ou
vos collègues. Tout cela peut jouer un rôle, mais c'est à vous de
proposer des solutions, pas des excuses.

S'il y avait un risque que le fournisseur ne vienne pas pour vous, alors vous
aurait dû avoir un plan d'urgence. Si le disque tombe en panne, prenant tout votre
code source avec - et vous n'avez pas de sauvegarde, c'est de votre faute. Récit
votre patron "le chat a mangé mon code source" ne le coupera tout simplement pas.

Astuce
Astuce 33

Fournissez des options, ne faites pas d'excuses boiteuses

Avant d'approcher quelqu'un pour lui dire pourquoi quelque chose ne peut pas être fait,
en retard ou en panne, arrêtez-vous et écoutez-vous. Parlez au canard en plastique sur
votre moniteur, ou le chat. Votre excuse semble-t-elle raisonnable ou stupide ?
Comment ça va sonner à votre patron ?

Parcourez la conversation dans votre esprit. Quelle est la probabilité de l'autre personne
dire? Vont-ils demander : « Avez-vous essayé ceci… » ou « N'y avez-vous pas pensé ? »
Comment allez-vous répondre ? Avant d'aller leur annoncer la mauvaise nouvelle, y a-t-il
autre chose que vous pouvez essayer? Parfois, vous savez juste ce qu'ils vont faire
dites, alors épargnez-leur la peine.

Au lieu d'excuses, proposez des options. Ne dites pas que cela ne peut pas être fait; Expliquer quoi
peut être fait pour sauver la situation. Le code doit-il être jeté?
Éduquez-les sur la valeur du refactoring (voir Refactoring ). Avez-vous besoin de
passer du temps à prototyper pour déterminer la meilleure façon de procéder (voir
Prototypes et Post-it ) ? Avez-vous besoin d'introduire de meilleurs tests (voir
Code That's Easy to Test et Ruthless Testing) ou l'automatisation (voir
Ubiquitous Automation) pour éviter que cela se reproduise ? Peut-être toi
besoin de ressources supplémentaires. N'ayez pas peur de demander ou d'admettre que vous avez besoin
aider.

Essayez de débusquer les excuses boiteuses avant de les exprimer à haute voix. Si tu dois,
dites-le d'abord à votre chat. Après tout, si le petit Tiddles doit être blâmé….

Les
Les sections
sections connexes
connexes comprennent
comprennent ::
• • Prototypes et Post-it
• • Refactorisation
• • Code facile à tester
• • Automatisation omniprésente
• • Tests impitoyables

Défis
Défis

• • Comment réagissez-vous lorsque quelqu'un, comme un caissier de banque, un


mécanicien, ou un commis - vient à vous avec une excuse boiteuse ? Que faites-vous
pensez à eux et à leur entreprise en conséquence ?

Entropie
Entropie logicielle
logicielle

Alors que le développement logiciel est à l'abri de presque toutes les lois physiques,
l'entropie nous frappe durement. L'entropie est un terme de la physique qui fait référence à la
quantité de "désordre" dans un système. Malheureusement, les lois de
la thermodynamique garantit que l'entropie dans l'univers tend vers une
maximum. Lorsque le désordre augmente dans les logiciels, les programmeurs l'appellent
"pourriture logicielle."

De nombreux facteurs peuvent contribuer à la pourriture des logiciels. Le plus


l'important semble être la psychologie, ou la culture, à l'œuvre sur un projet.
Même si vous êtes une équipe, la psychologie de votre projet peut être très
chose délicate. Malgré les meilleurs plans et les meilleures personnes, un projet peut
connaît encore la ruine et la décadence au cours de sa vie. Pourtant il y a d'autres
des projets qui, malgré d'énormes difficultés et des revers constants,
combattre avec succès la tendance de la nature au désordre et réussir à venir
assez bien.

Qu'est-ce qui fait la différence ?

Dans les centres-villes, certains bâtiments sont beaux et propres, tandis que d'autres sont
carcasses pourrissantes. Pourquoi? Chercheurs dans le domaine de la criminalité et de la dégradation urbaine
découvert un mécanisme de déclenchement fascinant, qui transforme très rapidement un
bâtiment propre, intact et habité en une épave détruite et abandonnée
[ WK82].

Une vitre brisée.

Une fenêtre cassée, laissée non réparée pendant une longue période,
inculque aux habitants de l'immeuble un sentiment d'abandon, un sentiment
que les pouvoirs en place ne se soucient pas du bâtiment. Donc une autre fenêtre
se casse. Les gens commencent à jeter des ordures. Des graffitis apparaissent. Structurel sérieux

les dégâts commencent. En un laps de temps relativement court, le bâtiment devient


endommagé au-delà du désir du propriétaire de le réparer, et le sentiment d'abandon
devient réalité.

La "Broken Window Theory" a inspiré les services de police de New York


et d'autres grandes villes pour sévir contre les petites choses afin de rester à l'écart
les gros trucs. Ça marche : se tenir au courant des fenêtres brisées, des graffitis et autres
les petites infractions ont réduit le niveau de criminalité grave.

Astuce
Astuce 44

Ne vivez pas avec des fenêtres cassées


Ne laissez pas de "fenêtres brisées" (mauvaises conceptions, mauvaises décisions ou mauvais code)
non réparé. Corrigez chacun d'entre eux dès qu'il est découvert. S'il n'y a pas assez
le temps de le réparer correctement, puis de le monter. Peut-être pouvez-vous commenter le
code incriminé, ou afficher un message "Non implémenté", ou remplacer
données factices à la place. Prenez des mesures pour éviter d'autres dommages et
montrez que vous maîtrisez la situation.

Nous avons vu des systèmes propres et fonctionnels se détériorer assez rapidement une fois
les fenêtres commencent à se casser. Il existe d'autres facteurs qui peuvent contribuer à
logiciel pourriture, et nous aborderons certains d'entre eux ailleurs, mais négligez
accélère la pourriture plus rapidement que tout autre facteur.

Vous pensez peut-être que personne n'a le temps de nettoyer tout


le verre brisé d'un projet. Si vous continuez à penser comme ça, alors vous
mieux vaut prévoir d'acheter une benne à ordures ou de déménager dans un autre quartier.
Ne laissez pas l'entropie gagner.

Éteindre
Éteindre les
les feux
feux

En revanche, il y a l'histoire d'une connaissance obscènement riche d'Andy.


Sa maison était impeccable, belle, chargée d'antiquités inestimables, d'objets
d'art, etc. Un jour, une tapisserie accrochée un peu trop près de
la cheminée de son salon a pris feu. Les pompiers se sont précipités pour
sauver la journée et sa maison. Mais avant qu'ils traînent leurs gros tuyaux sales
dans la maison, ils s'arrêtèrent - avec le feu qui faisait rage - pour dérouler une natte
entre la porte d'entrée et la source de l'incendie.

Ils ne voulaient pas salir le tapis.

Un cas assez extrême, certes, mais c'est comme ça que ça doit être avec
logiciel. Une fenêtre cassée - un morceau de code mal conçu, un mauvais
décision de gestion avec laquelle l'équipe doit vivre pendant la durée de la
projet— c'est tout ce qu'il faut pour amorcer le déclin. Si vous vous retrouvez à travailler sur un
projet avec pas mal de fenêtres brisées, il est trop facile de se glisser dans le
état d'esprit de "Tout le reste de ce code est de la merde, je vais juste suivre le mouvement." Ce n'est pas
peu importe si le projet a bien fonctionné jusqu'à présent. Dans la version originale
expérience menant à la "théorie de la fenêtre brisée", une voiture abandonnée était assise
pendant une semaine intacte. Mais une fois qu'une seule fenêtre a été brisée, la voiture a été
dépouillé et retourné en quelques heures.

De même, si vous vous retrouvez dans une équipe et un projet où le


le code est d'une beauté immaculée - proprement écrit, bien conçu et
élégant - vous ferez probablement très attention à ne pas le gâcher, tout comme
les pompiers. Même s'il y a un incendie qui fait rage (date limite, date de sortie, commerce
montrer la démo, etc.), vous ne voulez pas être le premier à faire des bêtises.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Soupe aux cailloux et grenouilles bouillies


• • Refactorisation
• • Des équipes pragmatiques

Défis
Défis

• • Contribuez à renforcer votre équipe en surveillant votre informatique


"quartier." Choisissez deux ou trois "fenêtres brisées" et discutez
avec vos collègues quels sont les problèmes et ce qui pourrait être fait
pour les réparer.
• • Pouvez-vous dire quand une fenêtre est brisée pour la première fois ? Quel est ton
réaction? Si c'était le résultat de la décision de quelqu'un d'autre, ou d'un
édit de gestion, que pouvez-vous faire à ce sujet ?
Soupe
Soupe aux
aux pierres
pierres et
et grenouilles
grenouilles bouillies
bouillies
Les trois soldats rentrant de la guerre avaient faim. Quand ils ont vu
le village devant leurs esprits remontés - ils étaient sûrs que les villageois
leur donner un repas. Mais quand ils y sont arrivés, ils ont trouvé les portes verrouillées et
les fenêtres fermées. Après de nombreuses années de guerre, les villageois manquaient de
nourriture et thésaurisent ce qu'ils ont.

Sans se décourager, les soldats ont fait bouillir une casserole d'eau et ont soigneusement placé trois
pierres dedans. Les villageois stupéfaits sont sortis pour regarder.

"C'est de la soupe aux cailloux", ont expliqué les soldats. « C'est tout ce que tu as mis dedans ? demandé
les villageois. "Absolument, même si certains disent que c'est encore meilleur avec un
quelques carottes…." Un villageois s'enfuit, revenant en peu de temps avec un panier de
carottes de son trésor.

Quelques minutes plus tard, les villageois ont de nouveau demandé "C'est ça?"

"Eh bien," dirent les soldats, "quelques pommes de terre lui donnent du corps." Off a couru un autre
villageois.

Au cours de l'heure qui a suivi, les soldats ont énuméré d'autres ingrédients susceptibles d'améliorer
la soupe : bœuf, poireaux, sel et herbes. Chaque fois qu'un villageois différent
courir pour piller leurs magasins personnels.

Finalement, ils avaient produit une grande marmite de soupe fumante. Les soldats
enlevé les pierres, et ils se sont assis avec tout le village pour profiter de la
premier repas carré que l'un d'entre eux avait mangé depuis des mois.

Il y a quelques morales dans l'histoire de la soupe aux pierres. Les villageois sont
trompés par les soldats, qui utilisent la curiosité des villageois pour obtenir de la nourriture
eux. Mais plus important encore, les soldats agissent comme un catalyseur, amenant le
village ensemble afin qu'ils puissent produire ensemble quelque chose qu'ils ne pourraient pas
ont fait par eux-mêmes - un résultat synergique. Finalement tout le monde gagne.

De temps en temps, vous voudrez peut-être imiter les soldats.

Vous pouvez être dans une situation où vous savez exactement ce qui doit être fait et
comment faire. L'ensemble du système apparaît juste devant vos yeux - vous savez que c'est
droite. Mais demandez la permission d'aborder le tout et vous serez accueilli
retards et regards vides. Les gens formeront des comités, les budgets auront besoin
l'approbation, et les choses vont se compliquer. Chacun gardera le sien
ressources. Parfois, cela s'appelle la "fatigue du démarrage".

Il est temps de sortir les pierres. Déterminez ce que vous pouvez raisonnablement demander.
Développez-le bien. Une fois que vous l'avez, montrez aux gens et laissez-les s'émerveiller. Alors
dire "bien sûr, ce serait mieux si on ajoutait…." Faire comme si ce n'était pas important.
Asseyez-vous et attendez qu'ils commencent à vous demander d'ajouter la fonctionnalité que vous
voulu à l'origine. Les gens trouvent plus facile de rejoindre un succès continu. Montrer
leur donner un aperçu de l'avenir et vous les inciterez à se rallier. [1]

[1] En faisant cela, vous serez peut-être rassuré par la ligne attribuée au contre-amiral Dr. Grace Hopper : "Il est plus facile de demander

pardon que d'obtenir la permission."

Astuce
Astuce 55

Soyez un catalyseur du changement


Le
Le côté
côté des
des villageois
villageois

D'un autre côté, l'histoire de la soupe aux pierres est aussi une histoire douce et graduelle.
tromperie. Il s'agit de se concentrer trop étroitement. Les villageois pensent à la
pierres et oublier le reste du monde. Nous y craquons tous, tous les jours.
Les choses nous tombent dessus.

Nous avons tous vu les symptômes. Les projets sortent lentement et inexorablement totalement
de main. La plupart des sinistres logiciels commencent trop petits pour être remarqués, et la plupart
les dépassements de projet se produisent un jour à la fois. Les systèmes dérivent de leur
spécifications fonctionnalité par fonctionnalité, tandis que patch après patch est ajouté à un
morceau de code jusqu'à ce qu'il ne reste plus rien de l'original. C'est souvent le
accumulation de petites choses qui casse le moral et les équipes.

Astuce
Astuce 66

Rappelez-vous la vue d'ensemble

Nous n'avons jamais essayé cela - honnêtement. Mais ils disent que si vous prenez une grenouille et
déposez-le dans de l'eau bouillante, il ressortira tout de suite. Toutefois, si
vous placez la grenouille dans une casserole d'eau froide, puis la chauffez progressivement, la grenouille
ne remarquera pas la lente augmentation de la température et restera en place jusqu'à ce que
cuit.

Notez que le problème de la grenouille est différent du problème des fenêtres cassées
discuté dans la section. 2Dans la théorie de la fenêtre brisée, les gens perdent la volonté
pour combattre l'entropie parce qu'ils perçoivent que personne d'autre ne s'en soucie. La grenouille juste
ne remarque pas le changement.

Ne soyez pas comme la grenouille. Gardez un œil sur la situation dans son ensemble. Révisez constamment
ce qui se passe autour de vous, pas seulement ce que vous faites personnellement.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Entropie logicielle
• • Programmation par coïncidence
• • Refactorisation
• • La fosse aux exigences

• • Des équipes pragmatiques

Défis
Défis

• • Lors de la révision d'une ébauche de ce livre, John Lakos a soulevé la question


problème suivant : Les militaires trompent progressivement les villageois, mais
le changement qu'ils catalysent leur fait du bien à tous. Cependant, par
en trompant progressivement la grenouille, vous lui faites du mal. Peux-tu
déterminez si vous préparez une soupe aux cailloux ou une soupe aux grenouilles lorsque vous
essayer de catalyser le changement ? La décision est-elle subjective ou objective ?

Logiciel
Logiciel assez
assez bon
bon

En nous efforçant de nous améliorer, nous gâchons souvent ce qui va bien.

Roi
Roi Lear
Lear 1.4
1.4

Il y a une vieille blague à propos d'une entreprise américaine qui passe une commande pour
100 000 circuits intégrés avec un fabricant japonais. Partie de la
spécification était le taux de défauts : une puce sur 10 000. Quelques semaines plus tard, le
la commande est arrivée : une grande boîte contenant des milliers de circuits intégrés et une petite
n'en contenant que dix. Attachée à la petite boîte se trouvait une étiquette qui disait : "Ces
sont les fautifs."

Si seulement nous avions vraiment ce genre de contrôle sur la qualité. Mais le monde réel
ne nous laissera tout simplement pas produire beaucoup de choses vraiment parfaites, en particulier pas sans bogues
logiciel. Le temps, la technologie et le tempérament conspirent tous contre nous.

Cependant, cela ne doit pas être frustrant. Comme Ed Yourdon l'a décrit dans un
article dans IEEE Software [ You95 ], vous pouvez vous discipliner pour écrire
un logiciel suffisamment performant, suffisamment performant pour vos utilisateurs, pour l'avenir
mainteneurs, pour votre tranquillité d'esprit. Vous constaterez que vous êtes plus
productif et vos utilisateurs sont plus heureux. Et vous pourriez bien constater que votre
les programmes sont en fait meilleurs pour leur incubation plus courte.

Avant d'aller plus loin, nous devons nuancer ce que nous allons dire. Le
l'expression "assez bon" n'implique pas un code bâclé ou mal produit. Tous
les systèmes doivent répondre aux exigences de leurs utilisateurs pour réussir. Nous sommes
préconisant simplement que les utilisateurs aient la possibilité de participer à la
processus de décider quand ce que vous avez produit est assez bon.

Impliquez
Impliquez vos
vos utilisateurs
utilisateurs dans
dans le
le compromis
compromis

Normalement, vous écrivez des logiciels pour d'autres personnes. Souvent, vous vous souviendrez de
[2] Mais à quelle fréquence leur demandez-vous à quel point
obtenir des exigences de leur part.
veulent-ils que leur logiciel soit ? Parfois, il n'y aura pas de choix. Si vous êtes
travailler sur des stimulateurs cardiaques, la navette spatiale ou une bibliothèque de bas niveau qui sera
largement diffusées, les exigences seront plus strictes et votre
options plus limitées. Toutefois, si vous travaillez sur un tout nouveau produit,
vous aurez différentes contraintes. Les gens du marketing auront des promesses
à conserver, les éventuels utilisateurs finaux peuvent avoir fait des plans basés sur une livraison
calendrier, et votre entreprise aura certainement des contraintes de trésorerie. Il
ne serait pas professionnel d'ignorer les exigences de ces utilisateurs simplement pour ajouter
de nouvelles fonctionnalités au programme, ou pour peaufiner le code juste une fois de plus.
Nous ne prônons pas la panique : il est tout aussi peu professionnel de promettre
échelles de temps impossibles et de couper les coins d'ingénierie de base pour répondre à un
date limite.

[2] C'était censé être une blague !

La portée et la qualité du système que vous produisez doivent être spécifiées dans le cadre
des exigences de ce système.

Astuce
Astuce 77

Faire de la qualité une question d'exigences

Souvent, vous serez dans des situations où des compromis sont impliqués. Étonnamment,
de nombreux utilisateurs préfèrent aujourd'hui utiliser un logiciel avec quelques aspérités plutôt que
attendre un an pour la version multimédia. De nombreux départements informatiques avec des
les budgets seraient d'accord. Aujourd'hui, un bon logiciel est souvent préférable au parfait
logiciel demain. Si vous donnez à vos utilisateurs quelque chose avec quoi jouer tôt,
leurs commentaires vous conduiront souvent à une meilleure solution éventuelle (voir Tracer
balles).

Savoir
Savoir quand
quand s'arrêter
s'arrêter

À certains égards, la programmation est comme la peinture. Vous commencez avec une toile vierge
et certaines matières premières de base. Vous utilisez une combinaison de science, d'art et
artisanat pour déterminer quoi en faire. Vous dessinez une forme générale,
peignez l'environnement sous-jacent, puis remplissez les détails. Vous constamment
prenez du recul avec un œil critique pour voir ce que vous avez fait. De temps en temps
vous jetez une toile et recommencez.

Mais les artistes vous diront que tout le travail acharné est ruiné si vous ne savez pas
quand s'arrêter. Si vous ajoutez couche après couche, détail sur détail, la peinture
se perd dans la peinture.

Ne gâchez pas un programme parfaitement bon en l'embellissant à outrance et


sur-raffinement. Passez à autre chose et laissez votre code se tenir à part entière pour un
alors que. Ce n'est peut-être pas parfait. Ne vous inquiétez pas : cela ne pourrait jamais être parfait. (Dans
Chapitre 6, nous discuterons des philosophies pour développer du code dans un format imparfait
monde.)

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Balles traçantes
• • La fosse aux exigences
• • Des équipes pragmatiques
• • De grandes attentes

Défis
Défis

• • Regardez les fabricants d'outils logiciels et d'exploitation


systèmes que vous utilisez. Pouvez-vous trouver des preuves que ces
les entreprises sont à l'aise avec les logiciels d'expédition dont elles savent qu'elles ne le sont pas
parfait? En tant qu'utilisateur, préférez-vous (1) attendre qu'ils obtiennent tous les
bugs out, (2) avoir un logiciel complexe et accepter certains bugs, ou (3) opter
pour un logiciel plus simple avec moins de défauts ?
• • Tenez compte de l'effet de la modularisation sur la livraison des logiciels.
Cela prendra-t-il plus ou moins de temps pour obtenir un bloc de logiciel monolithique
la qualité requise par rapport à un système conçu en modules ?
Pouvez-vous trouver des exemples commerciaux ?

Votre
Votre portefeuille
portefeuille de
de connaissances
connaissances

Un investissement dans la connaissance récompense toujours le meilleur intérêt.

Benjamin
Benjamin Franklin
Franklin

Ah, ce bon vieux Ben Franklin, jamais à court d'idées pour une homélie lapidaire. Pourquoi, si nous
pourrait juste se coucher tôt et se lever tôt, nous serions super
programmeurs, n'est-ce pas ? Les lève-tôt pourraient attraper le ver, mais qu'est-ce que
arrive au ver précoce?

Dans ce cas, cependant, Ben a vraiment mis le doigt sur la tête. Vos connaissances
et l'expérience sont vos principaux atouts professionnels.

Malheureusement, ce sont des actifs qui[3] Votre à


arrivent connaissance
expiration. devient hors de
date à mesure que de nouvelles techniques, langages et environnements sont développés.
L'évolution des forces du marché peut rendre votre expérience obsolète ou non pertinente.
Compte tenu de la vitesse à laquelle les années Web passent, cela peut arriver assez rapidement.

[3] Un actif qui expire est quelque chose dont la valeur diminue avec le temps. Les exemples incluent un entrepôt plein de bananes et un

billet pour un match de balle.


À mesure que la valeur de vos connaissances diminue, votre valeur pour votre
entreprise ou client. Nous voulons éviter que cela ne se produise.

Votre
Votre portefeuille
portefeuille de
de connaissances
connaissances

Nous aimons penser à tous les faits que les programmeurs connaissent sur l'informatique, les
domaines d'application dans lesquels ils travaillent, et toute leur expérience en tant que leur
Portefeuilles de connaissances. La gestion d'un portefeuille de connaissances ressemble beaucoup à
gérer un portefeuille financier :

1. 1. Les investisseurs sérieux investissent régulièrement, par habitude.


2. 2. La diversification est la clé du succès à long terme.
3. 3. Les investisseurs avisés équilibrent leurs portefeuilles entre des
et des investissements à haut risque et à haut rendement.
4. 4. Les investisseurs essaient d'acheter bas et de vendre haut pour un rendement maximum.
5. 5. Les portefeuilles doivent être revus et rééquilibrés périodiquement.

Pour réussir dans votre carrière, vous devez gérer votre portefeuille de connaissances
en utilisant ces mêmes lignes directrices.

Construire
Construire votre
votre portefeuille
portefeuille

• • Investissez régulièrement. Tout comme dans l'investissement financier, vous devez


investissez régulièrement dans votre portefeuille de connaissances. Même si ce n'est qu'un petit
montant, l'habitude elle-même est aussi importante que les sommes. Quelques échantillons
les objectifs sont énumérés dans la section suivante.
• • Diversifier. Plus vous connaissez de choses différentes, plus
précieux tu es. Comme référence, vous devez connaître les tenants et les aboutissants de
la technologie particulière avec laquelle vous travaillez actuellement. Mais ne le faites pas
arrêtez là. Le visage de l'informatique change rapidement - une technologie en vogue
aujourd'hui pourrait bien être presque inutile (ou du moins pas demandé)

demain. Plus vous êtes à l'aise avec les technologies, plus


mieux vous serez en mesure de vous adapter au changement.
• • Gérer le risque. La technologie existe sur un spectre allant des risques,
des normes potentiellement très rémunératrices à des normes à faible risque et peu rémunératrices. Ce n'est pas un
bonne idée d'investir tout votre argent dans des actions à haut risque qui pourraient
s'effondrer soudainement, ni investir tout cela de manière conservatrice et
rater d'éventuelles opportunités. Ne mettez pas tous vos oeufs techniques
dans un seul panier.
• • Achetez bas, vendez haut. Apprendre une technologie émergente avant elle
devient populaire peut être aussi difficile que de trouver une action sous-évaluée,
mais le gain peut être tout aussi gratifiant. Apprendre Java la première fois
est sorti était peut-être risqué, mais cela a porté ses fruits pour le
adopteurs précoces qui sont maintenant au sommet de ce domaine.
• • Réviser et rééquilibrer. C'est une industrie très dynamique. Ce
la technologie chaude que vous avez commencé à étudier le mois dernier pourrait être de la pierre
froid maintenant. Peut-être avez-vous besoin de rafraîchir cette base de données
technologie que vous n'avez pas utilisée depuis longtemps. Ou peut-être pourriez-vous être
mieux placé pour cette nouvelle offre d'emploi si vous avez essayé cet autre
langue….

De toutes ces consignes, la plus importante est la plus simple à suivre :

Astuce
Astuce 88

Investissez régulièrement dans votre portefeuille de connaissances

Buts
Buts

Maintenant que vous avez quelques directives sur quoi et quand ajouter à votre
portefeuille de connaissances, quelle est la meilleure façon d'acquérir des connaissances intellectuelles
capital avec lequel financer votre portefeuille? Voici quelques suggestions.

• • Apprenez au moins une nouvelle langue chaque année. Différent


les langues résolvent les mêmes problèmes de différentes manières. Par l'apprentissage
plusieurs approches différentes, vous pouvez aider à élargir votre réflexion
et éviter de rester coincé dans une ornière. De plus, l'apprentissage de nombreux
langues est beaucoup plus facile maintenant, grâce à la richesse des
logiciel sur Internet (voir page 267).
• • Lire un livre technique chaque trimestre. Les librairies regorgent de
livres techniques sur des sujets intéressants liés à votre projet en cours.
Une fois que vous avez pris l'habitude, lisez un livre par mois. Après avoir maîtrisé

les technologies que vous utilisez actuellement, diversifiez-vous et étudiez-en quelques-unes


qui n'ont rien à voir avec votre projet.
• • Lisez aussi des livres non techniques. Il est important de se rappeler
que les ordinateurs sont utilisés par des gens—des gens dont vous avez besoin
essayant de satisfaire. N'oubliez pas le côté humain de l'équation.
• • Prendre des cours. Cherchez des cours intéressants dans votre local
collège communautaire ou universitaire, ou peut-être à la prochaine foire commerciale
qui vient en ville.
• • Participer à des groupes d'utilisateurs locaux. Ne vous contentez pas d'aller écouter, mais
participer activement. L'isolement peut être mortel pour votre carrière ; découvrir
sur quoi les gens travaillent en dehors de votre entreprise.
• • Expérimentez avec différents environnements. Si vous avez travaillé
uniquement sous Windows, jouez avec Unix à la maison (le Linux disponible gratuitement
est parfait pour cela). Si vous n'avez utilisé que des makefiles et un éditeur, essayez un
IDE, et vice versa.
• • Rester au courant. Abonnez-vous à des magazines spécialisés et à d'autres revues
(voir page 262 pour les recommandations). Choisissez-en qui couvrent
technologie différente de celle de votre projet actuel.
• • Soyez câblé. Vous voulez connaître les tenants et les aboutissants d'une nouvelle langue ou
autre technologie ? Les groupes de discussion sont un excellent moyen de savoir ce que
expériences que d'autres personnes ont avec lui, le jargon particulier
ils utilisent, et ainsi de suite. Naviguez sur le Web pour trouver des journaux, des sites commerciaux et
toute autre source d'information que vous pouvez trouver.

Il est important de continuer à investir. Une fois que vous vous sentez à l'aise avec certains
nouvelle langue ou un peu de technologie, passez à autre chose. Apprenez-en un autre.

Peu importe que vous utilisiez ou non l'une de ces technologies sur un
projet, ou même si vous les mettez sur votre CV. Le processus de
l'apprentissage élargira votre réflexion, vous ouvrira à de nouvelles possibilités et
de nouvelles façons de faire. La pollinisation croisée des idées est importante; Essayez de
appliquer les leçons que vous avez apprises à votre projet actuel. Même si votre
projet n'utilise pas cette technologie, vous pouvez peut-être emprunter quelques idées. Obtenir
familiarisé avec l'orientation objet, par exemple, et vous écrirez du C ordinaire
programmes différemment.

Opportunités
Opportunités d'apprentissage
d'apprentissage

Donc vous lisez avec voracité, vous êtes au courant de toutes les dernières nouveautés
développements dans votre domaine (ce qui n'est pas facile à faire), et quelqu'un vous demande
une question. Vous n'avez pas la moindre idée de la réponse, et librement
admettre autant.
Ne laissez pas cela s'arrêter là. Prenez-le comme un défi personnel pour trouver la réponse.
Demandez à un gourou. (Si vous n'avez pas de gourou dans votre bureau, vous devriez pouvoir
trouver un sur Internet : voir l'encadré sur la page ci-contre.) Rechercher sur le Web.
Aller à la bibliothèque.
[4]

[4] En cette ère du Web, beaucoup de gens semblent avoir oublié les véritables bibliothèques en direct remplies de matériel de recherche et

personnel.

Si vous ne pouvez pas trouver la réponse vous-même, découvrez qui peut. Ne le laissez pas reposer.
Parler à d'autres personnes vous aidera à construire votre réseau personnel, et vous pourriez
surprenez-vous en trouvant des solutions à d'autres problèmes sans rapport avec
le chemin. Et cet ancien portefeuille ne cesse de grossir….

Toutes ces lectures et recherches prennent du temps, et le temps est déjà compté
fournir. Vous devez donc planifier à l'avance. Ayez toujours quelque chose à lire dans un
sinon moment mort. Le temps passé à attendre les médecins et les dentistes peut être
une excellente occasion de rattraper votre retard de lecture, mais assurez-vous d'apporter votre
votre propre magazine avec vous, ou vous pourriez vous retrouver à feuilleter un
article écorné de 1973 sur la Papouasie-Nouvelle-Guinée.

Esprit
Esprit critique
critique

Le dernier point important est de penser de manière critique à ce que vous lisez et entendez.
Vous devez vous assurer que les connaissances de votre portfolio sont exactes et
non influencé par le battage publicitaire des fournisseurs ou des médias. Méfiez-vous des fanatiques qui insistent
que leur dogme fournit la seule réponse - cela peut être ou non
applicable à vous et à votre projet.

Ne sous-estimez jamais le pouvoir du mercantilisme. Juste parce qu'un Web


le moteur de recherche répertorie un résultat en premier ne signifie pas qu'il s'agit de la meilleure correspondance ; le
fournisseur de contenu peut payer pour obtenir la meilleure facturation. Juste parce qu'une librairie
mettre un livre en évidence ne signifie pas que c'est un bon livre, ou même qu'il est populaire ;
ils ont peut-être été payés pour le placer là.

Astuce
Astuce 99

Analysez de manière critique ce que vous lisez et entendez

Malheureusement, il n'y a plus que très peu de réponses simples. Mais avec votre
vaste portefeuille, et en appliquant une analyse critique à la

Soins et culture des gourous

Avec l'adoption mondiale d'Internet, les gourous sont soudainement aussi


fermer comme votre touche Entrée. Alors, comment trouvez-vous un, et comment obtenez-vous
un pour parler avec vous?

Nous constatons qu'il existe des astuces simples.

• • Sachez exactement ce que vous voulez demander et soyez aussi précis que possible.
Tu peux être.
• • Formez votre question avec soin et politesse. Se souvenir
que vous demandez une faveur ; ne semble pas exiger un
répondre.
• • Une fois que vous avez formulé votre question, arrêtez-vous et regardez à nouveau
pour la réponse. Choisissez des mots-clés et recherchez sur le Web.
Recherchez les FAQ appropriées (listes des questions fréquemment posées
questions avec réponses).
• • Décidez si vous voulez demander publiquement ou en privé. Usenet
les news-groups sont de merveilleux lieux de rencontre pour les experts
sur n'importe quel sujet, mais certaines personnes se méfient de ces groupes
caractère public. Alternativement, vous pouvez toujours envoyer votre
gourou directement. Dans tous les cas, utilisez une ligne d'objet significative.
("Besoin d'aide!!! " ne suffit pas.)
• • Asseyez-vous et soyez patient. Les gens sont occupés, et cela peut prendre
jours pour obtenir une réponse précise.

Enfin, n'oubliez pas de remercier tous ceux qui vous répondront. Et si


vous voyez des gens poser des questions auxquelles vous pouvez répondre, jouer votre rôle et
participer.

torrent de publications techniques que vous lirez, vous pourrez comprendre les
réponses complexes.

Défis
Défis

• • Commencez à apprendre une nouvelle langue cette semaine. Toujours programmé


en C++ ? Essayez Smalltalk [ URL 13 ] ou Squeak [ URL 14 ]. Faire du Java ?
Essayez Eiffel [ URL 10 ] ou TOM [ URL 15 ]. Voir page 267 pour les sources de
d'autres compilateurs et environnements gratuits.
• • Commencez à lire un nouveau livre (mais finissez d'abord celui-ci') Si vous êtes
faire une implémentation et un codage très détaillés, lire un livre sur
conception et architecture. Si vous faites de la conception de haut niveau, lisez un
livre sur les techniques de codage.

• • Sortez et parlez de technologie avec des personnes qui ne sont pas impliquées dans
votre projet actuel, ou qui ne travaillent pas pour la même entreprise.
Réseautez dans la cafétéria de votre entreprise, ou cherchez peut-être des collègues
passionnés lors d'une réunion d'un groupe d'utilisateurs locaux.

Communiquer!
Communiquer!

Je crois qu'il vaut mieux être regardé que d'être négligé.

Mae
Mae West,
West, Belle
Belle des
des années
années 90,
90, 1934
1934

Peut-être pourrions-nous tirer une leçon de Mme West. Ce n'est pas seulement ce que vous avez,
mais aussi comment vous l'emballez. Avoir les meilleures idées, le meilleur code ou le
la plupart des pensées pragmatiques sont finalement stériles à moins que vous ne puissiez communiquer
avec d'autres personnes. Une bonne idée est orpheline sans efficacité
communication.

En tant que développeurs, nous devons communiquer à plusieurs niveaux. Nous passons des heures à
réunions, écouter et parler. Nous travaillons avec les utilisateurs finaux, en essayant de
comprendre leurs besoins. Nous écrivons du code, qui communique nos intentions
à une machine et documente notre réflexion pour les générations futures de
développeurs. Nous rédigeons des propositions et des mémos demandant et justifiant
ressources, en signalant notre situation et en suggérant de nouvelles approches. Et nous
travailler au quotidien au sein de nos équipes pour défendre nos idées, modifier l'existant
pratiques et en suggérer de nouvelles. Une grande partie de notre journée se passe
communiquer, nous devons donc bien le faire.

Nous avons dressé une liste d'idées que nous trouvons utiles.

Sachez
Sachez ce
ce que
que vous
vous voulez
voulez dire
dire

Probablement la partie la plus difficile des styles de communication plus formels


utilisé dans les affaires consiste à déterminer exactement ce que vous voulez dire. Fiction
les écrivains tracent leurs livres en détail avant de commencer, mais les gens qui écrivent
les documents techniques se contentent souvent de s'asseoir devant un clavier, entrez "1.
Introduction", et commencez à taper tout ce qui leur passe par la tête.

Planifiez ce que vous voulez dire. Rédigez un plan. Ensuite, demandez-vous : "Est-ce que cela
comprendre ce que j'essaie de dire ?" Affinez-le jusqu'à ce que ce soit le cas.
Cette approche ne s'applique pas seulement à la rédaction de documents. Quand tu es
face à une réunion importante ou à un appel téléphonique avec un gros client, notez
notez les idées que vous souhaitez communiquer et planifiez quelques stratégies
pour les faire passer.

Connaissez
Connaissez votre
votre public
public

Vous ne communiquez que si vous transmettez des informations. Pour ce faire, vous
devez comprendre les besoins, les intérêts et les capacités de votre public.
Nous nous sommes tous assis dans des réunions où un geek du développement aveugle les yeux de
le vice-président du marketing avec un long monologue sur les mérites de
une technologie arcanique. Ce n'est pas communiquer : c'est juste parler, et c'est
ennuyeux. [5]

[5] Le mot ennuyer vient du vieux français enui, qui signifie aussi « ennuyer ».

Formez une image mentale forte de votre auditoire. La sagesse acrostiche, montrée
dans la figure 1.1 à la page suivante, peut aider.

Illustration
Illustration 1.1.
1.1. L'acrostiche
L'acrostiche de
de la
la sagesse
sagesse -- comprendre
comprendre un
un public
public

Supposons que vous souhaitiez suggérer un système Web pour permettre à vos utilisateurs finaux de
soumettre des rapports de bogues. Vous pouvez présenter ce système de différentes manières,
en fonction de votre public. Les utilisateurs finaux apprécieront de pouvoir
soumettre des rapports de bogues 24 heures sur 24 sans attendre au téléphone. Ton
le service marketing pourra utiliser ce fait pour augmenter les ventes. Gestionnaires
du service support aura deux raisons d'être satisfait : moins de personnel
seront nécessaires et le signalement des problèmes sera automatisé. Enfin,
les développeurs peuvent profiter de l'expérience avec le client-serveur basé sur le Web
technologies et un nouveau moteur de base de données. En faisant le pitch approprié
à chaque groupe, vous les enthousiasmerez tous pour votre projet.

Choisissez
Choisissez votre
votre moment
moment

Il est 18 heures le vendredi après-midi, après une semaine où les auditeurs


ont été. Le plus jeune de votre patron est à l'hôpital, il pleut
à l'extérieur, et le retour à la maison est assuré d'être un cauchemar. Ce
n'est probablement pas le bon moment pour lui demander une mise à niveau de la mémoire de votre PC.

Pour comprendre ce que votre public a besoin d'entendre, vous devez


déterminer quelles sont leurs priorités. Attrapez un manager qui vient de recevoir un

du mal par son patron car du code source a été perdu, et vous aurez un
auditeur plus réceptif à vos idées sur les référentiels de code source. Faire
ce que vous dites est pertinent dans le temps, ainsi que dans le contenu. Parfois tout ça
prend la simple question « Est-ce le bon moment pour parler de… ? »

Choisissez
Choisissez un
un style
style
Ajustez le style de votre prestation en fonction de votre public. Certaines personnes veulent un
séance d'information formelle "juste les faits". D'autres aiment une conversation longue et variée avant
se mettre au travail. Lorsqu'il s'agit de documents écrits, certains aiment
reçoivent de gros rapports reliés, tandis que d'autres s'attendent à recevoir un simple mémo ou un e-mail. Si
dans le doute, demandez.

Rappelez-vous, cependant, que vous êtes la moitié de la transaction de communication. Si


quelqu'un dit qu'il a besoin d'un paragraphe décrivant quelque chose et vous ne pouvez pas
voir un moyen de le faire en moins de plusieurs pages, dites-le-leur. Se souvenir,
ce genre de rétroaction est aussi une forme de communication.

Faites
Faites en
en sorte
sorte que
que ça
ça ait
ait l'air
l'air bien
bien

Vos idées sont importantes. Ils méritent un beau véhicule pour véhiculer
à votre public.

Trop de développeurs (et leurs managers) se concentrent uniquement sur le contenu


lors de la production de documents écrits. Nous pensons que c'est une erreur. N'importe quel chef
vous dira que vous pouvez être esclave dans la cuisine pendant des heures pour ruiner votre
efforts avec une mauvaise présentation.

Il n'y a plus d'excuse aujourd'hui pour produire des documents imprimés de mauvaise qualité.
Les traitements de texte modernes (ainsi que les systèmes de mise en page tels que LaTeX et
troff) peut produire une sortie époustouflante. Vous devez apprendre quelques notions de base
commandes. Si votre traitement de texte prend en charge les feuilles de style, utilisez-les. (Ton
société a peut-être déjà défini des feuilles de style que vous pouvez utiliser.)
comment définir les en-têtes et pieds de page. Regardez les exemples de documents
inclus avec votre forfait pour avoir des idées sur le style et la mise en page. Vérifier la
l'orthographe, d'abord automatiquement puis à la main. Après poinçon, leur orthographe
manquez des steaks que le vérificateur peut nouer du ketch.

Impliquez
Impliquez votre
votre public
public

Nous constatons souvent que les documents que nous produisons finissent par être moins importants
que le processus que nous suivons pour les produire. Si possible, impliquez votre

lecteurs avec les premières ébauches de votre document. Obtenez leurs commentaires et choisissez
leur cerveau. Vous établirez une bonne relation de travail, et vous aurez probablement
produire un meilleur document dans le processus.

Soyez
Soyez un
un auditeur
auditeur

Il y a une technique que vous devez utiliser si vous voulez que les gens vous écoutent :
écoute-les. Même s'il s'agit d'une situation où vous avez toutes les informations,
même s'il s'agit d'une réunion formelle avec vous debout devant 20 costumes - si
vous ne les écoutez pas, ils ne vous écouteront pas.

Encouragez les gens à parler en posant des questions ou demandez-leur de résumer


ce que vous leur dites. Transformez la réunion en dialogue, et vous ferez votre
pointer plus efficacement. Qui sait, vous pourriez même apprendre quelque chose.

Revenez
Revenez aux
aux gens
gens

Si vous posez une question à quelqu'un, vous pensez qu'il est impoli s'il ne le fait pas
répondre. Mais à quelle fréquence échouez-vous à contacter les gens lorsqu'ils vous envoient
un e-mail ou un mémo demandant des informations ou demandant une action ? Dans
le rush de la vie quotidienne, c'est facile à oublier. Répondez toujours aux e-mails et
messages vocaux, même si la réponse est simplement "Je vous recontacterai plus tard".
Tenir les gens informés les rend beaucoup plus indulgents face aux
glisser, et leur faire sentir que vous ne les avez pas oubliés.

Astuce
Astuce 10
10
C'est à la fois ce que vous dites et la façon dont vous le dites

À moins que vous ne travailliez dans le vide, vous devez être capable de communiquer. Le
plus efficace que la communication, plus vous devenez influent.

Communication par courrier électronique

Tout ce que nous avons dit sur la communication par écrit s'applique
également au courrier électronique. Le courrier électronique a évolué au point où il
est le pilier des communications intra et interentreprises. Le courrier électronique est
utilisé pour discuter de contrats, pour régler des différends et comme preuve dans
rechercher. Mais pour une raison quelconque, les gens qui n'enverraient jamais un
un document papier minable est heureux de lancer un e-mail d'apparence désagréable

autour du monde.

Nos conseils par e-mail sont simples :

• • Relisez avant de cliquer sur .


• • Vérifier l'orthographe.
• • Gardez le format simple. Certaines personnes lisent leurs e-mails en utilisant
polices proportionnelles, de sorte que l'art ASCII vous représente laborieusement
créés leur apparaîtront comme des gratouilles de poule.
• • N'utilisez des e-mails au format RTF ou HTML que si vous savez
que tous vos destinataires puissent le lire. Le texte brut est universel.
• • Essayez de limiter au maximum les citations. Personne n'aime
recevoir leur propre e-mail de 100 lignes avec "J'accepte" suivi
sur.
• • Si vous citez l'e-mail d'autres personnes, assurez-vous de
attribuez-le et citez-le en ligne (plutôt que comme un
pièce jointe).
• • Ne flambez pas à moins que vous ne vouliez qu'il revienne et hante
toi plus tard.
• • Vérifiez votre liste de destinataires avant l'envoi. Une récente
Un article du Wall Street Journal décrit un employé qui a pris
à diffuser les critiques de son patron sur les départements
e-mail. sans se rendre compte que son patron était inclus dans le
liste de distribution.
• • Archivez et organisez vos e-mails, à la fois les éléments d'importation
vous recevez et le courrier que vous envoyez.

Comme l'ont découvert divers employés de Microsoft et de Netscape au cours de la


Enquête du ministère de la Justice de 1999, le courrier électronique est éternel. Essayez de
accordez la même attention et le même soin aux e-mails qu'à n'importe quel
note écrite ou rapport.

Résumé
Résumé

• • Sachez ce que vous voulez dire.


• • Connaissez votre auditoire.
• • Choisissez votre moment.
• • Choisissez un style.
• • Donnez une belle apparence.
• • Impliquez votre auditoire.
• • Soyez à l'écoute.
• • Revenez vers les gens.
Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Prototypes et Post-it
• • Des équipes pragmatiques

Défis
Défis

• • Il existe plusieurs bons livres qui contiennent des sections sur


communication au sein des équipes de développement [ Bro95 , McC95 , DL99 ].
Faites-vous un devoir d'essayer de lire les trois au cours des 18 prochains mois. Dans
De plus, le livre Dinosaur Brains [ Ber96 ] traite de l'émotionnel
bagages que nous apportons tous dans le milieu de travail.
• • La prochaine fois que vous devrez faire une présentation ou rédiger un mémo
préconisant une position, essayez de travailler à travers l'acrostiche de la sagesse
avant de commencer. Voyez si cela vous aide à comprendre comment positionner ce
vous dites. Le cas échéant, parlez ensuite à votre auditoire et voyez comment
exacte votre évaluation de leurs besoins était.

Chapitre 2. Une approche pragmatique

Certains trucs et astuces s'appliquent à tous les niveaux de logiciel


développement, des idées presque axiomatiques et des processus
pratiquement universelle. Cependant, ces approches sont rarement documentées comme
tel; vous les trouverez principalement écrits sous forme de phrases étranges dans les discussions
de conception, de gestion de projet ou de codage.

Dans ce chapitre, nous allons rassembler ces idées et ces processus. Les deux premiers
sections, Les maux de la duplication et de l'orthogonalité, sont étroitement liées.
Le premier vous avertit de ne pas dupliquer les connaissances dans vos systèmes,
la seconde de ne pas diviser une seule connaissance sur plusieurs systèmes
Composants.
À mesure quepertinentes.
applications le rythme du changement
Dans s'accélère,
Réversibilité, il devient
nous verrons de plustechniques
quelques en plus difficile
qui de garder notre
aider à isoler vos projets de leur environnement changeant.

Les deux sections suivantes sont également liées. Dans Tracer Bullets, on parle d'un
style de développement qui vous permet de rassembler les exigences, de tester les conceptions,
et implémenter le code en même temps. Si cela semble trop beau pour être vrai, c'est :
les développements des balles traçantes ne sont pas toujours applicables. Quand ils ne le sont pas,
Prototypes et Post-it vous montrent comment utiliser le prototypage pour tester
architectures, algorithmes, interfaces et idées.

Alors que l'informatique mûrit lentement, les concepteurs produisent de plus en plus
langues de niveau supérieur. Alors que le compilateur qui accepte "faire en sorte" n'a pas
encore été inventés, dans Domain Languages nous présentons quelques-uns plus modestes
suggestions que vous pouvez appliquer vous-même.

Enfin, nous travaillons tous dans un monde où le temps et les ressources sont limités. Tu peux
mieux survivre à ces deux pénuries (et garder vos patrons plus heureux) si vous
devenez bon pour déterminer combien de temps les choses prendront, ce que nous couvrons dans
Estimation.

En gardant ces principes fondamentaux à l'esprit lors du développement, vous


peut écrire du code meilleur, plus rapide et plus fort. Vous pouvez même le faire paraître
facile.

Les
Les maux
maux de
de la
la duplication
duplication

Donner à un ordinateur deux connaissances contradictoires était le capitaine


La méthode préférée de James T. Kirk pour désactiver un artificiel en maraude

intelligence. Malheureusement, le même principe peut être efficace pour amener


vers le bas de votre code.

En tant que programmeurs, nous collectons, organisons, maintenons et exploitons les connaissances.
Nous documentons le savoir dans un cahier des charges, nous le faisons vivre dans
code en cours d'exécution, et nous l'utilisons pour fournir les vérifications nécessaires pendant les tests.

Malheureusement, la connaissance n'est pas stable. Il change, souvent rapidement. Ton


la compréhension d'une exigence peut changer à la suite d'une rencontre avec le
client. Le gouvernement modifie un règlement et une logique commerciale s'impose
dépassé. Les tests peuvent montrer que l'algorithme choisi ne fonctionnera pas. Tout ça
l'instabilité signifie que nous passons une grande partie de notre temps en maintenance
mode, réorganisant et réexprimant les connaissances dans nos systèmes.

La plupart des gens supposent que la maintenance commence lorsqu'une application est
publié, cette maintenance consiste à corriger les bogues et à améliorer les fonctionnalités. Nous
pense que ces gens ont tort. Les programmeurs sont constamment en maintenance
mode. Notre compréhension change de jour en jour. De nouvelles exigences arrivent comme
nous concevons ou codons. Peut-être que l'environnement change. Quel que soit le
raison, la maintenance n'est pas une activité discrète, mais une partie courante de la
tout le processus de développement.

Lorsque nous effectuons une maintenance, nous devons trouver et changer le


représentations des choses - ces capsules de connaissances intégrées dans
application. Le problème est qu'il est facile de dupliquer les connaissances dans le
spécifications, processus et programmes que nous développons, et lorsque nous le faisons,
nous invitons un cauchemar de maintenance - un cauchemar qui commence bien avant le
navires d'application.

Nous estimons que la seule façon de développer des logiciels de manière fiable et de rendre notre
développements plus faciles à comprendre et à maintenir, est de suivre ce que nous appelons
le principe DRY :

Chaque élément de connaissance doit avoir un seul, sans ambiguïté, faisant autorité
représentation au sein d'un système.

Pourquoi l'appelle-t-on SEC ?


Astuce
Astuce 11
11

SEC — Ne vous répétez pas

L'alternative est d'avoir la même chose exprimée en deux endroits ou plus.


Si vous en changez un, vous devez vous rappeler de changer les autres, ou, comme le
ordinateurs extraterrestres, votre programme sera mis à genoux par un
contradiction. Il ne s'agit pas de savoir si vous vous souviendrez : c'est une question
du moment où vous oublierez.

Vous constaterez que le principe DRY apparaît à maintes reprises tout au long
ce livre, souvent dans des contextes qui n'ont rien à voir avec le codage. Nous ressentons
qu'il s'agit de l'un des outils les plus importants du programmeur pragmatique
boîte à outils.

Dans cette section, nous décrirons les problèmes de duplication et suggérerons des
stratégies pour y faire face.

Comment
Comment se
se produit
produit la
la duplication
duplication ??

La plupart des doublons que nous voyons appartiennent à l'une des catégories suivantes :

• • Duplication imposée. Les développeurs estiment qu'ils n'ont pas le choix—le


l'environnement semble nécessiter une duplication.
• • Duplication par inadvertance. Les développeurs ne réalisent pas qu'ils sont
doublons d'informations.
• • Duplication impatiente. Les développeurs deviennent paresseux et dupliquent
car cela semble plus facile.
• • Duplication inter-développeurs. Plusieurs personnes dans une équipe (ou sur
différentes équipes) dupliquent une information.

Examinons ces quatre i de la duplication plus en détail.

Duplication
Duplication imposée
imposée

Parfois, la duplication semble nous être imposée. Les normes du projet peuvent
exiger des documents qui contiennent des informations en double, ou des documents qui
informations en double dans le code. Plusieurs plates-formes cibles nécessitent chacune
leurs propres langages de programmation, bibliothèques et développement
environnements, ce qui nous oblige à dupliquer des définitions et des procédures partagées.
Les langages de programmation eux-mêmes nécessitent certaines structures qui
informations en double. Nous avons tous travaillé dans des situations où nous nous sentions
impuissant à éviter les doubles emplois. Et pourtant, il existe souvent des moyens de garder
chaque élément de connaissance en un seul endroit, en respectant le principe DRY, et
rendre nos vies plus faciles en même temps. Voici quelques techniques :

Représentations multiples de l'information. Au niveau du codage, nous avons souvent


besoin d'avoir les mêmes informations représentées sous différentes formes. Peut être
nous écrivons une application client-serveur, en utilisant différents langages sur le
client et serveur, et doivent représenter une structure partagée sur les deux.
Peut-être avons-nous besoin d'une classe dont les attributs reflètent le schéma d'une base de données
tableau. Peut-être que vous écrivez un livre et que vous souhaitez inclure des extraits de
programmes que vous allez également compiler et tester.

Avec un peu d'ingéniosité, vous pouvez normalement éliminer le besoin de duplication.


Souvent, la réponse consiste à écrire un simple filtre ou générateur de code. Ouvrages en
plusieurs langues peuvent être construites à partir d'une représentation commune des métadonnées
à l'aide d'un simple générateur de code à chaque construction du logiciel (exemple de
ceci est illustré à la figure 3.4
). Des définitions de classe peuvent être générées
automatiquement depuis le schéma de la base de données en ligne, ou depuis les métadonnées utilisées
pour construire le schéma en premier lieu. Les extraits de code de ce livre sont
inséré par un préprocesseur chaque fois que nous formatons le texte. L'astuce consiste à
rendre le processus actif : cela ne peut pas être une conversion unique, ou nous sommes de retour
dans une situation de duplication de données.

Documentation en code. Les programmeurs apprennent à commenter leur code :


bon code a beaucoup de commentaires. Malheureusement, on ne leur apprend jamais pourquoi
le code a besoin de commentaires : un mauvais code nécessite beaucoup de commentaires.

Le principe DRY nous dit de garder les connaissances de bas niveau dans le code,
où il appartient, et réserver les commentaires pour d'autres, de haut niveau
explications. Sinon, nous dupliquons les connaissances, et chaque changement
signifie changer à la fois le code et les commentaires. Les commentaires seront
deviennent inévitablement obsolètes et les commentaires peu fiables sont pires que
aucun commentaire du tout. (Voir Tout est, pour
écrit plus d'informations sur
commentaires.)

Documentation et code. Vous écrivez de la documentation, puis vous écrivez du code.


Quelque chose change, et vous modifiez la documentation et mettez à jour le
code. La documentation et le code contiennent tous deux des représentations du même
connaissance. Et nous savons tous que dans le feu de l'action, avec des délais
se profilent et des clients importants réclament, nous avons tendance à différer la mise à jour de
Documentation.

Dave a déjà travaillé sur un commutateur télex international. Tout à fait compréhensible,
le client exigeait une spécification de test exhaustive et exigeait que le
le logiciel passe tous les tests à chaque livraison. Pour s'assurer que les tests sont exacts
reflète la spécification, l'équipe les a générés par programmation
du document lui-même. Lorsque le client a modifié son cahier des charges, le
la suite de tests a changé automatiquement. Une fois que l'équipe a convaincu le client que

la procédure était solide, générer des tests d'acceptation ne prenait généralement qu'un
quelques secondes.

Problèmes de langue. De nombreuses langues imposent une duplication considérable dans le


source. Souvent, cela se produit lorsque la langue sépare les éléments d'un module
interface dès son implémentation. C et C++ ont des fichiers d'en-tête qui
dupliquer les noms et les informations de type des variables, fonctions,
et (pour C++) les classes. Object Pascal duplique même ces informations dans le
même dossier. Si vous utilisez des appels de procédure à distance ou CORBA ], [ URL 29
vous allez dupliquer les informations d'interface entre la spécification d'interface
et le code qui l'implémente.

Il n'y a pas de technique facile pour surmonter les exigences d'une langue.
Alors que certains environnements de développement cachent le besoin de fichiers d'en-tête en
en les générant automatiquement, et Object Pascal vous permet d'abréger
déclarations de fonction répétées, vous êtes généralement coincé avec ce que vous êtes
donné. Au moins avec la plupart des problèmes linguistiques, un fichier d'en-tête qui
n'est pas d'accord avec la mise en œuvre générera une certaine forme de compilation
ou erreur de liaison. Vous pouvez toujours vous tromper, mais au moins on vous dira
à ce sujet assez tôt.

Pensez également aux commentaires dans les fichiers d'en-tête et d'implémentation. Il y a


absolument aucun intérêt à dupliquer un commentaire d'en-tête de fonction ou de classe
entre les deux fichiers. Utilisez les fichiers d'en-tête pour documenter les problèmes d'interface,
et les fichiers de mise en œuvre pour documenter les détails de fond que les utilisateurs
de votre code n'ont pas besoin de savoir.

Duplication
Duplication par
par inadvertance
inadvertance

Parfois, la duplication survient à la suite d'erreurs dans la conception.

Prenons un exemple tiré de l'industrie de la distribution. Dire notre analyse


révèle que, parmi d'autres attributs, un camion a un type, un numéro d'immatriculation,
et un chauffeur. De même, un itinéraire de livraison est une combinaison d'un itinéraire, d'un camion,
et un chauffeur. Nous codons certaines classes sur la base de cette compréhension.

Mais que se passe-t-il quand Sally est malade et qu'on doit changer de chauffeur ?
Truck et DeliveryRoute contiennent tous deux un chauffeur. Lequel change-t-on ?
Il est clair que cette duplication est mauvaise. Normalisez-le en fonction du sous-jacent
modèle d'entreprise - un camion a-t-il vraiment un chauffeur dans le cadre de son activité sous-jacente?
ensemble d'attributs ? Est-ce qu'un itinéraire? Ou peut-être qu'il doit y avoir un troisième objet qui
relie un conducteur, un camion et un itinéraire. Quelle que soit l'éventuelle
solution, évitez ce type de données non normalisées.

Il existe un type légèrement moins évident de données non normalisées qui se produit lorsque
nous avons plusieurs éléments de données qui sont mutuellement dépendants. Regardons
u en

A première vue, cette classe peut sembler raisonnable. Une ligne a clairement un début
et end, et aura toujours une longueur (même si elle est nulle). Mais nous avons
reproduction. La longueur est définie par les points de début et de fin : modifiez l'un des
les points et la longueur changent. Il est préférable de faire la longueur d'un
c ah

Plus tard dans le processus de développement, vous pouvez choisir de violer le DRY
principe pour des raisons de performance. Cela se produit fréquemment lorsque vous devez
cachez les données pour éviter de répéter des opérations coûteuses. L'astuce consiste à localiser
l'impact. La violation n'est pas exposée au monde extérieur : seule la
el s
oP tin

Cet exemple illustre également un problème important pour les objets orientés
langages tels que Java et C++. Dans la mesure du possible, utilisez toujours accessor
fonctions pour lire et écrire les attributs des objets. [1] Cela facilitera les choses
pour ajouter des fonctionnalités, telles que la mise en cache, à l'avenir.

[1] L'utilisation des fonctions d'accès est liée au principe d'accès uniforme de Meyer |Mey97b], qui stipule que "Tous les services

offerts par un module doivent être disponibles à travers une notation uniforme, qui ne trahisse pas s'ils sont

Implémenté par le stockage ou par le calcul."

Duplication
Duplication impatiente
impatiente

Chaque projet est soumis à des contraintes de temps, des forces qui peuvent pousser les meilleurs d'entre nous à
prendre des raccourcis. Besoin d'une routine similaire à celle que vous avez écrite ? Vous serez
tenté de copier l'original et d'apporter quelques modifications. Besoin d'une valeur pour
représentent le nombre maximum de points ? Si je change le fichier d'en-tête, le
tout le projet sera reconstruit. Peut-être que je devrais juste utiliser un nombre littéral ici;
et ici; et ici. Besoin d'une classe comme celle du runtime Java ? La provenance est
disponible, alors pourquoi ne pas simplement le copier et apporter les modifications dont vous avez besoin (licence
nonobstant les dispositions) ?

Si vous ressentez cette tentation, souvenez-vous de l'aphorisme rebattu "raccourcis


faire de longs retards." Vous pouvez bien gagner quelques secondes maintenant, mais à la
perte potentielle d'heures plus tard. Réfléchir aux enjeux entourant l'an 2000
fiasco. Beaucoup ont été causés par la paresse des développeurs qui ne paramétraient pas
la taille des champs de date ou la mise en œuvre de bibliothèques centralisées de services de date.

La duplication impatiente est une forme facile à détecter et à gérer, mais il faut
discipline et une volonté de passer du temps à l'avance pour éviter la douleur plus tard.

Duplication
Duplication inter-développeurs
inter-développeurs

D'autre part, peut-être le type de duplication le plus difficile à détecter et


handle se produit entre différents développeurs sur un projet. Des ensembles entiers de
fonctionnalité peut être dupliquée par inadvertance, et cette duplication pourrait
passer inaperçu pendant des années, entraînant des problèmes de maintenance. Nous avons entendu
de première main d'un État américain dont les systèmes informatiques gouvernementaux étaient
interrogés pour la conformité Y2K. L'audit a révélé plus de 10 000
programmes, chacun contenant sa propre version du numéro de sécurité sociale
validation.
À un niveau élevé, traitez le problème en ayant une conception claire, une solide
chef de projet technique (voir Equipes pragmatiques
), et un bien compris
répartition des responsabilités au sein de la conception. Cependant, au niveau du module,
le problème est plus insidieux. Fonctionnalité ou données couramment nécessaires qui
ne relève pas d'un domaine de responsabilité évident peut être mis en œuvre
plusieurs fois.

Nous estimons que la meilleure façon d'y faire face est d'encourager les activités actives et
communication fréquente entre les développeurs. Mettre en place des forums pour discuter
problèmes communs. (Sur des projets passés, nous avons mis en place un Usenet privé
groupes de discussion pour permettre aux développeurs d'échanger des idées et de poser des questions. Ce
fournit un moyen de communication non intrusif, même à travers plusieurs
sites – tout en conservant un historique permanent de tout ce qui a été dit.) Nommer un
membre de l'équipe en tant que bibliothécaire du projet, dont le travail consiste à faciliter la
échange de connaissances. Avoir une place centrale dans l'arborescence des sources où
des routines utilitaires et des scripts peuvent être déposés. Et mettez un point d'honneur à lire
le code source et la documentation d'autres personnes, de manière informelle ou pendant
revues de code. Vous n'êtes pas en train d'espionner, vous apprenez d'eux. Et
rappelez-vous que l'accès est réciproque - ne vous méprenez pas sur les autres
fouiller (piaffe ?) dans votre code non plus.

Astuce
Astuce 12
12

Rendez-le facile à réutiliser

Ce que vous essayez de faire, c'est de favoriser un environnement où il est plus facile de trouver
et réutiliser des trucs existants plutôt que de les écrire soi-même. Si ce n'est pas facile, les gens
ne le fera pas. Et si vous ne parvenez pas à réutiliser, vous risquez de dupliquer les connaissances.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Orthogonalité
• • Manipulation de texte
• • Générateurs de codes
• • Refactorisation
• • Des équipes pragmatiques
• • Automatisation omniprésente
• • Tout est écrit

Orthogonalité
Orthogonalité

L'orthogonalité est un concept critique si vous voulez produire des systèmes qui sont
facile à concevoir, construire, tester et étendre. Cependant, la notion de
l'orthogonalité est rarement enseignée directement. Il s'agit souvent d'une caractéristique implicite de
diverses autres méthodes et techniques que vous apprenez. C'est une erreur. Une fois
vous apprenez à appliquer directement le principe d'orthogonalité, vous remarquerez une
amélioration immédiate de la qualité des systèmes que vous produisez.

Qu'est-ce
Qu'est-ce que
que l'orthogonalité
l'orthogonalité ??

"Orthogonalité" est un terme emprunté à la géométrie. Deux lignes sont


orthogonaux s'ils se rencontrent à angle droit, comme les axes d'un graphique. Dans
termes vectoriels, les deux droites sont indépendantes. Déplacez-vous le long d'une des lignes,
et votre position projetée sur l'autre ne change pas.
En informatique, le terme en est venu à signifier une sorte d'indépendance ou
découplage. Deux choses ou plus sont orthogonales si les changements dans l'une ne le sont pas
affecter aucun des autres. Dans un système bien conçu, le code de la base de données
être orthogonal à l'interface utilisateur : vous pouvez modifier l'interface sans
affecter la base de données et permuter les bases de données sans modifier l'interface.

Avant d'examiner les avantages des systèmes orthogonaux, examinons d'abord un


système qui n'est pas orthogonal.

Un
Un système
système non
non orthogonal
orthogonal

Vous faites un tour en hélicoptère du Grand Canyon lorsque le pilote, qui a fait
l'erreur évidente de manger du poisson pour le déjeuner, gémit et s'évanouit soudainement.
Heureusement, il vous a laissé planer à 100 pieds au-dessus du sol. vous rationalisez
que le levier de pas collectif [2] contrôle la portance globale, donc en l'abaissant légèrement
commencera une descente douce vers le sol. Cependant, lorsque vous l'essayez, vous
découvrir que la vie n'est pas si simple. Le nez de l'hélicoptère tombe et vous
commencer à descendre en spirale vers la gauche. Soudain, vous découvrez que vous pilotez un
système où chaque entrée de commande a des effets secondaires. Abaissez le
levier gauche et vous devez ajouter un mouvement vers l'arrière compensateur pour
le manche droit et appuyez sur la pédale droite. Mais alors chacun de ces
les modifications affectent à nouveau tous les autres contrôles. Soudain, vous jonglez avec un
système incroyablement complexe, où chaque changement a un impact sur tous les autres
contributions. Votre charge de travail est phénoménale : vos mains et vos pieds sont constamment
se déplaçant, essayant d'équilibrer toutes les forces en interaction.

[2] Les hélicoptères ont quatre commandes de base. Le cyclique est le bâton que vous tenez dans votre main droite. Déplacez-le, et l'hélicoptère

se déplace dans la direction correspondante. Votre main gauche tient le levier de pas collectif. Tirez dessus et vous augmentez le

pas sur toutes les pales, générant de la portance. Au bout du levier de pas se trouve la manette des gaz. Enfin, vous avez deux pédales, qui

varier la quantité de poussée du rotor de queue et ainsi aider à faire tourner l'hélicoptère.

Les commandes de l'hélicoptère ne sont décidément pas orthogonales.

Avantages
Avantages de
de l'orthogonalité
l'orthogonalité

Comme l'illustre l'exemple de l'hélicoptère, les systèmes non orthogonaux sont


intrinsèquement plus complexe à modifier et à contrôler. Lorsque des composants de n'importe quel
système sont hautement interdépendants, il n'existe pas de solution locale.

Astuce
Astuce 13
13

Éliminer les effets entre des choses non liées

Nous voulons concevoir des composants autonomes : indépendants et


avec un but unique et bien défini (ce que Yourdon et Constantine appellent
cohésion [ YC86 ]). Lorsque les composants sont isolés les uns des autres, vous
sachez que vous pouvez en changer un sans avoir à vous soucier du reste. Comme
tant que vous ne modifiez pas les interfaces externes de ce composant, vous pouvez être
confortable que vous ne causerez pas de problèmes qui se répercutent sur l'ensemble
système.
Vous obtenez deux avantages majeurs si vous écrivez des systèmes orthogonaux :
productivité et réduction des risques.

Gagnez
Gagnez en
en productivité
productivité

• • Les modifications sont localisées, de sorte que le temps de développement et le temps de test sont
réduit. Il est plus facile d'écrire relativement petit, autonome
composants qu'un seul gros bloc de code. Des composants simples peuvent
être conçu, codé, testé à l'unité, puis oublié - il n'est pas nécessaire
pour continuer à modifier le code existant lorsque vous ajoutez un nouveau code.
• • Une approche orthogonale favorise également la réutilisation. Si les composants
ont des responsabilités précises et bien définies, elles peuvent être combinées
avec de nouveaux composants d'une manière qui n'était pas envisagée par leur
exécutants originaux. Plus vos systèmes sont faiblement couplés, plus
ils sont plus faciles à reconfigurer et à réorganiser.
• • Il y a un gain de productivité assez subtil quand on combine
composantes orthogonales. Supposons qu'un composant fait M distinct
choses et un autre fait N choses. S'ils sont orthogonaux et que vous
les combiner, le résultat fait M × N choses. Cependant, si les deux
les composants ne sont pas orthogonaux, il y aura un chevauchement et le résultat
fera moins. Vous obtenez plus de fonctionnalités par unité d'effort en combinant
composantes orthogonales.

Réduire
Réduire les
les risques
risques

Une approche orthogonale réduit les risques inhérents à tout développement.

• • Les sections de code malades sont isolées. Si un module est malade, il est
moins susceptibles de propager les symptômes dans le reste du système. C'est
aussi plus facile de le découper et de le transplanter dans quelque chose de nouveau et
en bonne santé.
• • Le système résultant est moins fragile. Faites de petits changements et
correctifs à un domaine particulier, et tous les problèmes que vous générez seront
limité à cette zone.
• • Un système orthogonal sera probablement mieux testé, car il
sera plus facile à concevoir et à exécuter des tests sur ses composants.
• • Vous ne serez pas aussi étroitement lié à un fournisseur, un produit ou un
plate-forme, car les interfaces avec ces composants tiers seront
être isolé à de plus petites parties du développement global.

Regardons quelques-unes des façons dont vous pouvez appliquer le principe d'orthogonalité
à votre travail.

Équipes
Équipes de
de projet
projet

Avez-vous remarqué à quel point certaines équipes de projet sont efficaces, avec tout le monde
savoir quoi faire et y contribuer pleinement, tandis que les membres des autres
les équipes se chamaillent constamment et ne semblent pas pouvoir sortir de chacune
le chemin de l'autre ?

Il s'agit souvent d'un problème d'orthogonalité. Lorsque les équipes sont organisées avec beaucoup de
se chevauchent, les membres sont confus quant aux responsabilités. Chaque changement nécessite
une réunion de toute l'équipe, car n'importe lequel d'entre eux pourrait être concerné.

Comment organisez-vous les équipes en groupes avec des responsabilités bien définies
et chevauchement minimal ? Il n'y a pas de réponse simple. Cela dépend en partie de la
projet et votre analyse des domaines de changement potentiel. Cela dépend aussi
sur les personnes dont vous disposez. Notre préférence est de commencer par séparer
infrastructure à partir de l'application. Chaque composante majeure de l'infrastructure
(base de données, interface de communication, couche middleware, etc.)
propre sous-équipe. Chaque division évidente de la fonctionnalité de l'application est similaire
divisé. Ensuite, nous examinons les personnes que nous avons (ou prévoyons d'avoir) et ajustons le
groupements en conséquence.
Vous pouvez obtenir une mesure informelle de l'orthogonalité d'une équipe de projet
structure. Voyez simplement combien de personnes doivent participer à la discussion
chaque modification demandée. Plus le nombre est grand, moins il est orthogonal
le groupe. De toute évidence, une équipe orthogonale est plus efficace. (Cela dit,
nous encourageons également les sous-équipes à communiquer constamment entre elles.)

Conception
Conception

La plupart des développeurs sont familiers avec la nécessité de concevoir des systèmes orthogonaux,
bien qu'ils puissent utiliser des mots tels que modulaire, basé sur des composants et
couches pour décrire le processus. Les systèmes doivent être composés d'un ensemble de
modules coopérants, dont chacun implémente des fonctionnalités indépendantes
des autres. Parfois, ces composants sont organisés en couches, chacune
offrant un niveau d'abstraction. Cette approche en couches est un moyen puissant de
concevoir des systèmes orthogonaux. Parce que chaque couche utilise uniquement les abstractions
fournis par les couches en dessous, vous avez une grande flexibilité pour changer
implémentations sous-jacentes sans affecter le code. La superposition réduit également
le risque d'emballement des dépendances entre les modules. Vous verrez souvent
superposition exprimée dans des diagrammes tels que la figure 2.1 à la page suivante.

Illustration
Illustration 2.1.
2.1. Schéma
Schéma de
de couche
couche typique
typique

Il existe un test simple pour la conception orthogonale. Une fois que vous avez vos composants
cartographié, demandez-vous : si je change radicalement les exigences derrière
une fonction particulière, combien de modules sont concernés ? Dans une orthogonale
système, la réponse devrait être "un". [3] Déplacer un bouton sur un panneau GUI
ne devrait pas nécessiter de modification du schéma de la base de données. Ajouter
l'aide contextuelle ne doit pas modifier le sous-système de facturation.

[3] En réalité, c'est naïf. À moins d'être extrêmement chanceux, la plupart des changements d'exigences du monde réel affecteront plusieurs

fonctions dans le système. Cependant, si vous analysez le changement en termes de fonctions, chaque changement fonctionnel devrait toujours

idéalement affecter un seul module.

Considérons un système complexe de surveillance et de contrôle d'un chauffage


usine. L'exigence initiale prévoyait une interface utilisateur graphique, mais
les exigences ont été modifiées pour ajouter un système de réponse vocale avec
commande téléphonique à touches de l'usine. Dans une conception orthogonale
système, vous n'auriez besoin de modifier que les modules associés au
interface utilisateur pour gérer cela : la logique sous-jacente de contrôle de l'usine
resterait inchangé. En fait, si vous structurez soigneusement votre système,
vous devriez pouvoir prendre en charge les deux interfaces avec le même sous-jacent
base de codes. C'est juste une, parle
vuede l'écriture de code découplé à l'aide de
Le paradigme Modèle-Vue-Contrôleur (MVC), qui fonctionne bien dans ce
situation.

Demandez-vous également à quel point votre conception est découplée des changements dans le réel
monde. Utilisez-vous un numéro de téléphone comme identifiant client ? Quoi
se passe-t-il lorsque la compagnie de téléphone réattribue les indicatifs régionaux ? Ne comptez pas sur le
propriétés des choses que vous ne pouvez pas contrôler.

Boîtes
Boîtes àà outils
outils et
et bibliothèques
bibliothèques
Veillez à préserver l'orthogonalité de votre système lorsque vous introduisez
boîtes à outils et bibliothèques tierces. Choisissez judicieusement vos technologies.

Nous avons déjà travaillé sur un projet qui nécessitait qu'un certain corps de code Java
exécuter à la fois localement sur une machine serveur et à distance sur une machine cliente. Le
les alternatives pour distribuer les classes de cette manière étaient RMI et CORBA. Si un
classe ont été rendues accessibles à distance à l'aide de RMI, chaque appel à une télécommande
méthode dans cette classe pourrait potentiellement lever une exception, ce qui signifie
qu'une implémentation naïve nous obligerait à gérer l'exception
chaque fois que nos cours à distance étaient utilisés. L'utilisation de RMI ici n'est clairement pas
orthogonal : le code appelant nos classes distantes ne devrait pas être conscient de
leurs emplacements. L'alternative - en utilisant CORBA - n'imposait pas que
restriction : nous pourrions écrire du code qui ne connaîtrait pas l'emplacement de nos classes.

Lorsque vous apportez une boîte à outils (ou même une bibliothèque d'autres membres de votre
équipe), demandez-vous si cela impose des modifications à votre code qui ne devraient pas
Soyez là. Si un schéma de persistance d'objet est transparent, alors il est orthogonal.
Si cela vous oblige à créer ou à accéder à des objets d'une manière spéciale, alors ce n'est pas le cas.
Garder ces détails isolés de votre code a l'avantage supplémentaire de
faciliter le changement de fournisseur à l'avenir.

Le système Enterprise Java Beans (EJB) est un exemple intéressant de


orthogonalité. Dans la plupart des systèmes orientés transaction, le code d'application
doit délimiter le début et la fin de chaque transaction. Avec EJB, cela
les informations sont exprimées de manière déclarative sous forme de métadonnées, en dehors de tout code. Le
le même code d'application peut s'exécuter dans différents environnements de transaction EJB
sans changement. Ceci est susceptible d'être un modèle pour de nombreux environnements futurs.

Une autre tournure intéressante sur l'orthogonalité est l'aspect-orienté


Programming (AOP), un projet de recherche au Xerox Parc ([ KLM + 97 ] et [ URL

49 ]). AOP vous permet d'exprimer en un seul endroit un comportement qui serait autrement
répartis dans votre code source. Par exemple, les messages de journal sont
normalement généré en saupoudrant des appels explicites à une fonction de journalisation
tout au long de votre source. Avec AOP, vous implémentez la journalisation orthogonalement à
les choses étant enregistrées. En utilisant la version Java d'AOP, vous pouvez écrire un
message de journal lors de la saisie d'une méthode eFr de classe

Si vous intégrez cet aspect dans votre code, des messages de trace seront générés. Si
vous ne le faites pas, vous ne verrez aucun message. Dans tous les cas, votre source d'origine est
inchangé.

Codage
Codage

Chaque fois que vous écrivez du code, vous courez le risque de réduire l'orthogonalité de
ton application. Sauf si vous surveillez constamment non seulement ce que vous êtes
faire mais aussi le contexte plus large de l'application, vous pourriez
dupliquer involontairement des fonctionnalités dans un autre module, ou exprimer
connaissances existantes deux fois.

Il existe plusieurs techniques que vous pouvez utiliser pour maintenir l'orthogonalité :

• • Gardez votre code découplé. Écrivez du code timide - des modules qui ne le font pas
révéler tout ce qui n'est pas nécessaire aux autres modules et qui ne s'appuie pas sur
implémentations d'autres modules. Essayez la loi de Déméter [ LH89 ],
dont nous discutons dans Découplage et la loi de Déméter. Si tu as besoin
pour changer l'état d'un objet, demandez à l'objet de le faire pour vous. Par ici
votre code reste isolé de l'implémentation de l'autre code et
augmente les chances que vous restiez orthogonal.
• • Évitez les données globales. Chaque fois que votre code fait référence à des données globales,
il se lie aux autres composants qui partagent ces données. Même
les globales que vous avez uniquement l'intention de lire peuvent entraîner des problèmes (par exemple,
si vous avez soudainement besoin de changer votre code pour qu'il soit multithread). Dans
général, votre code est plus facile à comprendre et à maintenir si vous
transmettez explicitement tout contexte requis dans vos modules. Dans
applications orientées objet, le contexte est souvent passé en paramètre à
constructeurs d'objets. Dans un autre code, vous pouvez créer des structures
contenant le contexte et en faire circuler les références.

Le pattern Singleton dans Design Patterns [ GHJV95 ] est un moyen de


s'assurer qu'il n'y a qu'une seule instance d'un objet d'un
classe. Beaucoup de gens utilisent ces objets singleton comme une sorte de global
variable (en particulier dans les langages, tels que Java, qui autrement ne
ne prend pas en charge le concept de globals). Soyez prudent avec les singletons, ils
peut également conduire à des liens inutiles.

• • Évitez les fonctions similaires. Vous rencontrerez souvent un ensemble de


fonctions qui se ressemblent toutes - peut-être qu'elles partagent un code commun à
le début et la fin, mais chacun a un algorithme central différent.
Le code dupliqué est un symptôme de problèmes structurels. Jettes un coup d'oeil à
le pattern Strategy dans les Design Patterns pour une meilleure implémentation.

Prenez l'habitude d'être constamment critique de votre code. Cherchez n'importe quel
possibilités de le réorganiser pour améliorer sa structure et son orthogonalité.
Ce processus s'appelle le refactoring, et il est si important que nous avons dédié
une section (voir Refactoring ).

Essai
Essai

Un système conçu et mis en œuvre orthogonalement est plus facile à tester.


Parce que les interactions entre les composants du système sont formalisées
et limité, une plus grande partie des tests du système peut être effectuée au niveau individuel
niveau module. C'est une bonne nouvelle, car les tests au niveau du module (ou de l'unité) sont
considérablement plus facile à spécifier et à exécuter que les tests d'intégration. En fait,
nous suggérons que chaque module ait son propre test unitaire intégré dans son code, et
que ces tests soient effectués automatiquement dans le cadre de la construction régulière
processus (voir Code facile à tester ).

Construire des tests unitaires est en soi un test intéressant d'orthogonalité. Qu'est-ce que ça fait
prendre pour construire et lier un test unitaire? Devez-vous faire glisser un grand pourcentage
du reste du système juste pour obtenir un test à compiler ou à lier ? Si oui, vous avez
trouvé un module qui n'est pas bien découplé du reste du système.

La correction des bogues est également un bon moment pour évaluer l'orthogonalité du système en tant que
ensemble. Lorsque vous rencontrez un problème, évaluez la localisation du correctif. Faire
vous ne modifiez qu'un seul module, ou les modifications sont-elles dispersées dans tout le
tout le système ? Lorsque vous apportez un changement, résout-il tout ou fait-il autre chose ?
des problèmes surgissent mystérieusement? C'est une bonne occasion d'apporter
automatisation à supporter. Si vous utilisez un système de contrôle de code source (et vous
après avoir lu le contrôle du code source
), balisez les corrections de bugs lorsque vous vérifiez le code
denombre
le retour après le test.source
de fichiers Vous pouvez
affectésensuite exécuter
par chaque des rapports
correction mensuels analysant les tendances dans
de bogue.

Documentation
Documentation

De manière peut-être surprenante, l'orthogonalité s'applique également à la documentation. Le


les axes sont le contenu et la présentation. Avec une documentation vraiment orthogonale,
vous devriez pouvoir changer radicalement l'apparence sans
changer le contenu. Les traitements de texte modernes fournissent des feuilles de style et
macros qui aident (voir It's All Writing ).

Vivre
Vivre avec
avec l'orthogonalité
l'orthogonalité

L'orthogonalité est étroitement liée au principe DRY introduit à la page 27.


Avec DRY, vous cherchez à minimiser la duplication au sein d'un système,
alors qu'avec l'orthogonalité, vous réduisez l'interdépendance entre les
composants du système. C'est peut-être un mot maladroit, mais si vous utilisez le principe
d'orthogonalité, étroitement combiné avec le principe DRY, vous constaterez que
les systèmes que vous développez sont plus flexibles, plus compréhensibles et plus faciles
pour déboguer, tester et maintenir.

Si vous êtes amené dans un projet où les gens luttent désespérément pour
faire des changements, et où chaque changement semble causer quatre autres choses à
se tromper, rappelez-vous le cauchemar avec l'hélicoptère. Le projet
n'est probablement pas conçu et codé orthogonalement. Il est temps de refactoriser.

Et, si vous êtes pilote d'hélicoptère, ne mangez pas le poisson….

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Les maux de la duplication


• • Contrôle du code source
• • Conception par contrat
• • Le découplage et la loi de Déméter
• • Métaprogrammation
• • C'est juste une vue
• • Refactorisation
• • Code facile à tester
• • Sorciers maléfiques
• • Des équipes pragmatiques
• • Tout est écrit

Défis
Défis

• • Considérez la différence entre les grands outils orientés GUI


généralement trouvé sur les systèmes Windows et petit mais combinable
utilitaires de ligne de commande utilisés aux invites du shell. Quel ensemble est le plus
orthogonal, et pourquoi ? Ce qui est plus facile à utiliser pour exactement le but
pour qui il était destiné ? Quel ensemble est le plus facile à combiner avec d'autres
des outils pour relever de nouveaux défis ?
• • C++ prend en charge l'héritage multiple et Java permet à une classe de
implémenter plusieurs interfaces. Quel impact l'utilisation de ces
installations ont sur l'orthogonalité? Y a-t-il une différence d'impact
entre l'utilisation de plusieurs héritages et de plusieurs interfaces ? Y a-t-il
une différence entre l'utilisation de la délégation et l'utilisation de l'héritage ?

Des
Des exercices
exercices

1.
1. Vous écrivez une classe appelée Split, qui divise les lignes d'entrée en champs.
Laquelle des deux signatures de classe Java suivantes est la plus orthogonale
c o

2.
2. Ce qui conduira à un design plus orthogonal : dialogue modal ou modal
des boites?

3.
3. Qu'en est-il des langages procéduraux par rapport à la technologie objet ? Qui
aboutit à un système plus orthogonal ?

Réversibilité
Réversibilité

Rien n'est plus dangereux qu'une idée si c'est la seule que vous ayez.

Emil-Auguste
Emil-Auguste Chartier,
Chartier, Propos
Propos sur
sur la
la religion,
religion, 1938
1938

Les ingénieurs préfèrent des solutions simples et uniques aux problèmes. Des tests mathématiques qui permettent
vous proclamer avec une grande confiance que x = 2 sont beaucoup plus confortables
que des essais flous et chaleureux sur les innombrables causes de la Révolution française.
La direction a tendance à être d'accord avec les ingénieurs : des réponses simples et faciles
bien sur les feuilles de calcul et les plans de projet.

Si seulement le monde réel coopérait ! Malheureusement, alors que x vaut 2 aujourd'hui, il


peut avoir besoin d'être 5 demain, et 3 la semaine prochaine. Rien n'est éternel - et si vous
comptez beaucoup sur un fait, vous pouvez presque garantir qu'il changera.

Il y a toujours plus d'une façon de mettre en œuvre quelque chose, et il y a


généralement plus d'un fournisseur disponible pour fournir un produit tiers. Si
vous vous lancez dans un projet entravé par la notion myope qu'il n'y a qu'un seul
façon de le faire, vous risquez d'avoir une mauvaise surprise. De nombreuses équipes projets
ont les yeux ouverts de force alors que l'avenir se déroule:

"Mais vous avez dit que nous utiliserions la base de données XYZ ! Nous avons terminé le codage du projet à 85 %,
nous ne pouvons pas changer maintenant !" protesta le programmeur. "Désolé, mais notre entreprise
a décidé de standardiser sur la base de données PDQ à la place, pour tous les projets. C'est hors de
mes mains. Nous n'aurons qu'à recoder. Vous travaillerez tous les week-ends
jusqu'à nouvel ordre."

Les changements n'ont pas besoin d'être aussi draconiens, ni même aussi immédiats. Mais comme
le temps passe et votre projet avance, vous risquez de vous retrouver coincé dans un
position intenable. À chaque décision cruciale, l'équipe du projet s'engage
à une cible plus petite - une version plus étroite de la réalité qui a moins d'options.
Au moment où de nombreuses décisions critiques ont été prises, la cible devient si
petit que s'il bouge, ou que le vent change de direction, ou un papillon à Tokyo
bat des ailes, vous manquez.[4] Et vous risquez de manquer énormément.

[4] Prenez un système non linéaire ou chaotique et appliquez une petite modification à l'une de ses entrées. Vous pouvez obtenir un grand et souvent

résultat imprévisible. Le papillon cliché battant des ailes à Tokyo pourrait être le début d'une chaîne d'événements qui finit par

générant une tornade au Texas. Cela ressemble-t-il à des projets que vous connaissez ?

Le problème est que les décisions critiques ne sont pas facilement réversibles.

Une fois que vous décidez d'utiliser la base de données de ce fournisseur, ou ce modèle architectural,
ou un certain modèle de déploiement (client-serveur versus autonome, par
exemple), vous êtes engagé dans une ligne de conduite qui ne peut être annulée,
sauf à grands frais.

Réversibilité
Réversibilité

De nombreux sujets abordés dans ce livre visent à produire des informations flexibles et adaptables.
logiciel. En respectant leurs recommandations, en particulier le DRY
principe (page 26), découplage (page 138) et utilisation des métadonnées (page
144) – nous n'avons pas à prendre autant de décisions critiques et irréversibles. C'est
une bonne chose, parce que nous ne prenons pas toujours les meilleures décisions la première fois
autour. Nous nous engageons dans une certaine technologie seulement pour découvrir que nous ne pouvons pas embaucher
suffisamment de personnes possédant les compétences nécessaires. Nous verrouillons un certain tiers
fournisseur juste avant d'être racheté par son concurrent. Exigences,
les utilisateurs et le matériel changent plus vite que nous ne pouvons développer le logiciel.

Supposons que vous décidiez, au début du projet, d'utiliser une base de données relationnelle de
fournisseur A. Beaucoup plus tard, lors des tests de performances, vous découvrez que le
la base de données est tout simplement trop lente, mais que la base de données d'objets du fournisseur B est
plus rapide. Avec la plupart des projets conventionnels, vous n'auriez pas de chance. La plupart
temps, les appels à des produits tiers sont enchevêtrés dans le code. Mais si
vous avez vraiment abstrait l'idée d'une base de données - au point où elle
fournit simplement la persistance en tant que service, vous avez alors la possibilité de
changer de cheval en cours de route.

De même, supposons que le projet commence comme un modèle client-serveur, mais ensuite, tard
dans le jeu, le marketing décide que les serveurs sont trop chers pour certains
clients, et ils veulent une version autonome. À quel point cela serait-il difficile pour
toi ? Comme il ne s'agit que d'un problème de déploiement, cela ne devrait pas prendre plus de quelques
jours. Si cela prendrait plus de temps, alors vous n'avez pas pensé à la réversibilité.
L'autre sens est encore plus intéressant. Et si le stand-alone
le produit que vous fabriquez doit être déployé dans un client-serveur ou n-tier
mode? Cela ne devrait pas être difficile non plus.

L'erreur consiste à supposer que toute décision est immuable - et non


se préparer aux imprévus qui pourraient survenir. Au lieu de tailler
décisions dans la pierre, considérez-les davantage comme étant écrites dans le sable au
plage. Une grosse vague peut arriver et les anéantir à tout moment.

Astuce
Astuce 14
14

Il n'y a pas de décisions finales

Architecture
Architecture flexible
flexible

Alors que beaucoup de gens essaient de garder leur code flexible, vous devez également penser
sur le maintien de la flexibilité dans les domaines de l'architecture, du déploiement et
intégration des fournisseurs.

Des technologies telles que CORBA peuvent aider à isoler des parties d'un projet de
changements dans le langage ou la plate-forme de développement. La performance de Java est-elle
sur cette plate-forme pas à la hauteur des attentes ? Recoder le client en C++, et
rien d'autre ne doit changer. Le moteur de règles en C++ n'est-il pas assez flexible ?
Passez à une version Smalltalk. Avec une architecture CORBA, vous avez
prendre un coup uniquement pour le composant que vous remplacez ; L'autre
les composants ne devraient pas être affectés.

Développez-vous pour Unix ? Lequel? Avez-vous toute la portabilité


préoccupations abordées ? Développez-vous pour une version particulière de
Les fenêtres? Lequel—3.1, 95, 98, NT, CE ou 2000 ? À quel point sera-t-il difficile de
prendre en charge d'autres versions ? Si vous gardez des décisions souples et flexibles, ce ne sera pas
dur du tout. Si vous avez une mauvaise encapsulation, un couplage élevé et un code dur
logique ou des paramètres dans le code, cela pourrait être impossible.

Vous ne savez pas comment le marketing souhaite déployer le système ? Pensez-y


front et vous pouvez prendre en charge un modèle autonome, client-serveur ou n-tier juste
en modifiant un fichier de configuration. Nous avons écrit des programmes qui font exactement cela.

Normalement, vous pouvez simplement cacher un produit tiers derrière un bien défini,
interface abstraite. En fait, nous avons toujours été en mesure de le faire sur n'importe quel projet
nous avons travaillé. Mais supposons que vous ne puissiez pas l'isoler aussi proprement. Et qu'est-ce qui se passerait si
vous avez dû saupoudrer généreusement certaines déclarations tout au long du code ? Mettre
cette exigence dans les métadonnées et utiliser un mécanisme automatique, tel que
comme Aspects (voir page 39) ou Perl, pour insérer les instructions nécessaires dans le
code lui-même. Quel que soit le mécanisme que vous utilisez, rendez-le réversible. Si quelque chose
est ajouté automatiquement, il peut également être retiré automatiquement.

Personne ne sait ce que l'avenir nous réserve, surtout pas nous ! Alors activez votre
code to rock-n-roll : "rocker" quand c'est possible, encaisser les coups quand c'est possible
devoir.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Le découplage et la loi de Déméter


• • Métaprogrammation
• • C'est juste une vue

Défis
Défis

• • C'est l'heure d'un peu de mécanique quantique avec le chat de Schrödinger.


Supposons que vous ayez un chat dans une boîte fermée, accompagné d'un
particule. La particule a exactement 50 % de chance de se scinder en deux.
Si c'est le cas, le chat sera tué. Si ce n'est pas le cas, le chat ira bien. Alors, est
le chat mort ou vivant ? Selon Schrödinger, la bonne réponse est
les deux. Chaque fois qu'une réaction subnucléaire a lieu qui a deux
résultats possibles, l'univers est cloné. Dans l'un, l'événement s'est produit,
dans l'autre non. Le chat est vivant dans un univers, mort dans un autre.
Ce n'est qu'en ouvrant la boîte que vous savez dans quel univers vous vous trouvez.

Pas étonnant que coder pour l'avenir soit difficile.

Mais pensez à l'évolution du code dans le même sens qu'à une boîte pleine de
Les chats de Schrödinger : chaque décision aboutit à une version différente du
avenir. Combien de futurs possibles votre code peut-il supporter ? Qui
ceux sont plus probables? À quel point sera-t-il difficile de les soutenir lorsque le
le temps vient?
Oserez-vous ouvrir la boîte ?

Balles
Balles traçantes
traçantes

À vos marques, tirez, visez…

[5] Vous pouvez découvrir


Il y a deux façons de tirer avec une mitrailleuse dans l'obscurité.
exactement où se trouve votre cible (portée, élévation et azimut). Tu peux
déterminer les conditions environnementales (température, humidité, air
pression, vent, etc.). Vous pouvez déterminer les spécifications précises de
les cartouches et les balles que vous utilisez, et leurs interactions avec le
l'arme réelle que vous tirez. Vous pouvez ensuite utiliser des tables ou un ordinateur de tir pour
calculer le relèvement et l'élévation exacts du baril. Si tout fonctionne
exactement comme spécifié, vos tables sont correctes et l'environnement ne
changer, vos balles devraient atterrir près de leur cible.

[5] Pour être pédant, il existe de nombreuses façons de tirer avec une mitrailleuse dans le noir, notamment en fermant les yeux et en pulvérisant

balles. Mais c'est une analogie, et nous sommes autorisés à prendre des libertés.

Ou vous pouvez utiliser des balles traçantes.

Les balles traçantes sont chargées à intervalles réguliers sur la ceinture de munitions aux côtés des
munition. Lorsqu'ils sont tirés, leur phosphore s'enflamme et laisse une
piste pyrotechnique du pistolet à tout ce qu'ils ont touché. Si les traceurs sont
toucher la cible, alors les balles régulières le sont aussi.

Sans surprise, les balles traçantes sont préférées au travail de calcul. Le


le retour d'information est immédiat, et parce qu'ils opèrent dans le même environnement
comme les vraies munitions, les effets externes sont minimisés.

L'analogie est peut-être violente, mais elle s'applique aux nouveaux projets, notamment
lorsque vous construisez quelque chose qui n'a pas été construit auparavant. Comme le
artilleurs, vous essayez d'atteindre une cible dans le noir. Parce que vos utilisateurs ont
jamais vu un système comme celui-ci auparavant, leurs exigences peuvent être vagues.
Parce que vous utilisez peut-être des algorithmes, des techniques, des langages ou des bibliothèques
que vous ne connaissez pas, vous faites face à un grand nombre d'inconnues. Et
parce que les projets prennent du temps à se terminer, vous pouvez à peu près garantir le
l'environnement dans lequel vous travaillez changera avant que vous n'ayez terminé.

La réponse classique est de spécifier le système à mort. Produire des rames de


papier détaillant chaque exigence, fixant chaque inconnue, et
contraignant l'environnement. Tirez avec l'arme à l'estime. Un grand
calcul à l'avant, puis tirez et espérez.

Les programmeurs pragmatiques, cependant, ont tendance à préférer l'utilisation de balles traçantes.

Code
Code qui
qui brille
brille dans
dans le
le noir
noir

Les balles traçantes fonctionnent parce qu'elles fonctionnent dans le même environnement et
sous les mêmes contraintes que les balles réelles. Ils arrivent rapidement à la cible,
Ainsi, le tireur reçoit une rétroaction immédiate. Et d'un point de vue pratique
ils sont une solution relativement bon marché.

Pour obtenir le même effet dans le code, nous recherchons quelque chose qui nous permette de
une exigence à certains aspects du système final rapidement, visiblement et
de façon répétée.

Astuce
Astuce 15
15

Utilisez des balles traçantes pour trouver la cible

Nous avons déjà entrepris un projet complexe de marketing de base de données client-serveur.
Une partie de son exigence était la capacité de spécifier et d'exécuter des
requêtes. Les serveurs étaient une gamme de bases de données relationnelles et spécialisées.
L'interface graphique du client, écrite en Pascal Objet, utilisait un ensemble de bibliothèques C pour fournir
une interface avec les serveurs. La requête de l'utilisateur était stockée sur le serveur dans un
Notation de type Lisp avant d'être convertie en SQL optimisé juste avant
exécution. Il y avait beaucoup d'inconnues et de nombreux environnements différents,
et personne ne savait trop comment l'interface graphique devait se comporter.

C'était une excellente occasion d'utiliser le code traceur. Nous avons développé le
framework pour le front-end, des bibliothèques pour représenter les requêtes, et un
structure permettant de convertir une requête stockée en une requête spécifique à la base de données. Alors
nous avons tout assemblé et vérifié que cela fonctionnait. Pour cette version initiale, tous
nous pourrions faire était de soumettre une requête qui répertorie toutes les lignes d'une table, mais il
prouvé que l'interface utilisateur pouvait parler aux bibliothèques, les bibliothèques pouvaient sérialiser
et désérialiser une requête, et le serveur pourrait générer du SQL à partir du résultat.
Au cours des mois suivants, nous avons progressivement étoffé cette structure de base,
ajouter de nouvelles fonctionnalités en augmentant chaque composant du code traceur
en parallèle. Lorsque l'interface utilisateur a ajouté un nouveau type de requête, la bibliothèque s'est agrandie et le
La génération SQL a été rendue plus sophistiquée.

Le code traceur n'est pas jetable : vous l'écrivez pour toujours. Il contient toutes les erreurs
vérifier, structurer, documenter et auto-vérifier que tout élément de
code de production a. Il n'est tout simplement pas entièrement fonctionnel. Cependant, une fois que vous
avez réalisé une connexion de bout en bout entre les composants de votre
système, vous pouvez vérifier à quelle distance vous vous trouvez de la cible, en ajustant si
nécessaire. Une fois que vous êtes sur la cible, ajouter des fonctionnalités est facile.

Le développement de Tracer est cohérent avec l'idée qu'un projet n'est jamais
terminé : il y aura toujours des modifications à apporter et des fonctions à ajouter. C'est
une approche incrémentale.

L'alternative conventionnelle est une sorte d'approche d'ingénierie lourde : le code


est divisé en modules, qui sont codés dans le vide. Les modules sont
combinés en sous-ensembles, qui sont ensuite combinés, jusqu'à ce qu'un
jour où vous avez une demande complète. Ce n'est qu'alors que l'application en tant que
ensemble être présenté à l'utilisateur et testé.

L'approche par code traceur présente de nombreux avantages :

• • Les utilisateurs voient quelque chose fonctionner tôt. Si tu as


communiqué avec succès ce que vous faites (voir Great
Attentes ), vos utilisateurs sauront qu'ils voient quelque chose
immature. Ils ne seront pas déçus par un manque de fonctionnalité ;
ils seront ravis de voir des progrès visibles vers leur système.
Ils peuvent également contribuer au fur et à mesure que le projet progresse, augmentant ainsi leur
achat. Ces mêmes utilisateurs seront probablement ceux qui vous diront comment
proche de la cible à chaque itération.
• • Les développeurs construisent une structure dans laquelle travailler. Le plus intimidant
morceau de papier est celui qui n'a rien d'écrit dessus. Si tu as
élaboré toutes les interactions de bout en bout de votre application, et
les avez incorporés dans le code, alors votre équipe n'aura pas besoin de tirer comme
beaucoup à partir de rien. Cela rend tout le monde plus productif et
encourage la cohérence.
• • Vous disposez d'une plateforme d'intégration. Comme le système est connecté
de bout en bout, vous disposez d'un environnement auquel vous pouvez ajouter de nouveaux
morceaux de code une fois qu'ils ont été testés unitairement. Plutôt que
tenter une intégration big bang, vous intégrerez tous les jours
(souvent plusieurs fois par jour). L'impact de chaque nouveau changement est plus
apparente, et les interactions sont plus limitées, donc le débogage et
les tests sont plus rapides et plus précis.
• • Vous avez quelque chose à démontrer. Les sponsors du projet et top
les cuivres ont tendance à vouloir voir des démos au plus gênant
fois. Avec le code traceur, vous aurez toujours quelque chose à leur montrer.
• • Vous avez une meilleure idée du progrès. Dans un code traceur
développement, les développeurs abordent les cas d'utilisation un par un. Quand on est
terminé, ils passent au suivant. Il est beaucoup plus facile de mesurer les performances
et pour démontrer les progrès à votre utilisateur. Parce que chaque individu
développement est plus petit, vous évitez de créer ces blocs monolithiques de
code qui sont signalés comme étant complets à 95 % semaine après semaine.

Les
Les balles
balles traçantes
traçantes n'atteignent
n'atteignent pas
pas toujours
toujours leur
leur cible
cible

Les balles traçantes montrent ce que vous frappez. Ce n'est peut-être pas toujours la cible.
Vous ajustez ensuite votre objectif jusqu'à ce qu'ils soient sur la cible. C'est le but.

C'est la même chose avec le code traceur. Vous utilisez la technique dans des situations où
vous n'êtes pas sûr à 100% de l'endroit où vous allez. Vous ne devriez pas être surpris si
vos deux premières tentatives échouent : l'utilisateur dit "ce n'est pas ce que je voulais dire"
ou les données dont vous avez besoin ne sont pas disponibles lorsque vous en avez besoin, ou des problèmes de performances
semblent probables. Trouvez comment changer ce que vous avez pour le rapprocher du
objectif, et soyez reconnaissant d'avoir utilisé une méthodologie de développement Lean.
Un petit corps de code a une faible inertie, il est facile et rapide à changer. Vous allez
être en mesure de recueillir des commentaires sur votre application et de générer un nouveau, plus
version précise plus rapidement et à moindre coût qu'avec toute autre méthode. Et
parce que chaque composant majeur de l'application est représenté dans votre traceur
code, vos utilisateurs peuvent être sûrs que ce qu'ils voient est basé sur
réalité, pas seulement une spécification papier.

Code
Code traceur
traceur versus
versus prototypage
prototypage

Vous pourriez penser que ce concept de code traceur n'est rien de plus que
prototypage sous un nom agressif. Il existe une différence. Avec un
prototype, vous visez à explorer des aspects spécifiques du système final. Avec
un vrai prototype, vous jeterez tout ce que vous aurez assemblé quand
essayer le concept et le recoder correctement en utilisant les leçons que vous avez
appris.

Par exemple, supposons que vous produisiez une application qui aide les expéditeurs
déterminer comment emballer des boîtes de taille impaire dans des conteneurs. Parmi d'autres
problèmes, l'interface utilisateur doit être intuitive et les algorithmes que vous
utiliser pour déterminer l'emballage optimal sont très complexes.

Vous pouvez prototyper une interface utilisateur pour vos utilisateurs finaux dans un outil graphique. Toi
code juste assez pour rendre l'interface réactive aux actions de l'utilisateur. Une fois
ils ont accepté la mise en page, vous pouvez la jeter et la recoder, ceci
temps avec la logique métier qui la sous-tend, en utilisant le langage cible. De la même manière,
vous voudrez peut-être prototyper un certain nombre d'algorithmes qui effectuent le
emballage proprement dit. Vous pouvez coder des tests fonctionnels de haut niveau et indulgents

langage tel que Perl et coder des tests de performances de bas niveau dans quelque chose
plus près de la machine. Dans tous les cas, une fois votre décision prise, vous
recommencer et coder les algorithmes dans leur environnement final, en s'interfaçant
au monde réel. C'est du prototypage, et c'est très utile.

L'approche du code traceur résout un problème différent. Tu dois savoir


comment l'application dans son ensemble s'articule. Vous voulez montrer votre
utilisateurs comment les interactions fonctionneront dans la pratique, et vous voulez donner votre
développeurs un squelette architectural sur lequel accrocher le code. Dans ce cas,
vous pouvez construire un traceur consistant en une implémentation triviale de la
algorithme d'emballage de conteneur (peut-être quelque chose comme premier arrivé, premier servi)
et une interface utilisateur simple mais fonctionnelle. Une fois que vous avez tous les composants
dans l'application plombée ensemble, vous avez un cadre pour montrer votre
utilisateurs et vos développeurs. Au fil du temps, vous ajoutez à ce cadre de nouvelles
fonctionnalité, complétant des routines stubed. Mais le cadre reste intact,
et vous savez que le système continuera à se comporter comme il le faisait lorsque votre
premier code traceur a été complété.

La distinction est suffisamment importante pour mériter d'être répétée. Prototypage


génère du code jetable. Le code traceur est léger mais complet et fait partie
du squelette du système final. Considérez le prototypage comme le
reconnaissance et collecte de renseignements qui ont lieu devant un seul
balle traçante est tirée.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Logiciel suffisamment bon


• • Prototypes et Post-it
• • Le piège des spécifications
• • De grandes attentes

Prototypes
Prototypes et
et Post-it
Post-it

De nombreuses industries différentes utilisent des prototypes pour tester des idées spécifiques ;
le prototypage est beaucoup moins cher que la production à grande échelle. Les constructeurs automobiles, pour
par exemple, peut construire de nombreux prototypes différents d'une nouvelle conception de voiture. Chaque
l'un est conçu pour tester un aspect spécifique de la voiture - l'aérodynamique,
style, caractéristiques structurelles, etc. Peut-être qu'un modèle en argile sera
construit pour les essais en soufflerie, peut-être qu'un modèle en bois de balsa et ruban adhésif sera
faire pour le département artistique, et ainsi de suite. Certains constructeurs automobiles franchissent cette étape
plus loin, et font maintenant beaucoup de travail de modélisation sur ordinateur,
réduisant encore plus les coûts. De cette façon, des éléments risqués ou incertains peuvent être
essayé sans s'engager à construire l'objet réel.

Nous construisons des prototypes de logiciels de la même manière, et pour le même


raisons - pour analyser et exposer les risques, et pour offrir des chances de correction à un
coût fortement réduit. Comme les constructeurs automobiles, nous pouvons cibler un prototype à tester
un ou plusieurs aspects spécifiques d'un projet.

Nous avons tendance à penser que les prototypes sont basés sur du code, mais ils ne doivent pas toujours
être. Comme les constructeurs automobiles, nous pouvons construire des prototypes à partir de différents matériaux.
Les post-it sont parfaits pour prototyper des éléments dynamiques tels que le flux de travail
et la logique d'application. Une interface utilisateur peut être prototypée sous la forme d'un dessin sur un
tableau blanc, comme une maquette non fonctionnelle dessinée avec un programme de peinture, ou
avec un constructeur d'interface.

Les prototypes sont conçus pour répondre à quelques questions seulement, ils sont donc beaucoup
moins cher et plus rapide à développer que les applications qui entrent en production. Le
le code peut ignorer des détails sans importance, sans importance pour vous pour le moment,
mais probablement très important pour l'utilisateur plus tard. Si vous prototypez un
GUI, par exemple, vous pouvez vous en tirer avec des résultats ou des données incorrects. Sur le
d'autre part, si vous étudiez simplement le calcul ou les performances
aspects, vous pouvez vous en sortir avec une interface graphique assez médiocre, ou peut-être même pas d'interface graphique
du tout.

Mais si vous vous trouvez dans un environnement où vous ne pouvez pas abandonner le
détails, alors vous devez vous demander si vous construisez vraiment un prototype
du tout. Peut-être qu'un développement de style balle traçante serait plus
approprié dans ce cas (voir Tracer Bullets ).

Choses
Choses àà prototyper
prototyper

Quelles sortes de choses pourriez-vous choisir d'étudier avec un prototype ?


Tout ce qui comporte des risques. Tout ce qui n'a pas été essayé auparavant, ou qui est
absolument critique pour le système final. Tout ce qui n'est pas prouvé, expérimental ou
douteux. Tout ce avec quoi vous n'êtes pas à l'aise. Vous pouvez prototyper

• • Architecture
• • Nouvelle fonctionnalité dans un système existant
• • Structure ou contenu des données externes
• • Outils ou composants tiers
• • Les problèmes de performance
• • Design de l'interface utilisateur

Le prototypage est une expérience d'apprentissage. Sa valeur ne réside pas dans le code produit,
mais dans les leçons apprises. C'est vraiment le but du prototypage.

Astuce
Astuce 16
16

Prototype à apprendre

Comment
Comment utiliser
utiliser les
les prototypes
prototypes

Lors de la construction d'un prototype, quels détails pouvez-vous ignorer ?

• • Exactitude. Vous pourrez peut-être utiliser des données fictives où


approprié.
• • Complétude. Le prototype ne peut fonctionner que dans un très
sens limité, peut-être avec une seule donnée d'entrée présélectionnée
et un élément de menu.
• • Robustesse. La vérification des erreurs est susceptible d'être incomplète ou
manque entièrement. Si vous vous écartez du chemin prédéfini, le prototype
peut s'écraser et brûler dans une glorieuse démonstration de pyrotechnie. C'est
d'accord.
• • Style. C'est douloureux de l'admettre en version imprimée, mais le code prototype
n'a probablement pas beaucoup de commentaires ou
Documentation. Vous pouvez produire des tonnes de documents en conséquence
de votre expérience avec le prototype, mais relativement peu
sur le système prototype lui-même.

Étant donné qu'un prototype doit passer sous silence les détails et se concentrer sur des aspects spécifiques
du système envisagé, vous souhaiterez peut-être mettre en œuvre des prototypes
en utilisant un langage de très haut niveau - plus élevé que le reste du projet
(peut-être un langage tel que Perl, Python ou Tcl). Une scénarisation de haut niveau
le langage vous permet de différer de nombreux détails (y compris la spécification des types de données) et
produisent toujours un morceau de code fonctionnel (bien qu'incomplet [6] Si
ouvous
lent).
besoin de prototyper des interfaces utilisateur, d'étudier des outils tels que Tcl/Tk, Visual
Basique, Powerbuilder ou Delphi.

[6] Si vous recherchez des performances absolues (et non relatives), vous devrez vous en tenir à un langage proche

performance à la langue cible.

Les langages de script fonctionnent bien comme "colle" pour combiner des éléments de bas niveau en
nouvelles combinaisons. Sous Windows, Visual Basic peut coller ensemble COM
contrôles. Plus généralement, vous pouvez utiliser des langages tels que Perl et Python pour
lier ensemble des bibliothèques C de bas niveau, soit manuellement, soit automatiquement avec
des outils tels que le SWIG disponible gratuitement].[En
URL
utilisant
28 cette approche, vous
peut assembler rapidement des composants existants dans de nouvelles configurations pour voir
comment les choses fonctionnent.
Architecture
Architecture de
de prototypage
prototypage
De nombreux prototypes sont construits pour modéliser l'ensemble du système sous
considération. Contrairement aux balles traçantes, aucun des modules individuels
dans le système prototype doivent être particulièrement fonctionnels. En fait, vous pouvez
même pas besoin de coder pour prototyper l'architecture - vous pouvez prototyper
sur un tableau blanc, avec des Post-it ou des fiches. Qu'est-ce que tu cherches
c'est ainsi que le système se tient dans son ensemble, reportant encore une fois les détails. Ici
sont des domaines spécifiques que vous voudrez peut-être rechercher dans l'architecture
prototype:

• • Les responsabilités des principales composantes sont-elles bien définies


et approprié?
• • Les collaborations entre les principaux composants sont-elles bien définies ?
• • Le couplage est-il minimisé ?
• • Pouvez-vous identifier les sources potentielles de duplication ?
• • Les définitions et contraintes d'interface sont-elles acceptables ?
• • Chaque module a-t-il un chemin d'accès aux données dont il a besoin
lors de l'exécution ? A-t-il cet accès quand il en a besoin ?

Ce dernier élément a tendance à générer le plus de surprises et le plus précieux


résultats de l'expérience de prototypage.

Comment
Comment ne
ne pas
pas utiliser
utiliser de
de prototypes
prototypes

Avant de vous lancer dans un prototypage basé sur du code, assurez-vous que tout le monde
comprend que vous écrivez du code jetable. Les prototypes peuvent être
trompeusement attrayant pour les gens qui ne savent pas qu'ils sont juste
prototypes. Vous devez indiquer très clairement que ce code est jetable,
incomplet et impossible à compléter.

Il est facile d'être induit en erreur par l'exhaustivité apparente d'un


prototype, et les sponsors ou la direction du projet peuvent insister pour déployer le
prototype (ou sa progéniture) si vous ne fixez pas les bonnes attentes. Rappeler
eux que vous pouvez construire un grand prototype d'une nouvelle voiture en bois de balsa
et du ruban adhésif, mais vous n'essaieriez pas de le conduire dans les embouteillages aux heures de pointe !

Si vous sentez qu'il y a une forte possibilité dans votre environnement ou votre culture que
le but du code prototype peut être mal interprété, il vaut peut-être mieux
avec l'approche de la balle traçante. Vous vous retrouverez avec un cadre solide sur
sur lesquelles fonder le développement futur.

Lorsqu'il est utilisé correctement, un prototype peut vous faire économiser énormément de temps, d'argent,
la douleur et la souffrance en identifiant et en corrigeant les problèmes potentiels
tôt dans le cycle de développement - le moment où corriger les erreurs est à la fois
pas cher et facile.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Le chat a mangé mon code source


• • Communiquer!
• • Balles traçantes
• • De grandes attentes

Des
Des exercices
exercices

4.
4. Le marketing aimerait s'asseoir et réfléchir à quelques pages Web
conçoit avec vous. Ils pensent à des cartes d'images cliquables pour prendre
vers d'autres pages, etc. Mais ils ne peuvent pas décider d'un modèle pour le
image—c'est peut-être une voiture, ou un téléphone, ou une maison. Vous avez une liste de cibles
pages et contenu ; ils aimeraient voir quelques prototypes. Oh au fait,
vous avez 15 minutes. Quels outils pourriez-vous utiliser ?
Langues
Langues du
du domaine
domaine

Les limites du langage sont les limites de son monde.

Ludwig
Ludwig Von
Von Wittgenstein
Wittgenstein

Les langages informatiques influencent la façon dont vous pensez à un problème, et comment
vous pensez à communiquer. Chaque langue est accompagnée d'une liste de
fonctionnalités - mots à la mode tels que saisie statique ou dynamique, précoce ou
liaison tardive, modèles d'héritage (simple, multiple ou aucun) - tous
peut suggérer ou obscurcir certaines solutions. Concevoir une solution avec Lisp en
l'esprit produira des résultats différents d'une solution basée sur le style C
penser, et vice versa. A l'inverse, et nous pensons plus important encore, la
langage du domaine du problème peut également suggérer une solution de programmation.

Nous essayons toujours d'écrire du code en utilisant le vocabulaire du domaine d'application


(voir Le puits des exigences , où nous suggérons d'utiliser un glossaire de projet). Dans
certains cas, nous pouvons passer au niveau suivant et réellement programmer en utilisant le
le vocabulaire, la syntaxe et la sémantique (le langage) du domaine.

Lorsque vous écoutez les utilisateurs d'un système proposé, ils peuvent être en mesure de dire
vous expliquez exactement comment le système devrait fonctionner :

Écouter les transactions définies par le règlement ABC 12.3 sur un ensemble de X.25
lignes, traduisez-les au format 43B de la société XYZ, retransmettez-les sur
la liaison montante du satellite et la stocker pour une analyse future.

Si vos utilisateurs disposent d'un certain nombre d'instructions bien délimitées, vous pouvez
inventer un mini-langage adapté au domaine d'application qui exprime
e ax

Ce langage n'a pas besoin d'être exécutable. Au départ, il pourrait s'agir simplement d'un moyen de
capturer les exigences de l'utilisateur - une spécification. Cependant, vous pouvez
voulons envisager d'aller plus loin et de mettre en œuvre
langue. Votre spécification est devenue un code exécutable.

Une fois que vous avez écrit l'application, les utilisateurs vous donnent une nouvelle exigence :
les transactions avec des soldes négatifs ne doivent pas être stockées et doivent être envoyées
er t

C'était facile, n'est-ce pas ? Avec le support approprié en place, vous pouvez
programme beaucoup plus proche du domaine d'application. Nous ne suggérons pas que
vos utilisateurs finaux programment réellement dans ces langages. Au lieu de cela, vous donnez
vous un outil qui vous permet de travailler plus près de leur domaine.

Astuce
Astuce 17
17

Programme proche du domaine du problème


Qu'il s'agisse d'un langage simple pour configurer et contrôler une application
programme, ou un langage plus complexe pour spécifier des règles ou des procédures, nous
pensez que vous devriez envisager des moyens de rapprocher votre projet du problème
domaine. En codant à un niveau d'abstraction plus élevé, vous êtes libre de
se concentrer sur la résolution des problèmes de domaine et peut ignorer les petits
Détails d'implémentation.

N'oubliez pas qu'il existe de nombreux utilisateurs d'une application. Il y a la fin


utilisateur, qui comprend les règles métier et les sorties requises. Là
sont également des utilisateurs secondaires : opérationnels, responsables de configuration et de test,
programmeurs de support et de maintenance, et les futures générations de
développeurs. Chacun de ces utilisateurs a son propre domaine de problème, et vous pouvez
générer des mini-environnements et des langages pour chacun d'eux.

Erreurs spécifiques au domaine

Si vous écrivez dans le domaine du problème, vous pouvez également effectuer


validation spécifique au domaine, signalement des problèmes en termes de vos utilisateurs
peut comprendre. Prenez notre application de commutation sur le parement
p a

Si cela s'est produit dans une programmation standard à usage général


langue, vous pouvez recevoir une erreur standard à usage général
em s

Mais avec un mini-langue, vous seriez plutôt en mesure d'émettre un


em s

Implémentation
Implémentation d'un
d'un mini-langage
mini-langage

Dans sa forme la plus simple, un mini-langage peut être dans un langage orienté ligne, facilement analysé
format. En pratique, nous utilisons probablement ce formulaire plus que tout autre. Ça peut
être analysé simplement à l'aide d'instructions switch ou d'expressions régulières dans

langages de script tels que Perl. La réponse à l'exercice 5 à la page 281


montre une implémentation simple en C.

Vous pouvez également implémenter un langage plus complexe, avec un langage plus formel
syntaxe. L'astuce ici est de définir d'abord la syntaxe en utilisant une notation telle que
BNF. [7] Une fois que vous avez spécifié votre grammaire, il est normalement trivial de
convertissez-le en syntaxe d'entrée pour un générateur d'analyseur. C et C++
les programmeurs utilisent yacc (ou son implémentation librement disponible,
bison [ URL 27 ]) depuis des années. Ces programmes sont documentés en détail dans le
livre Lex et Yacc [ LMB92 ]. Les programmeurs Java peuvent essayer javaCC, qui peut
être trouvé à [ URL 26 ]. La réponse à l'exercice 7 de la page 282 montre un analyseur
écrit en utilisant
bison. Comme il le montre, une fois que vous connaissez la syntaxe, ce n'est vraiment pas un
beaucoup de travail pour écrire des mini-langages simples.

[7] BNF, ou Backus-Naur Form, vous permet de spécifier des grammaires hors-contexte de manière récursive. Tout bon livre sur le compilateur

la construction ou l'analyse couvrira BNF en détail (exhaustif).

Il existe une autre manière d'implémenter un mini-langage : étendre un


un. Par exemple, vous pouvez intégrer des fonctionnalités au niveau de l'application avec
(disons) Python [ URL] 9et écrivez quelque chose comme
[8]

[ 8

Langages
Langages de
de données
données et
et langages
langages impératifs
impératifs

Les langages que vous implémentez peuvent être utilisés de deux manières différentes.

Les langages de données produisent une certaine forme de structure de données utilisée par une application.
Ces langages sont souvent utilisés pour représenter les informations de configuration.

Par exemple, le programme sendmail est utilisé dans le monde entier pour
routage des e-mails sur Internet. Il possède de nombreuses fonctionnalités excellentes et
avantages, qui sont contrôlés par un fichier de configuration de mille lignes, écrit
e n u

F=sl

De toute évidence, la lisibilité n'est pas l'un des points forts de sendmail.

Depuis des années, Microsoft utilise un langage de données capable de décrire


menus, widgets, boîtes de dialogue et autres ressources Windows. Figure 2.2 sur
la page suivante montre un extrait d'un fichier de ressources typique. C'est beaucoup plus facile
à lire que le exemple sendmail, mais il est utilisé exactement de la même manière
façon - il est compilé pour générer une structure de données.

Illustration
Illustration 2.2.
2.2. Fichier
Fichier .rc
.rc Windows
Windows
Les langages impératifs vont encore plus loin. Ici la langue est
réellement exécuté, et peut donc contenir des instructions, des constructions de contrôle et
similaire (comme le script de la page 58).

Vous pouvez également utiliser vos propres langages impératifs pour faciliter le programme
entretien. Par exemple, il peut vous être demandé d'intégrer des informations provenant de
une application héritée dans votre nouveau développement d'interface graphique. Une façon courante de
y parvenir se fait par grattage d'écran; votre application se connecte au
application mainframe comme s'il s'agissait d'un utilisateur humain normal, émettant
frappes et "lire" les réponses qu'il reçoit. Vous pouvez scripter le
interaction à l'aide d'un mini-langage.[9]

[9] En fait, vous pouvez acheter des outils qui ne prennent en charge que ce type de script. Vous pouvez également rechercher des packages open source tels que

que Expect, qui offrent des fonctionnalités similaires [ URL


]. 24

ol c

Lorsque l'application détermine qu'il est temps d'entrer un numéro de sécurité sociale
nombre, il invoque l'interpréteur sur ce script, qui contrôle alors le
transaction. Si l'interpréteur est intégré à l'application, les deux
peut même partager des données directement (par exemple, via un mécanisme de rappel).

Ici, vous programmez dans le domaine du programmeur de maintenance. Quand


l'application mainframe change et les champs se déplacent, le
programmeur peut simplement mettre à jour votre description de haut niveau, plutôt que
ramper dans les détails du code C.

Langages
Langages autonomes
autonomes et
et intégrés
intégrés

Un mini-langage n'a pas besoin d'être utilisé directement par l'application pour être
utile. Plusieurs fois, nous pouvons utiliser un langage de spécification pour créer des artefacts
(y compris les métadonnées) qui sont compilées, lues ou autrement utilisées par le
programme lui-même (voir Métaprogrammation).

Par exemple, à la page 100, nous décrivons un système dans lequel nous avons utilisé Perl pour
générer un grand nombre de dérivations à partir d'un schéma original
spécification. Nous avons inventé un langage commun pour exprimer la base de données
schéma, puis généré toutes les formes dont nous avions besoin—SQL, C, Web
pages, XML et autres. L'application n'a pas utilisé la spécification
directement, mais il s'appuyait sur la sortie qu'il produisait.

Il est courant d'intégrer des langages impératifs de haut niveau directement dans votre
application, afin qu'ils s'exécutent lorsque votre code s'exécute. Il s'agit clairement d'un
capacité puissante; vous pouvez modifier le comportement de votre application en
changer les scripts qu'il lit, le tout sans compiler. Cela peut considérablement
simplifier la maintenance dans un domaine d'application dynamique.

Développement
Développement facile
facile ou
ou maintenance
maintenance facile
facile ??
Nous avons examiné plusieurs grammaires différentes, allant du simple
formats orientés ligne à des grammaires plus complexes qui ressemblent à de vrais
langues. Étant donné que sa mise en œuvre demande des efforts supplémentaires, pourquoi choisiriez-vous un
grammaire plus complexe ?

Le compromis est l'extensibilité et la maintenance. Alors que le code d'analyse d'un


la "vraie" langue peut être plus difficile à écrire, il sera beaucoup plus facile pour les gens de
comprendre, et d'étendre à l'avenir avec de nouvelles fonctionnalités et
Fonctionnalité. Les langages trop simples peuvent être faciles à analyser, mais peuvent
être énigmatique - un peu comme
exemplele sendmail à la page 60.

Étant donné que la plupart des applications dépassent leur durée de vie prévue, vous êtes
probablement mieux de mordre la balle et d'adopter le plus complexe et
langage lisible à l'avant. L'effort initial sera remboursé plusieurs fois dans
réduction des coûts d'assistance et de maintenance.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Métaprogrammation

Défis
Défis

• • Certaines des exigences de votre projet actuel pourraient-elles être


exprimé dans un langage spécifique à un domaine ? Serait-il possible de
écrire un compilateur ou un traducteur qui pourrait générer la plupart du code
requis?
• • Si vous décidez d'adopter des mini-langages comme mode de programmation
plus près du domaine du problème, vous acceptez que certains efforts
être tenus de les mettre en œuvre. Pouvez-vous voir comment le
cadre que vous développez pour un projet peut être réutilisé dans d'autres ?

Des
Des exercices
exercices

5.
5. Nous voulons implémenter un mini-langage pour contrôler un dessin simple
package (peut-être un système de graphiques de tortues). La langue consiste en
commandes à une seule lettre. Certaines commandes sont suivies d'un seul
on bm

N 1 #p

Implémentez le code qui parse ce langage. Il doit être conçu ainsi


qu'il est simple d'ajouter de nouvelles commandes.

6.
6. Concevoir une grammaire BNF pour analyser une spécification temporelle. La totalité de la
el s

7. pIm
7. léem
bison, ou un analyseur-générateur similaire.
8.
8. faire
Implémentez l'analyseur de temps en utilisant Perl. [Astuce : Expressions régulières
de bons analyseurs.]

Estimation
Estimation

Rapide! Combien de temps faudra-t-il pour envoyer Guerre et Paix sur une ligne modem 56k ?
De combien d'espace disque aurez-vous besoin pour un million de noms et d'adresses ?
Combien de temps faut-il pour qu'un bloc de 1 000 octets passe par un routeur ? Combien
mois faudra-t-il pour livrer votre projet?

À un certain niveau, ce sont toutes des questions dénuées de sens - elles manquent toutes
information. Et pourtant, ils peuvent tous être répondus, tant que vous êtes
estimation confortable. Et, dans le processus de production d'une estimation, vous
apprenez à mieux comprendre le monde dans lequel vivent vos programmes.

En apprenant à estimer et en développant cette compétence au point où vous


avez un sens intuitif de l'ampleur des choses, vous serez en mesure de montrer
une apparente capacité magique à déterminer leur faisabilité. Quand quelqu'un
dit "nous enverrons la sauvegarde sur une ligne RNIS au site central", vous serez
capable de savoir intuitivement si cela est pratique. Lorsque vous codez,
vous pourrez savoir quels sous-systèmes doivent être optimisés et lesquels
peut être laissé seul.

Astuce
Astuce 18
18

Devis pour éviter les mauvaises surprises

En prime, à la fin de cette section, nous vous révélerons la seule bonne réponse


donner chaque fois que quelqu'un vous demande un devis.

Quelle
Quelle est
est la
la précision
précision suffisante
suffisante ??

Dans une certaine mesure, toutes les réponses sont des estimations. C'est juste que certains sont plus
précis que d'autres. Donc, la première question que vous devez vous poser quand
quelqu'un vous demande un devis est le contexte dans lequel votre réponse sera
être pris. Ont-ils besoin d'une grande précision ou recherchent-ils un stade approximatif
chiffre?

• • Si votre grand-mère vous demande quand vous arriverez, elle est probablement
se demandant s'il faut vous préparer un déjeuner ou un dîner. D'autre part,
un plongeur coincé sous l'eau et à court d'air est probablement
intéressé par une réponse à la seconde près.
• • Quelle est la valeur de p ? Si vous vous demandez combien de bordure à
acheter pour mettre autour d'un parterre de fleurs circulaire, alors "3" est probablement bon
assez. [10] Si vous êtes à l'école, alors peut-être que "22/7" est un bon
approximation. Si vous êtes à la NASA, alors peut-être que 12 décimales suffiront
faire.

[10] « 3 » est également apparemment assez bon si vous êtes un législateur. En 1897, le projet de loi No.

246 a tenté de décréter que désormais p devrait avoir la valeur "3". Le projet de loi a été déposé indéfiniment à sa
deuxième lecture lorsqu'un professeur de mathématiques a souligné que leurs pouvoirs ne s'étendaient pas tout à fait à la réussite

les lois de la nature.

L'un des aspects intéressants de l'estimation est que les unités que vous utilisez
faire une différence dans l'interprétation du résultat. Si tu dis ça
quelque chose prendra environ 130 jours ouvrables, alors les gens s'attendront à
qu'il soit assez proche. Cependant, si vous dites "Oh, environ six mois", alors
ils savent qu'il faut le chercher à tout moment entre cinq et sept mois à partir de maintenant.
Les deux chiffres représentent la même durée, mais "130 jours" probablement
implique un degré de précision plus élevé que vous ne le pensez. Nous vous recommandons
échelle des estimations de temps comme suit :

Estimation
Estimation du
du devis
devis en
en
1-15 jours jours
3-8 semaines semaines
8-30 semaines mois
30+ semaines réfléchissez bien avant de donner une estimation

Ainsi, si après avoir effectué tous les travaux nécessaires, vous décidez qu'un projet prendra
125 jours ouvrables (25 semaines), vous voudrez peut-être fournir une estimation de
"environ six mois."

Les mêmes concepts s'appliquent aux estimations de n'importe quelle quantité : choisir les unités de
votre réponse pour refléter l'exactitude que vous avez l'intention de transmettre.

D'où
D'où viennent
viennent les
les estimations
estimations ??

Toutes les estimations sont basées sur des modèles du problème. Mais avant que nous soyons trop
profondément dans les techniques de construction de modèles, nous devons mentionner une base
astuce d'estimation qui donne toujours de bonnes réponses : demandez à quelqu'un qui
déjà fait. Avant de vous engager trop dans la construction de modèles, lancez
autour de quelqu'un qui a été dans une situation similaire dans le passé.

Voyez comment leur problème a été résolu. Il est peu probable que vous trouviez jamais un exact
match, mais vous seriez surpris du nombre de fois où vous réussirez à dessiner
sur les expériences des autres.

Comprendre
Comprendre ce
ce qui
qui est
est demandé
demandé

La première partie de tout exercice d'estimation consiste à comprendre


ce qui est demandé. En plus des problèmes de précision évoqués ci-dessus, vous
besoin d'avoir une idée de l'étendue du domaine. Cela est souvent implicite dans le
question, mais vous devez prendre l'habitude de réfléchir à la portée avant
commencer à deviner. Souvent, la portée que vous choisissez fera partie de la réponse
vous donnez : "En supposant qu'il n'y a pas d'accidents de la circulation et qu'il y a de l'essence dans la voiture,
Je devrais être là dans 20 minutes."

Construire
Construire un
un modèle
modèle du
du système
système

C'est la partie amusante de l'estimation. D'après votre compréhension de la question


étant demandé, construisez un modèle mental brut et prêt à l'emploi. Si vous êtes
l'estimation des temps de réponse, votre modèle peut impliquer un serveur et une sorte
du trafic arrivant. Pour un projet, le modèle peut être les étapes que votre
l'organisation utilise au cours du développement, ainsi qu'une image très approximative de
comment le système pourrait être mis en œuvre.

La construction de modèles peut être à la fois créative et utile à long terme. Souvent, le
le processus de construction du modèle conduit à la découverte de modèles sous-jacents
et des processus qui n'étaient pas apparents à la surface. Vous voudrez peut-être même
réexaminer la question initiale : "Vous avez demandé un devis pour faire X.

Cependant, il semble que Y, une variante de X, pourrait être fait en environ la moitié du temps,
et vous perdez une seule fonctionnalité."

La construction du modèle introduit des inexactitudes dans le processus d'estimation.


C'est inévitable, et aussi bénéfique. Vous sacrifiez la simplicité du modèle
pour Precision. Doubler l'effort sur le modèle peut ne vous donner qu'un léger
augmentation de la précision. Votre expérience vous dira quand arrêter le raffinage.

Décomposer
Décomposer le
le modèle
modèle en
en composants
composants

Une fois que vous avez un modèle, vous pouvez le décomposer en composants. Tu auras besoin
découvrir les règles mathématiques qui décrivent comment ces composants
interagir. Parfois, un composant apporte une valeur unique qui est ajoutée
dans le résultat. Certains composants peuvent fournir des facteurs multiplicateurs, alors que
d'autres peuvent être plus compliqués (comme ceux qui simulent l'arrivée de
trafic à un nœud).

Vous constaterez que chaque composant aura généralement des paramètres qui affectent
comment il contribue au modèle global. A ce stade, identifiez simplement chaque
paramètre.

Donnez
Donnez une
une valeur
valeur àà chaque
chaque paramètre
paramètre

Une fois que vous avez ventilé les paramètres, vous pouvez passer en revue et attribuer
chacun une valeur. Vous vous attendez à introduire des erreurs dans cette étape. L'astuce
est de déterminer quels paramètres ont le plus d'impact sur le résultat, et
concentrez-vous sur leur bon fonctionnement. Typiquement, les paramètres dont
les valeurs ajoutées dans un résultat sont moins significatives que celles qui sont
multiplié ou divisé. Doubler la vitesse d'une ligne peut doubler la quantité de données
reçu en une heure, tandis que l'ajout d'un délai de transit de 5 ms n'aura pas
effet notable.

Vous devriez avoir un moyen justifiable de calculer ces paramètres critiques.


Pour l'exemple de mise en file d'attente, vous voudrez peut-être mesurer la valeur réelle
taux d'arrivée des transactions du système existant, ou trouver un système similaire pour
mesure. De même, vous pouvez mesurer le temps actuel nécessaire pour servir un
demande ou établir un devis en utilisant les techniques décrites dans ce
section. En fait, vous vous retrouverez souvent à fonder une estimation sur d'autres
sous-estime. C'est là que vos plus grandes erreurs se glisseront.

Calculer
Calculer les
les réponses
réponses

Ce n'est que dans les cas les plus simples qu'une estimation aura une réponse unique. Toi
pourrait être heureux de dire "Je peux marcher cinq pâtés de maisons en 15 minutes."
Cependant, à mesure que les systèmes deviennent plus complexes, vous voudrez protéger votre
réponses. Exécutez plusieurs calculs, en faisant varier les valeurs de la critique
paramètres, jusqu'à ce que vous trouviez ceux qui pilotent vraiment le modèle. UN
tableur peut être d'une grande aide. Ensuite, formulez votre réponse en fonction de ces
paramètres. "Le temps de réponse est d'environ trois quarts de seconde si le
système a un bus SCSI et 64 Mo de mémoire, et une seconde avec 48 Mo
mémoire." (Remarquez comment "trois quarts de seconde" transmet un autre
sensation de précision supérieure à 750 ms.)

Pendant la phase de calcul, vous pouvez commencer à obtenir des réponses qui semblent
étrange. Ne soyez pas trop rapide pour les rejeter. Si votre arithmétique est correcte,
votre compréhension du problème ou votre modèle est probablement erroné. C'est
informations précieuses.

Gardez
Gardez une
une trace
trace de
de vos
vos prouesses
prouesses d'estimation
d'estimation

Nous pensons que c'est une bonne idée d'enregistrer vos estimations afin que vous puissiez voir à quel point
vous étiez. Si une estimation globale impliquait le calcul de sous-estimations, gardez
trace de ceux-ci également. Vous constaterez souvent que vos estimations sont assez bonnes, en
En fait, après un certain temps, vous vous y attendrez.

Lorsqu'une estimation s'avère erronée, ne vous contentez pas de hausser les épaules et de vous en aller. Trouver
pourquoi il diffère de votre supposition. Peut-être avez-vous choisi des paramètres qui
ne correspondait pas à la réalité du problème. Peut-être que votre modèle était erroné.
Quelleprochaine
votre que soit laestimation
raison, prenez le temps de découvrir ce qui s'est passé. Si tu fais,
sera meilleure.

Estimation
Estimation des
des calendriers
calendriers de
de projet
projet

Les règles normales d'estimation peuvent s'effondrer face à la


complexités et aléas d'un développement d'application de taille. Nous trouvons
que souvent la seule façon de déterminer le calendrier d'un projet est de
acquérir de l'expérience sur ce même projet. Cela ne doit pas être un paradoxe si vous
pratiquer le développement incrémental en répétant les étapes suivantes.

• • Vérifier les exigences


• • Analyser les risques
• • Concevoir, mettre en œuvre, intégrer
• • Valider avec les utilisateurs

Au départ, vous n'avez peut-être qu'une vague idée du nombre d'itérations


requis, ou combien de temps ils peuvent être. Certaines méthodes nécessitent que vous clouiez ceci
dans le cadre du plan initial, mais pour tous les projets sauf les plus insignifiants
c'est une erreur. Sauf si vous faites une application similaire à une précédente
un, avec la même équipe et la même technologie, vous ne faites que deviner.

Ainsi, vous complétez le codage et les tests de la fonctionnalité initiale et marquez


ceci comme la fin du premier incrément. Sur la base de cette expérience, vous pouvez
affiner votre estimation initiale sur le nombre d'itérations et ce qui peut être
inclus dans chacun. Le raffinement s'améliore à chaque fois, et
la confiance dans le calendrier grandit avec lui.

Astuce
Astuce 19
19

Itérer la planification avec le code

Cela peut ne pas être populaire auprès de la direction, qui veut généralement un seul,
numéro dur et rapide avant même le début du projet. Vous devrez aider
qu'ils comprennent que l'équipe, leur productivité et l'environnement
déterminera le calendrier. En formalisant cela, et en affinant le planning
dans le cadre de chaque itération, vous leur donnerez la planification la plus précise
estimations que vous pouvez.

Que
Que dire
dire lorsqu'on
lorsqu'on lui
lui demande
demande une
une estimation
estimation

Vous dites "je vous recontacterai".

Vous obtenez presque toujours de meilleurs résultats si vous ralentissez le processus et


passez un peu de temps à parcourir les étapes que nous décrivons dans cette section.
Les estimations données à la machine à café reviendront (comme le café) à
te hante.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Vitesse de l'algorithme

Défis
Défis

• • Commencez à tenir un journal de vos estimations. Pour chacun, suivez comment


précis que vous vous êtes avéré être. Si votre erreur était supérieure à 50 %, essayez
pour savoir où votre estimation s'est mal passée.
Des
Des exercices
exercices

9.
9. On vous demande "Qui a une bande passante plus élevée : un 1Mbps
ligne de communication ou une personne marchant entre deux ordinateurs avec
une bande complète de 4 Go dans leur poche ? » Quelles contraintes imposerez-vous à votre
réponse pour vous assurer que la portée de votre réponse est correcte ? (Pour
exemple, vous pourriez dire que le temps nécessaire pour accéder à la bande est
ignoré.)

dix.
dix. Alors, qui a la bande passante la plus élevée ?

Chapitre 3. Les outils de base

Chaque artisan commence son voyage avec un ensemble de base de bonne qualité
outils. Un menuisier peut avoir besoin de règles, de gabarits, de quelques scies, de bonnes
rabots, ciseaux fins, perceuses et entretoises, maillets et pinces. Ces outils permettront
être choisi avec amour, sera construit pour durer, effectuera des travaux spécifiques avec peu
se chevauchent avec d'autres outils et, peut-être le plus important, se sentiront bien dans
les mains du menuisier en herbe.

Commence alors un processus d'apprentissage et d'adaptation. Chaque outil aura son


propre personnalité et bizarreries, et aura besoin de sa propre manipulation spéciale. Chaque
doit être aiguisé d'une manière unique, ou tenu juste ainsi. Au fil du temps, chacun va
porter selon l'usage, jusqu'à ce que la poignée ressemble à un moule de menuisier
mains et la surface de coupe s'aligne parfaitement avec l'angle auquel le
l'outil est tenu. À ce stade, les outils deviennent des conduits de l'artisan
cerveau au produit fini - ils sont devenus des extensions de son
mains. Au fil du temps, le menuisier ajoutera de nouveaux outils, comme le biscuit
cutters, scies à onglets à guidage laser, gabarits à queue d'aronde - tous de merveilleux morceaux de
technologie. Mais vous pouvez parier qu'il ou elle sera plus heureux avec l'un d'entre eux
outils originaux à la main, sentir l'avion chanter en glissant à travers le bois.

Les outils amplifient votre talent. Meilleurs sont vos outils et mieux vous savez
comment les utiliser, plus vous pouvez être productif. Commencez avec un ensemble de base de
outils généralement applicables. Au fur et à mesure que vous acquérez de l'expérience et que vous rencontrez
exigences particulières, vous ajouterez à cet ensemble de base. Comme l'artisan, attendez-vous
à ajouter régulièrement à votre boîte à outils. Soyez toujours à l'affût de meilleures façons de
faire des choses. Si vous rencontrez une situation où vous sentez que votre
les outils ne peuvent pas le couper, faites une note pour rechercher quelque chose de différent ou plus
puissant qui aurait aidé. Laissez le besoin piloter vos acquisitions.

Beaucoup de nouveaux programmeurs font l'erreur d'adopter un seul outil électrique,


tel qu'un environnement de développement intégré (IDE) particulier, et jamais
quitter son interface cosy. C'est vraiment une erreur. Nous devons être à l'aise
au-delà des limites imposées par un IDE. La seule façon de le faire est de garder le
ensemble d'outils de base pointu et prêt à l'emploi.

Dans ce chapitre, nous parlerons de l'investissement dans votre propre boîte à outils de base. Comme avec
toute bonne discussion sur les outils, nous commencerons (dans The Power of Plain Text) par
en regardant vos matières premières, les choses que vous allez façonner. De là, nous allons
passer à l'établi ou, dans notre cas, à l'ordinateur. Comment pouvez-vous utiliser votre
ordinateur pour tirer le meilleur parti des outils que vous utilisez ? Nous en discuterons dans Shell
Jeux. Maintenant que nous avons du matériel et un banc sur lequel travailler, nous allons passer au

outil que vous utiliserez probablement plus que tout autre, votre éditeur. Dans l'édition avancée,
nous vous proposerons des moyens de vous rendre plus efficace.

Pour nous assurer que nous ne perdons jamais rien de notre précieux travail, nous devons toujours
utiliser un système de contrôle du code source, même pour des choses telles que notre
carnet d'adresses! Et, puisque M. Murphy était vraiment un optimiste après tout, vous
ne peut pas être un grand programmeur jusqu'à ce que vous deveniez hautement qualifié en débogage.

Vous aurez besoin de colle pour lier une grande partie de la magie ensemble. Nous discutons de certains
possibilités, telles que awk, Perl et Python, dans la manipulation de texte.

Tout comme les menuisiers construisent parfois des gabarits pour guider la construction de
pièces complexes, les programmeurs peuvent écrire du code qui écrit lui-même du code. Nous
discutez-en dans Générateurs de code.

Passez du temps à apprendre à utiliser ces outils et, à un moment donné, vous serez
surpris de découvrir vos doigts se déplaçant sur le clavier, manipulant
texte sans pensée consciente. Les outils seront devenus des extensions de
tes mains.

La
La puissance
puissance du
du texte
texte brut
brut

En tant que programmeurs pragmatiques, notre matériau de base n'est pas le bois ou le fer, c'est
connaissance. Nous rassemblons les exigences en tant que connaissances, puis exprimons que
connaissance de nos conceptions, implémentations, tests et documents. Et nous
croient que le meilleur format pour stocker les connaissances de manière persistante est le texte brut.
Avec le texte brut, nous nous donnons la capacité de manipuler les connaissances,
à la fois manuellement et par programme, en utilisant pratiquement tous les outils de notre
disposition.

Qu'est-ce
Qu'est-ce que
que le
le texte
texte brut
brut ??

Le texte brut est composé de caractères imprimables sous une forme qui peut être lue et
compris directement par les gens. Par exemple, bien que l'extrait suivant
est composé de caractères imprimables, il n'a pas de sens.
C ah

Le lecteur n'a aucune idée de la signification de 467abe. Un meilleur


le choix serait de le rendre compréhensible pour les humains.

aDr gwin

Le texte brut ne signifie pas que le texte n'est pas structuré ; XML, SGML et
HTML sont d'excellents exemples de texte brut qui a une structure bien définie.
Vous pouvez faire tout ce que vous pourriez faire avec du texte brut avec du binaire
format, y compris la gestion des versions.

Le texte brut a tendance à être à un niveau supérieur à un codage binaire pur,


qui est généralement dérivé directement de la mise en œuvre. Supposez que vous
voulait stocker une propriété appelée
uses_menus qui peut être TRUE ou
FAUX. En utilisant du texte, vous pouvez écrire ceci comme

ym p

C o

Le problème avec la plupart des formats binaires est que le contexte nécessaire pour
comprendre que les données sont distinctes des données elles-mêmes. Vous êtes artificiellement
séparer les données de leur sens. Les données peuvent également être cryptées ; il
n'a absolument aucun sens sans la logique d'application pour l'analyser. Avec
texte brut, cependant, vous pouvez obtenir un flux de données auto-descriptif qui est
indépendamment de l'application qui l'a créé.

Astuce
Astuce 20
20

Conserver les connaissances en texte brut

Désavantages
Désavantages

Il y a deux inconvénients majeurs à utiliser du texte brut : (1) Cela peut prendre plus de temps
espace à stocker qu'un format binaire compressé, et (2) il peut être
informatiquement plus coûteux à interpréter et à traiter un fichier texte brut.

En fonction de votre application, l'une ou l'autre de ces situations ou les deux peuvent être
inacceptable - par exemple, lors du stockage de données de télémétrie par satellite, ou
format interne d'une base de données relationnelle.

Mais même dans ces situations, il peut être acceptable de stocker des métadonnées sur
les données brutes en clair (voir Métaprogrammation).

Certains développeurs peuvent craindre qu'en mettant les métadonnées en texte brut, ils ne soient
l'exposer aux utilisateurs du système. Cette peur est déplacée. Les données binaires peuvent
être plus obscur que le texte brut, mais il n'est pas plus sûr. Si vous vous inquiétez de
les utilisateurs voyant des mots de passe, chiffrez-les. Si vous ne voulez pas qu'ils changent

[1] de tous les paramètres


paramètres de configuration, inclure un hachage sécurisé
valeurs dans le fichier sous forme de somme de contrôle.
[1] MD5 est souvent utilisé à cette fin. Pour une excellente introduction au monde merveilleux de la cryptographie, voir [ Sch95 ].

Le
Le pouvoir
pouvoir du
du texte
texte

Étant donné que les fonctionnalités plus grandes et plus lentes ne sont pas les plus fréquemment demandées par
utilisateurs, pourquoi s'embêter avec du texte brut ? Quels sont les bénéfices?

• • Assurance contre l'obsolescence


• • Effet de levier
• • Tests plus faciles

Assurance
Assurance contre
contre l'obsolescence
l'obsolescence

Les formes de données lisibles par l'homme et les données auto-descriptives survivront à tous
d'autres formes de données et les applications qui les ont créées. Période.

Tant que les données survivent, vous aurez une chance de pouvoir utiliser
il - potentiellement longtemps après que l'application originale qui l'a écrit est caduque.

Vous pouvez analyser un tel fichier avec seulement une connaissance partielle de son format ; avec
la plupart des fichiers binaires, vous devez connaître tous les détails de l'ensemble du format afin
pour l'analyser avec succès.

Considérez un fichier de données d'un système[2] qui vous est donné. Tu sais
hérité
peu sur l'application d'origine ; tout ce qui est important pour vous, c'est qu'il
maintenu une liste des numéros de sécurité sociale des clients, que vous devez trouver
et extrait. Parmi les données, vous voyez

[ ]2

Reconnaissant le format d'un numéro de sécurité sociale, vous pouvez rédiger rapidement un
petit programme pour extraire ces données, même si vous n'avez aucune information sur
rien d'autre dans le fichier.

aM si

Vous n'avez peut-être pas reconnu l'importance des chiffres aussi


facilement. C'est la différence entre lisible par l'homme et humain
compréhensible.

0FIELD1
Pendant qu'on y est,

fait de l'exercice une évidence et garantit que les données survivront


tout projet qui l'a créé.

Effet
Effet de
de levier
levier
Pratiquement tous les outils de l'univers informatique, à partir du code source
systèmes de gestion aux environnements de compilateur aux éditeurs et autonomes
filtres, peuvent fonctionner sur du texte brut.

La philosophie Unix

Unix est célèbre pour être conçu autour de la philosophie du petit,


des outils pointus, chacun destiné à bien faire une chose. Cette philosophie est
activé en utilisant un format sous-jacent commun - le format orienté ligne,
fichier texte brut. Bases de données utilisées pour l'administration du système (utilisateurs et
mots de passe, configuration réseau, etc.) sont tous conservés en tant que
fichiers texte brut. (certains systèmes, tels que Solaris, maintiennent également un
formes binaires de certaines bases de données pour optimiser les performances.
La version en texte brut est conservée comme interface avec la version binaire.)

Lorsqu'un système tombe en panne, vous pouvez être confronté à un minimum


environnement pour le restaurer (vous ne pourrez peut-être pas accéder aux graphiques
pilotes, par exemple), des situations comme celle-ci peuvent vraiment vous faire
apprécier la simplicité du texte brut.

Par exemple, supposons que vous ayez un déploiement de production d'un grand
application avec un fichier de configuration complexe spécifique sendmail
au sitearrive
(
à l'esprit). Si ce fichier est en texte brut, vous pouvez le placer sous un code source
système de contrôle (voir Contrôle du code ), source
afin que vous conserviez automatiquement un
historique de tous les changements. Les outils de comparaison de fichiers tels que diff et fc vous permettent
pour voir en un coup d'œil les modifications apportées, tandis que la somme vous permet de
générer une somme de contrôle pour surveiller le fichier contre les accidents (ou malveillants)
modification.

Tests
Tests plus
plus faciles
faciles

Si vous utilisez du texte brut pour créer des données synthétiques afin de piloter des tests système, il est alors
une simple question d'ajouter, de mettre à jour ou de modifier les données de test sans avoir à
créer des outils spéciaux pour le faire. De même, la sortie en texte brut de
les tests de régression peuvent être trivialement analysés (avec diff, par exemple) ou
soumis à un examen plus approfondi avec Perl, Python ou un autre
outil de script.

Plus
Plus petit
petit dénominateur
dénominateur commun
commun

Même dans l'avenir des agents intelligents basés sur XML qui voyagent dans la nature et
Internet dangereux de manière autonome, négociant l'échange de données entre
eux-mêmes, le fichier texte omniprésent sera toujours là. En fait, dans
environnements hétérogènes, les avantages du texte brut peuvent l'emporter sur tous
des inconvénients. Vous devez vous assurer que toutes les parties peuvent communiquer
utilisant une norme commune. Le texte brut est cette norme.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Contrôle du code source


• • Générateurs de codes
• • Métaprogrammation
• • Tableaux noirs
• • Automatisation omniprésente
• • Tout est écrit

Défis
Défis

• • Concevoir une petite base de données de carnet d'adresses (nom, numéro de téléphone,
et ainsi de suite) en utilisant une représentation binaire simple dans votre
langue de choix. Faites-le avant de lire le reste de ce défi.
1. 1. Traduisez ce format en texte brut à l'aide de XML.
2. 2. Pour chaque version, ajoutez un nouveau champ de longueur variable appelé
directions dans lesquelles vous pourriez entrer des directions vers chaque personne
loger.

Quels sont les problèmes liés à la gestion des versions et à l'extensibilité ? Qui
formulaire était plus facile à modifier? Qu'en est-il de la conversion des données existantes ?

Jeux
Jeux de
de coquillages
coquillages

Chaque menuisier a besoin d'un bon établi solide et fiable, un endroit où


tenir les pièces à une hauteur convenable pendant qu'il les travaille. Le
l'établi devient le centre de l'ébénisterie, l'artisan revenant à
maintes et maintes fois au fur et à mesure qu'une pièce prend forme.

Pour un programmeur manipulant des fichiers de texte, cet atelier est le


shell de commande. À partir de l'invite du shell, vous pouvez appeler votre répertoire complet
d'outils, en utilisant des tuyaux pour les combiner d'une manière jamais imaginée par leur
développeurs originaux. Depuis le shell, vous pouvez lancer des applications, des débogueurs,
navigateurs, éditeurs et utilitaires. Vous pouvez rechercher des fichiers, interroger l'état de
le système et la sortie du filtre. Et en programmant le shell, vous pouvez construire
macro-commandes complexes pour les activités que vous effectuez souvent.

Pour les programmeurs formés aux interfaces graphiques et au développement intégré


environnements (IDE), cela peut sembler une position extrême. Après tout, impossible
vous faites tout aussi bien en pointant et en cliquant ?

La réponse simple est non." Les interfaces graphiques sont merveilleuses, et elles peuvent être
plus rapide et plus pratique pour certaines opérations simples. Déplacement de fichiers,
lire des e-mails encodés MIME et taper des lettres sont toutes des choses que vous
pourrait vouloir faire dans un environnement graphique. Mais si tu fais tout ton travail
en utilisant des interfaces graphiques, vous manquez toutes les capacités de votre
environnement. Vous ne pourrez pas automatiser les tâches courantes ni utiliser la totalité
puissance des outils mis à votre disposition. Et vous ne pourrez pas combiner vos
outils pour créer des outils de macro personnalisés. Un avantage des interfaces graphiques est
WYSIWYG—ce que vous voyez est ce que vous obtenez. L'inconvénient est
WYSIAYG—ce que vous voyez est tout ce que vous obtenez.

Les environnements GUI sont normalement limités aux capacités que leurs
concepteurs prévus. Si vous avez besoin d'aller au-delà du modèle, le concepteur
à condition que vous n'ayez généralement pas de chance - et le plus souvent, vous avez besoin
aller au-delà du modèle. Les programmeurs pragmatiques ne se contentent pas de couper du code, ou
développer des modèles d'objets, ou écrire de la documentation, ou automatiser la construction
processus - nous faisons toutes ces choses. La portée d'un outil est généralement
limité aux tâches que l'outil est censé effectuer. Par exemple,

supposons que vous ayez besoin d'intégrer un préprocesseur de code (pour implémenter
conception par contrat, ou pragmas multi-traitements, ou autres) dans votre
IDE. À moins que le concepteur de l'EDI n'ait explicitement fourni des crochets pour cela
capacité, vous ne pouvez pas le faire.

Vous êtes peut-être déjà à l'aise de travailler à partir de l'invite de commande, dans
auquel cas vous pouvez ignorer cette section en toute sécurité. Sinon, vous devrez peut-être être
convaincu que la coquille est votre amie.

En tant que programmeur pragmatique, vous voudrez constamment effectuer des tâches ad hoc
opérations—choses que l'interface graphique peut ne pas prendre en charge. La ligne de commande est
mieux adapté lorsque vous souhaitez combiner rapidement quelques commandes pour
effectuer une requête ou une autre tâche. Voici quelques exemples.

Trouvez
Trouvez tous
tous les
les fichiers
fichiers .c
.c modifiés
modifiés plus
plus récemment
récemment que
que votre
votre Makefile.
Makefile.

t
Coquille… or
GUI… .. Ouvrez l'explorateur, accédez au répertoire correct, cliquez sur le Makefile et notez le
temps de modifications. Ensuite, affichez Outils/Rechercher et entrez *.c pour la spécification du fichier.
Sélectionnez l'onglet date et entrez la date que vous avez notée pour le Makefile dans le premier champ de date.
Appuyez ensuite sur OK.

Construire
Construire une
une archive
archive zip/tar
zip/tar de
de ma
ma source.
source.

pzi
Coquille… a
t a
GUI….. Ouvrez un utilitaire ZIP (tel que le shareware WinZip [ URL 41 ], sélectionnez "Create New
Archive", entrez son nom, sélectionnez le répertoire source dans la boîte de dialogue d'ajout, définissez le filtre sur
"* .c", cliquez sur "Ajouter", définissez le filtre sur "* .h", cliquez sur "Ajouter", puis fermez l'archive.

Quels
Quels fichiers
fichiers Java
Java n'ont
n'ont pas
pas été
été modifiés
modifiés la
la semaine
semaine dernière
dernière ??

t
Coquille… or
GUI… .. Cliquez et naviguez jusqu'à "Find files", cliquez sur le champ "Named" et tapez "* .java", sélectionnez le
Onglet "Date de modification". Sélectionnez ensuite "Entre". Cliquez sur la date de début et saisissez le
date de démarrage du projet. Cliquez sur la date de fin et tapez le
date d'il y a une semaine aujourd'hui (assurez-vous d'avoir un calendrier à portée de main). Cliquez sur "Rechercher maintenant".

Parmi
Parmi ces
ces fichiers,
fichiers, lesquels
lesquels utilisent
utilisent les
les bibliothèques
bibliothèques awt
awt ??

t
Coquille… or

GUI….. Chargez chaque fichier de la liste de l'exemple précédent dans un éditeur et recherchez le

chaîne "java.awt". Notez le nom de chaque fichier contenant une correspondance.

De toute évidence, la liste pourrait s'allonger. Les commandes shell peuvent être obscures ou concises,
mais ils sont puissants et concis. Et, parce que les commandes shell peuvent être
combinés dans des fichiers de script (ou des fichiers de commande sous les systèmes Windows), vous
peut créer des séquences de commandes pour automatiser les choses que vous faites souvent.

Astuce
Astuce 21
21

Utilisez la puissance des coquilles de commande

Familiarisez-vous avec le shell et vous verrez votre productivité monter en flèche.


Besoin de créer une liste de tous les noms de packages uniques explicitement importés par
ov t

Si vous n'avez pas passé beaucoup de temps à explorer les capacités de la commande
shell sur les systèmes que vous utilisez, cela peut sembler intimidant. Cependant, investissez
un peu d'énergie pour se familiariser avec votre coquille et les choses vont bientôt commencer
tomber en place. Jouez avec votre shell de commande et vous serez
surpris de voir à quel point cela vous rend plus productif.

Utilitaires
Utilitaires Shell
Shell et
et systèmes
systèmes Windows
Windows

Bien que les shells de commande fournis avec les systèmes Windows soient
s'améliorant progressivement, les utilitaires de ligne de commande Windows sont toujours inférieurs à
leurs homologues Unix. Cependant, tout n'est pas perdu.

Cygnus Solutions propose un package appelé Cygwin [ URL 31 ]. Ainsi que


fournissant une couche de compatibilité Unix pour Windows, Cygwin est livré avec un
c o
grep et trouver. Les utilitaires et les bibliothèques peuvent être téléchargés et utilisés pour
[3] La distribution Cygwin est livrée avec
gratuit, mais assurez-vous de lire leur licence.
le shell Bash.

[3] La licence publique générale GNU [ URL 57 ] est une sorte de virus légal que les développeurs Open Source utilisent pour protéger leurs

(et vos) droits. Vous devriez passer un peu de temps à le lire. En substance, il dit que vous pouvez utiliser et modifier des logiciels sous licence GPL,

mais si vous distribuez des modifications, elles doivent être sous licence conformément à la GPL (et marquées comme telles), et vous devez

rendre la source disponible. C'est la partie virale - chaque fois que vous dérivez une œuvre d'une œuvre sous GPL, votre travail dérivé doit

également être GPL. Cependant, cela ne vous limite en aucune façon lorsque vous utilisez simplement les outils - la propriété et la licence de

les logiciels développés à l'aide des outils dépendent de vous.

Utilisation des outils Unix sous Windows

Nous aimons la disponibilité d'outils Unix de haute qualité sous Windows,


et les utiliser quotidiennement. Cependant, sachez qu'il existe une intégration
questions. Contrairement à leurs homologues Ms-dos, ces utilitaires sont
sensible à la casse des noms de fichiers,
ls a*.bat
donc ne trouvera pas
AUTOEXEC.BAT. Vous pouvez également rencontrer des problèmes avec les noms de fichiers
contenant des espaces et avec des différences dans les séparateurs de chemin. Enfin,
il y a des problèmes intéressants lors de l'exécution de programmes MS-DOS qui
attendez-vous à des arguments de style Ms-DOS sous les shells Unix, pour
exemples, les utilitaires Java de JavaSoft utilisent deux-points comme leur
séparateurs CLASSPATH sous Unix, mais utilisez un point-virgule sous
MS-DOS. En conséquence, un script Bash ou ksh qui s'exécute sur une machine Unix
fonctionnera de manière identique sous Windows, mais la ligne de commande qu'il passe
à Java sera interprété de manière incorrecte.

Alternativement, David Korn (de la renommée de Korn Shell) a mis en place un package
appelé uwin. Cela a les mêmes objectifs que la distribution Cygwin - c'est un
Environnement de développement Unix sous Windows. UWIN est livré avec un
version du shell Korn. Les versions commerciales sont disponibles auprès de Global
Technologies, Ltd. [ URL 30 ]. De plus, AT&T permet le téléchargement gratuit de
le package pour l'évaluation et l'utilisation académique. Encore une fois, lisez leur licence
avant d'utiliser.

Enfin, Tom Christiansen est (au moment de la rédaction) en train de mettre en place Perl
Power Tools , une tentative d'implémentation de tous les utilitaires Unix familiers
de manière portable, en Perl
], [ URL 32

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Automatisation omniprésente

Défis
Défis

• • Y a-t-il des choses que vous faites actuellement manuellement dans une interface graphique ?
Vous arrive-t-il de transmettre des instructions à des collègues qui impliquent un certain nombre de
étapes individuelles "cliquer sur ce bouton", "sélectionner cet élément" ? Ceux-ci pourraient-ils être
automatique?
• • Chaque fois que vous déménagez dans un nouvel environnement, assurez-vous
savoir quels coquillages sont disponibles. Voyez si vous pouvez apporter votre
shell actuel avec vous.
• • Recherchez des alternatives à votre shell actuel. Si vous rencontrez
un problème que votre shell ne peut pas résoudre, voyez si un autre shell pourrait
mieux faire face.

Édition
Édition de
de puissance
puissance

Nous avons déjà parlé des outils comme une extension de votre main. Bon ça
s'applique aux éditeurs plus qu'à tout autre outil logiciel. Vous devez pouvoir
manipuler le texte aussi facilement que possible, car le texte est le brut de base
matériel de programmation. Examinons quelques caractéristiques communes et
fonctions qui vous aident à tirer le meilleur parti de votre environnement d'édition.

Un
Un éditeur
éditeur

Nous pensons qu'il est préférable de bien connaître un éditeur et de l'utiliser pour toutes les éditions
tâches : code, documentation, mémos, administration système, etc.
Sans un seul éditeur, vous faites face à une Babel de confusion des temps modernes.
Vous devrez peut-être utiliser l'éditeur intégré dans l'IDE de chaque langue pour le codage,
et un produit bureautique tout-en-un pour la documentation, et peut-être un autre
éditeur intégré pour l'envoi d'e-mails. Même les frappes que vous utilisez pour éditer
les lignes de commande dans le shell peuvent [4] êtreIl différentes.
est difficile d'être compétent
dans l'un de ces environnements si vous avez un ensemble différent de montage
conventions et commandes dans chacun.

[4] Idéalement, le shell que vous utilisez devrait avoir des raccourcis clavier qui correspondent à ceux utilisés par votre éditeur. Bash, par exemple,

prend en charge
raccourcis
les deux clavier vi et emacs.

Vous devez être compétent. En tapant simplement de manière linéaire et en utilisant une souris pour couper
et la pâte ne suffit pas. Vous ne pouvez pas être aussi efficace que vous le pouvez

avec un puissant éditeur sous vos doigts. Dactylographieou


dix fois pour déplacer le curseur vers la gauche au début d'une ligne n'est pas aussi efficace

en tapant une seule touche comme ou .

Astuce
Astuce 22
22

Bien utiliser un seul éditeur

Choisissez un éditeur, connaissez-le parfaitement et utilisez-le pour toutes les tâches d'édition. Si tu
utiliser un seul éditeur (ou ensemble de raccourcis clavier) pour toutes les activités d'édition de texte,
vous n'avez pas besoin de vous arrêter et de réfléchir pour accomplir une manipulation de texte :
les frappes nécessaires seront un réflexe. L'éditeur sera une extension de votre
main; les touches chanteront en se frayant un chemin à travers le texte et la pensée.
C'est notre objectif.

Assurez-vous que l'éditeur que vous choisissez est disponible sur toutes les plateformes que vous utilisez.
Emacs, vi, CRiSP, Brief et autres sont disponibles sur plusieurs plateformes,
souvent dans les versions GUI et non GUI (écran texte).

Fonctionnalités
Fonctionnalités de
de l'éditeur
l'éditeur

Au-delà des fonctionnalités que vous trouvez particulièrement utiles et confortables,


voici quelques capacités de base que nous pensons que tout éditeur décent devrait avoir.
Si votre éditeur n'est pas à la hauteur dans l'un de ces domaines, c'est peut-être le moment de
envisagez de passer à un niveau plus avancé.

• • Configurable. Tous les aspects de l'éditeur doivent être configurables


selon vos préférences, y compris les polices, les couleurs, la taille des fenêtres et
liaisons de frappe (quelles touches exécutent quelles commandes). En utilisant
seules les frappes pour les opérations d'édition courantes sont plus efficaces que
commandes de la souris ou du menu, car vos mains ne quittent jamais
le clavier.
• • Extensible. Un éditeur ne devrait pas être obsolète juste parce qu'un nouveau
langage de programmation sort. Il doit pouvoir s'intégrer à
quel que soit l'environnement de compilation que vous utilisez. Tu devrais être capable de
"enseignez-lui" les nuances de toute nouvelle langue ou format de texte (XML,
HTML version 9, etc.).
• • Programmable. Vous devriez pouvoir programmer l'éditeur pour
effectuer des tâches complexes en plusieurs étapes. Cela peut être fait avec des macros ou
avec un langage de programmation de script intégré (Emacs utilise un
variante de Lisp, par exemple).

En outre, de nombreux éditeurs prennent en charge des fonctionnalités spécifiques à un


langage de programmation, tel que :

• • Mise en évidence de la syntaxe


• • Auto-complétion
• • Auto-indentation
• • Code initial ou document passe-partout
• • Liaison pour aider les systèmes
• • Fonctionnalités de type IDE (compilation, débogage, etc.)

Une fonctionnalité telle que la coloration syntaxique peut sembler un extra frivole, mais
en réalité, cela peut être très utile et améliorer votre productivité. Une fois que vous obtenez
habitué à voir des mots-clés apparaître dans une couleur ou une police différente, une erreur de frappe
un mot-clé qui n'apparaît pas de cette façon vous saute aux yeux bien avant que vous ne tiriez
le compilateur.

Avoir la possibilité de compiler et de naviguer directement vers les erreurs dans le


L'environnement de l'éditeur est très pratique pour les gros projets. Emacs en particulier est
adepte de ce style d'interaction.

Productivité
Productivité

Un nombre surprenant de personnes que nous avons rencontrées utilisent l'utilitaire de bloc-notes de Windows pour
modifier leur code source. C'est comme utiliser une cuillère à café comme une pelle - simplement
taper et utiliser le copier-coller de base à la souris ne suffit pas.

Quel genre de choses aurez-vous besoin de faire qui ne peut pas être fait de cette façon ?

Eh bien, il y a le mouvement du curseur, pour commencer. Des frappes simples qui bougent
vous en unités de mots, lignes, blocs ou fonctions sont bien plus efficaces que
taper à plusieurs reprises une frappe qui vous déplace caractère par caractère ou ligne
par ligne.

O u
déclarations par ordre alphabétique, et quelqu'un d'autre a enregistré quelques
fichiers qui ne respectent pas cette norme (cela peut sembler extrême, mais sur un
grand projet, cela peut vous faire gagner beaucoup de temps à parcourir une longue liste de
déclarations d'importation). Vous souhaitez parcourir rapidement quelques fichiers et trier un
petite partie d'entre eux. Dans des éditeurs tels que vi et Emacs, vous pouvez le faire facilement
(voir Figure 3.1 )

Illustration
Illustration 3.1.
3.1. Trier
Trier les
les lignes
lignes dans
dans un
un éditeur
éditeur

Certains éditeurs peuvent aider à rationaliser les opérations courantes. Par exemple, lorsque
vous créez un nouveau fichier dans une langue particulière, l'éditeur peut fournir une
modèle pour vous. Cela pourrait inclure :
• • Nom de la classe ou du module renseigné (dérivé du nom du fichier)
• • Votre nom et/ou déclarations de droits d'auteur

• • Squelettes pour les constructions dans ce langage (constructeur et


déclarations de destructeur, par exemple)

Une autre fonctionnalité utile est l'indentation automatique. Plutôt que d'avoir à indenter
manuellement (en utilisant l'espace ou la tabulation), l'éditeur indente automatiquement pour vous
au moment opportun (après avoir tapé une accolade ouvrante, par exemple). Le gentil
partie de cette fonctionnalité est que vous pouvez utiliser l'éditeur pour fournir une cohérence
style d'indentation pour votre projet.[5]

[5] Le noyau Linux est développé de cette façon. Ici, vous avez des développeurs dispersés géographiquement, dont beaucoup travaillent sur le

mêmes morceaux de code. Il existe une liste publiée de paramètres (dans ce cas, pour Emacs) qui décrit l'indentation requise

style.


Où aller
aller en
en partant
partant d'ici
d'ici

Ce type de conseil est particulièrement difficile à rédiger car pratiquement tous


lecteur est à un niveau différent de confort et d'expertise avec le ou les éditeurs qu'il
utilisent actuellement. Donc, pour résumer et donner quelques indications sur
où aller ensuite, retrouvez-vous dans la colonne de gauche du graphique et regardez
dans la colonne de droite pour voir ce que nous pensons que vous devriez faire.

Si
Si cela
cela vous
vous ressemble…
ressemble… Alors
Alors pensez
pensez à…
à…
J'utilise uniquement les fonctionnalités
Choisissezdeunbase
éditeur
de puissant et apprenez-le bien.
de nombreux éditeurs différents.
J'ai un éditeur préféré, mais je Apprenez-les. Réduisez le nombre de frappes dont vous avez besoin pour
n'utilisez pas toutes ses fonctionnalités.
taper.
J'ai un éditeur préféré et Essayez de l'étendre et de l'utiliser pour plus de tâches que vous ne le faites déjà.
utilisez-le dans la mesure du possible.
Je pense que tu es fou. Bloc-notes
Tant que vous êtes heureux et productif, allez-y ! Mais si vous trouvez
est le meilleur éditeur jamais créé.
sujet à "l'envie des éditeurs", vous devrez peut-être réévaluer
ta position.

Quels
Quels éditeurs
éditeurs sont
sont disponibles
disponibles ??

Après vous avoir recommandé de maîtriser un éditeur décent, lequel devons-nous


recommander? Eh bien, nous allons esquiver cette question ; votre choix d'éditeur est
personnel (certains diraient même religieux !). Cependant, dans
Annexe A , nous listons un certain nombre d'éditeurs populaires et où les trouver.

Défis
Défis

• • Certains éditeurs utilisent des langages complets pour la personnalisation et


scénarisation. Emacs, par exemple, utilise Lisp. Comme l'un des nouveaux
langues que vous allez apprendre cette année, apprenez la langue que vous
l'éditeur utilise. Pour tout ce que vous vous retrouvez à faire de manière répétée, développez
un ensemble de macros (ou équivalent) pour le gérer.
• • Savez-vous tout ce que votre éditeur est capable de faire ? Essayez de
surprenez vos collègues qui utilisent le même éditeur. Essayez d'accomplir
n'importe quelle tâche d'édition donnée en aussi peu de frappes que possible.
Contrôle
Contrôle du
du code
code source
source

Le progrès, loin de consister en un changement, dépend de la rémanence. Ceux


qui ne peut pas se souvenir du passé est condamné à le répéter.

George
George Santayana,
Santayana, Vie
Vie de
de raison
raison

L'une des choses importantes que nous recherchons dans une interface utilisateur est la
clé—un seul bouton qui nous pardonne nos erreurs. C'est encore mieux si le
l'environnement prend en charge plusieurs niveaux d'annulation et de rétablissement, vous pouvez donc revenir en arrière
et récupérer de quelque chose qui s'est passé il y a quelques minutes. Mais
et si l'erreur s'était produite la semaine dernière et que vous aviez allumé votre ordinateur
allumé et éteint dix fois depuis ? Eh bien, c'est l'un des nombreux avantages de

utiliser un système de contrôle de code source : c'est un clé


géant
- un projet à l'échelle
machine à voyager dans le temps qui peut vous ramener à ces beaux jours de la semaine dernière, quand
le code réellement compilé et exécuté.

Systèmes de contrôle de code source ou configuration plus large


systèmes de gestion, gardez une trace de chaque changement que vous apportez à votre source
codes et documents. Les meilleurs peuvent garder une trace du compilateur et du système d'exploitation
versions également. Avec un système de contrôle de code source correctement configuré, vous
pouvez toujours revenir à une version précédente de votre logiciel.

Mais un système de contrôle de code source [6] )(SCCS


fait bien plus que défaire
erreurs. Un bon SCCS vous permettra de suivre les changements, de répondre aux questions
comme : Qui a apporté des modifications à cette ligne de code ? Quelle est la différence
entre la version actuelle et celle de la semaine dernière ? Combien de lignes de code ont fait
nous changeons dans cette version? Quels fichiers sont modifiés le plus souvent ? Ce genre de
les informations sont inestimables pour le suivi des bogues, l'audit, les performances et la qualité
fins.

[6] Nous utilisons le SCCS en majuscules pour désigner les systèmes de contrôle de code source génériques. Il existe également un système spécifique appelé "sccs",

initialement publié avec AT&T System V Unix.

Un SCCS vous permettra également d'identifier les versions de votre logiciel. Une fois identifié,
vous pourrez toujours revenir en arrière et régénérer la version, indépendamment
des changements qui ont pu se produire plus tard.

Nous utilisons souvent un SCCS pour gérer les branches dans l'arbre de développement. Pour
exemple, une fois que vous avez publié un logiciel, vous voudrez normalement
continuer à développer pour la prochaine version. En même temps, vous devrez
traiter les bogues dans la version actuelle, en envoyant des versions corrigées aux clients.
Vous voudrez que ces corrections de bogues soient intégrées à la prochaine version (le cas échéant), mais
vous ne voulez pas expédier le code en cours de développement aux clients. Avec un SCCS
vous pouvez générer des branches dans l'arborescence de développement chaque fois que vous générez
Une libération. Vous appliquez des corrections de bogues au code dans la branche et continuez
se développant sur le tronc principal. Étant donné que les corrections de bogues peuvent être pertinentes pour le
tronc principal également, certains systèmes vous permettent de fusionner les modifications sélectionnées à partir de
automatiquement la branche dans le tronc principal.

Les systèmes de contrôle du code source peuvent conserver les fichiers qu'ils gèrent dans un
référentiel—un excellent candidat pour l'archivage.

Enfin, certains produits peuvent permettre à deux utilisateurs ou plus de travailler


simultanément sur le même ensemble de fichiers, même en apportant des modifications simultanées dans
le même dossier. Le système gère alors la fusion de ces modifications lors
les fichiers sont renvoyés au référentiel. Bien qu'apparemment risqué, un tel
fonctionnent bien dans la pratique sur des projets de toutes tailles.

Astuce
Astuce 23
23

Toujours utiliser le contrôle du code source


Toujours. Même si vous êtes une équipe d'une seule personne sur un projet d'une semaine. Même si
c'est un prototype "jetable". Même si les choses sur lesquelles vous travaillez ne sont pas
code source. Assurez-vous que tout est sous le code source
contrôle—documentation, listes de numéros de téléphone, mémos aux fournisseurs, makefiles,
les procédures de construction et de publication, ce petit script shell qui grave le CD
maître—tout. Nous utilisons régulièrement le contrôle du code source sur à peu près
tout ce que nous tapons (y compris le texte de ce livre). Même si nous ne sommes pas
travaillant sur un projet, notre travail au quotidien est sécurisé dans un référentiel.

Contrôle
Contrôle du
du code
code source
source et
et constructions
constructions

Il y a un énorme avantage caché à avoir un projet entier sous la


parapluie d'un système de contrôle de code source : vous pouvez avoir des versions de produit qui
sont automatiques et répétables.

Le mécanisme de génération de projet peut extraire la dernière source du référentiel


automatiquement. Il peut fonctionner au milieu de la nuit après que tout le monde
(espérons-le) rentrés chez eux. Vous pouvez exécuter des tests de régression automatiques pour vous assurer
que le codage du jour n'a rien cassé. L'automatisation du build
assure la cohérence - il n'y a pas de procédures manuelles et vous n'aurez pas besoin
les développeurs se souviennent de copier le code dans une zone de construction spéciale.

La construction est reproductible car vous pouvez toujours reconstruire la source telle qu'elle
existé à une date donnée.

Mais
Mais mon
mon équipe
équipe n'utilise
n'utilise pas
pas le
le contrôle
contrôle du
du code
code source
source

Honte à eux! Cela ressemble à une occasion de faire un peu d'évangélisation!


Cependant, en attendant qu'ils voient la lumière, vous devriez peut-être
implémentez votre propre contrôle de source privé. Utilisez l'un des
outils que nous énumérons à l'annexe A , et mettez un point d'honneur à conserver votre travail personnel
en toute sécurité dans un référentiel (ainsi que de faire tout ce que votre projet
a besoin). Bien que cela puisse sembler être une duplication des efforts, nous pouvons assez
beaucoup de garanties que cela vous évitera des soucis (et économisera de l'argent pour votre projet)
première fois que vous devez répondre à des questions telles que "Qu'avez-vous fait au xyz
module?" et "Qu'est-ce qui a cassé la construction?" Cette approche peut également aider
convaincre votre direction que le contrôle du code source fonctionne vraiment.

N'oubliez pas qu'un SCCS s'applique également aux choses que vous faites à l'extérieur
de travail.

Produits
Produits de
de contrôle
contrôle du
du code
code source
source

L'annexe A , donne les URL des systèmes de contrôle de code source représentatifs,
certains commerciaux et d'autres disponibles gratuitement. Et bien d'autres produits sont
disponible : recherchez des pointeurs vers la FAQ sur la gestion de la configuration.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Orthogonalité
• • La puissance du texte brut
• • Tout est écrit
Défis
Défis

• • Même si vous ne pouvez pas utiliser un SCCS au travail, installez RCS ou


CVS sur un système personnel. Utilisez-le pour gérer vos projets favoris,
documents que vous écrivez, et (éventuellement) les modifications de configuration appliquées à
le système informatique lui-même.
• • Découvrez quelques-uns des projets Open Source pour lesquels
des archives accessibles au public sont disponibles sur le Web (telles que
Mozilla [ URL 51 ], KDE [ URL 54 ] et Gimp [ URL 55 ]). Comment faire
vous obtenez des mises à jour de la source? Comment apportez-vous des modifications ?
projet réglemente l'accès ou arbitre la prise en compte des modifications ?

Débogage
Débogage

C'est une chose douloureuse

Pour regarder votre propre problème et savoir

Que toi-même et personne d'autre ne l'a fait

Sophocle,
Sophocle, Ajax
Ajax

Le mot bug a été utilisé pour décrire un "objet de terreur" depuis le


XIVe siècle. Contre-amiral Dr Grace Hopper, l'inventeur de
COBOL, est crédité d'avoir observé le premier bogue informatique - littéralement, un
papillon de nuit pris dans un relais dans un système informatique ancien. Lorsqu'on lui a demandé d'expliquer
pourquoi la machine ne se comportait pas comme prévu, un technicien a signalé que
il y avait "un bogue dans le système", et consciencieusement l'a enregistré - ailes et tout - dans
le journal de bord.

Malheureusement, nous avons encore des "bogues" dans le système, mais pas du genre volant.
Mais le sens du XIVe siècle - un croque-mitaine - est peut-être encore plus
applicable aujourd'hui qu'elle ne l'était alors. Les défauts logiciels se manifestent dans un
diverses manières, des exigences mal comprises aux erreurs de codage.
Malheureusement, les systèmes informatiques modernes sont encore limités à faire ce
vous leur dites de faire, pas nécessairement ce que vous voulez qu'ils fassent.

Personne n'écrit un logiciel parfait, il est donc évident que le débogage prendra beaucoup de temps
majeure partie de votre journée. Examinons quelques-uns des problèmes liés à
débogage et quelques stratégies générales pour trouver des bogues insaisissables.

Psychologie
Psychologie du
du débogage
débogage

Le débogage lui-même est un sujet sensible et émotionnel pour de nombreux développeurs.


Au lieu de l'attaquer comme une énigme à résoudre, vous pouvez rencontrer le déni,
pointer du doigt, des excuses boiteuses ou tout simplement de l'apathie.

Acceptez le fait que le débogage n'est que la résolution de problèmes et attaquez-le comme
tel.

Après avoir trouvé le bogue de quelqu'un d'autre, vous pouvez passer du temps et de l'énergie à poser
blâmez le sale coupable qui l'a créé. Dans certains lieux de travail, cela fait partie de
la culture, et peut être cathartique. Cependant, dans le domaine technique, vous
veulent se concentrer sur la résolution du problème, pas sur le blâme.

Astuce
Astuce 24
24
Résoudre le problème, pas le blâme

Peu importe que le bug soit de votre faute ou de quelqu'un d'autre. C'est
toujours ton problème.

Un
Un état
état d'esprit
d'esprit de
de débogage
débogage

La personne la plus facile à tromper c'est soi-même

Edward
Edward Bulwer-Lytton,
Bulwer-Lytton, Le
Le renié
renié

Avant de commencer le débogage, il est important d'adopter le bon état d'esprit. Toi
besoin de désactiver de nombreuses défenses que vous utilisez chaque jour pour protéger votre ego,
éliminez toutes les pressions du projet auxquelles vous pourriez être soumis et obtenez-vous
confortable. Avant tout, rappelez-vous la première règle de débogage :

Astuce
Astuce 25
25

Ne pas paniquer

Il est facile de paniquer, surtout si vous êtes confronté à une échéance ou si vous avez un
un patron ou un client nerveux qui respire dans votre cou pendant que vous essayez de
trouver la cause du bug. Mais il est très important de prendre du recul, et

pensez réellement à ce qui pourrait causer les symptômes que vous croyez
indiquer un bogue.

Si votre première réaction en voyant un bogue ou en voyant un rapport de bogue est "c'est
impossible », vous avez tout à fait tort. Ne gaspillez pas un seul neurone dans le train
de pensée qui commence par "mais ça ne peut pas arriver" parce qu'il est clair que c'est possible,
et a.

Attention à la myopie lors du débogage. Résistez à l'envie de corriger uniquement les symptômes
vous voyez : il est plus probable que le problème réel soit plusieurs étapes supprimées
de ce que vous observez, et peut impliquer un certain nombre d'autres
choses. Essayez toujours de découvrir la cause profonde d'un problème, pas seulement cette
aspect particulier de celui-ci.


Où commencer
commencer

Avant de commencer à regarder le bogue, assurez-vous que vous travaillez sur le code
qui a été compilé proprement, sans avertissements. Nous définissons régulièrement le compilateur
niveaux d'avertissement aussi élevés que possible. Cela n'a pas de sens de perdre du temps
essayer de trouver un problème que le compilateur pourrait trouver pour vous ! Nous devons le faire
se concentrer sur les problèmes les plus difficiles à résoudre.

Lorsque vous essayez de résoudre un problème, vous devez rassembler toutes les données pertinentes.
Malheureusement, le rapport de bug n'est pas une science exacte. Il est facile d'être induit en erreur par
coïncidences, et vous ne pouvez pas vous permettre de perdre du temps à déboguer les coïncidences.
Vous devez d'abord être précis dans vos observations.

La précision des rapports de bogues est encore réduite lorsqu'ils passent par un
tierce partie - vous devrez peut-être surveiller l'utilisateur qui a signalé le bogue
en action pour obtenir un niveau de détail suffisant.

Andy a déjà travaillé sur une grande application graphique. À l'approche de la libération, le
les testeurs ont signalé que l'application plantait à chaque fois qu'ils peignaient un
caresser avec un pinceau particulier. Le programmeur responsable a fait valoir que
Il n'y avait rien de mal à cela; il avait essayé de peindre avec, et il
a très bien fonctionné. Ce dialogue a fait des allers-retours pendant plusieurs jours, avec
les tempéraments montent rapidement.
Finalement, nous les avons réunis dans la même pièce. Le testeur a choisi le
outil pinceau et peint un trait du coin supérieur droit au coin inférieur gauche
coin. L'application a explosé. "Oh," dit le programmeur, dans un petit
voix, qui a ensuite admis timidement qu'il n'avait fait que des coups d'essai
du coin inférieur gauche au coin supérieur droit, ce qui n'a pas révélé le bogue.

Il y a deux points dans cette histoire :

• • Vous devrez peut-être interroger l'utilisateur qui a signalé le bogue dans


afin de recueillir plus de données que celles initialement fournies.
• • Tests artificiels (tels que le coup de pinceau unique du programmeur
de bas en haut) n'exercez pas suffisamment d'application. Vous devez
tester brutalement à la fois les conditions aux limites et l'utilisation réaliste de l'utilisateur final
motifs. Vous devez le faire systématiquement (voir Ruthless Testing ).

Stratégies
Stratégies de
de débogage
débogage

Une fois que vous pensez savoir ce qui se passe, il est temps de découvrir ce que
programme pense se passe.

Reproduction d'insectes

Non, nos bugs ne se multiplient pas vraiment (bien que certains d'entre eux soient
probablement assez vieux pour le faire légalement). Nous parlons d'un autre
genre de reproduction.

La meilleure façon de commencer à corriger un bogue est de le rendre reproductible. Après


tout, si vous ne pouvez pas le reproduire, comment saurez-vous s'il est jamais réparé ?

Mais nous voulons plus qu'un bogue qui peut être reproduit en suivant
une longue série d'étapes; nous voulons un bogue qui peut être reproduit
avec une seule commande. Il est beaucoup plus difficile de corriger un bogue si vous devez y aller
à travers 15 étapes pour arriver au point où le bogue apparaît.
Parfois en vous forçant à isoler les circonstances qui
affichez le bogue, vous aurez même un aperçu de la façon de le corriger.

Voir Ubiquitos Automation , pour d'autres idées dans ce sens.

Visualisez
Visualisez vos
vos données
données

Souvent, le moyen le plus simple de discerner ce que fait un programme ou ce qu'il est
va faire - est d'avoir un bon aperçu des données sur lesquelles il fonctionne. Le plus simple
exemple de ceci est une approche simple "nom de variable = valeur de données",
qui peut être implémenté sous forme de texte imprimé ou sous forme de champs dans une boîte de dialogue GUI
ou liste.

Mais vous pouvez obtenir un aperçu beaucoup plus approfondi de vos données en utilisant un débogueur
qui vous permet de visualiser vos données et toutes les interrelations qui

exister. Il existe des débogueurs qui peuvent représenter vos données sous forme de survol 3D
à travers un paysage de réalité virtuelle, ou sous forme de tracé de forme d'onde 3D, ou tout simplement
schémas structurels simples, comme le montre la figure 3.2 à la page suivante. Comme
vous suivez votre programme en une seule étape, des images comme celles-ci peuvent valoir la peine
bien plus que mille mots, car le bogue que vous avez chassé
vous saute soudainement aux yeux.

Illustration
Illustration 3.2.
3.2. Exemple
Exemple de
de diagramme
diagramme de
de débogueur
débogueur d'une
d'une liste
liste chaînée
chaînée circulaire.
circulaire. Le
Le

les
les flèches
flèches représentent
représentent des
des pointeurs
pointeurs vers
vers des
des nœuds.
nœuds.

Même si votre débogueur a une prise en charge limitée de la visualisation des données, vous pouvez toujours
faites-le vous-même, soit à la main, avec du papier et un crayon, soit avec un
programmes de traçage.

Le débogueur DDD a des capacités de visualisation et est librement


disponible (voir [ URL 19]). Il est intéressant de noter que DDD fonctionne avec
plusieurs langages, dont Ada, C, C++, Fortran, Java, Modula, Pascal,
Perl et Python (clairement une conception orthogonale).

Tracé
Tracé

Les débogueurs se concentrent généralement sur l'état du programme maintenant. Parfois tu


besoin de plus - vous devez surveiller l'état d'un programme ou d'une structure de données
au fil du temps. Voir une trace de pile ne peut que vous dire comment vous êtes arrivé ici directement.
Il ne peut pas vous dire ce que vous faisiez avant cette chaîne d'appels, en particulier dans
systèmes basés sur les événements.

Les instructions de suivi sont ces petits messages de diagnostic que vous imprimez sur le
écran ou à un fichier qui dit des choses telles que "arrivé ici" et "valeur de x = 2". C'est
une technique primitive par rapport aux débogueurs de style IDE, mais il est
particulièrement efficace pour diagnostiquer plusieurs classes d'erreurs que les débogueurs
ne peut pas. Le traçage est inestimable dans tout système où le temps lui-même est un facteur :
processus simultanés, systèmes en temps réel et applications basées sur des événements.

Vous pouvez utiliser des instructions de traçage pour "explorer" le code. C'est toi
peut ajouter des instructions de traçage au fur et à mesure que vous descendez dans l'arborescence des appels.

Les messages de suivi doivent être dans un format régulier et cohérent ; vous voudrez peut-être
les analyser automatiquement. Par exemple, si vous deviez retrouver un
fuite de ressources (telle que des ouvertures/fermetures de fichiers déséquilibrées), vous pouvez suivre chaque
ouvrir et fermer chacun dans un fichier journal. En traitant le fichier journal avec Perl, vous
pourrait facilement identifier où se produisait l'ouverture incriminée.

Variables corrompues ? Vérifiez leur voisinage


Parfois, vous examinerez une variable en vous attendant à voir une petite
valeur entière, et à la place obtenir quelque chose
0x6e69614d.
comme Avant
vous retroussez vos manches pour un débogage sérieux, jetez un coup d'œil rapide
regardez la mémoire autour de cette variable corrompue. Souvent ça va
vous donner un indice. Dans notre cas, l'examen de la mémoire environnante comme
c a
On dirait
nous que où
savons quelqu'un a pulvérisé une adresse sur notre comptoir. Maintenant
chercher.

Esquive
Esquive en
en caoutchouc
caoutchouc

Une technique très simple mais particulièrement utile pour trouver la cause d'un
problème est simplement de l'expliquer à quelqu'un d'autre. L'autre personne doit
regardez l'écran par-dessus votre épaule et hochez constamment la tête
(comme un canard en caoutchouc qui monte et descend dans une baignoire). Ils n'ont pas besoin de
dis un mot; le simple fait d'expliquer, étape par étape, ce qu'est le code
censé faire fait souvent sauter le problème hors de l'écran et annoncer
lui-même.
[7]

[7] Pourquoi "l'esquive en caoutchouc" ? Pendant ses études de premier cycle à l'Imperial College de Londres, Dave a beaucoup travaillé avec un chercheur

assistant nommé Greg Pugh, l'un des meilleurs développeurs que Dave ait connus. Pendant plusieurs mois, Greg a transporté un petit

canard en caoutchouc jaune, qu'il plaçait sur son terminal pendant le codage. Il a fallu un certain temps avant que Dave ait le courage de demander...

Cela semble simple, mais en expliquant le problème à une autre personne, vous devez
énoncez explicitement des choses que vous pouvez tenir pour acquises lorsque vous traversez

le code vous-même. En ayant à verbaliser certaines de ces hypothèses, vous


peut soudainement avoir un nouvel aperçu du problème.

Processus
Processus d'élimination
d'élimination

Dans la plupart des projets, le code que vous déboguez peut être un mélange de
code d'application écrit par vous et d'autres membres de votre équipe de projet,
produits tiers (base de données, connectivité, librairies graphiques,
communications spécialisées ou algorithmes, etc.) et la plateforme
environnement (système d'exploitation, bibliothèques système et compilateurs).

Il est possible qu'un bogue existe dans le système d'exploitation, le compilateur ou un tiers
produit, mais cela ne devrait pas être votre première pensée. Il est beaucoup plus probable
que le bogue existe dans le code de l'application en cours de développement. C'est
généralement plus rentable de supposer que le code de l'application est incorrect
appeler dans une bibliothèque que de supposer que la bibliothèque elle-même est cassée. Même
si le problème vient d'un tiers, vous devrez quand même éliminer votre
code avant de soumettre le rapport de bogue.

Nous avons travaillé sur un projet où un ingénieur senior était convaincu que le
L'appel système select a été interrompu sur Solaris. Aucune quantité de persuasion ou de logique
pourrait changer d'avis (le fait que toutes les autres applications de mise en réseau sur
la boîte fonctionnait bien n'était pas pertinente). Il a passé des semaines à écrire des solutions de contournement,
qui, pour une raison étrange, ne semble pas résoudre le problème. Quand enfin
forcé de s'asseoir et de lire la documentation sur sélectionner, il a découvert le
problème et l'a corrigé en quelques minutes. Nous utilisons maintenant l'expression
"select est cassé" comme un doux rappel chaque fois que l'un de nous commence à blâmer
le système pour une faute susceptible d'être la nôtre.

Astuce
Astuce 26
26

"select" n'est pas cassé

N'oubliez pas que si vous voyez des empreintes de sabots, pensez à des chevaux et non à des zèbres. Le système d'exploitation est
probablement pas cassé. Et la base de données est probablement très bien.

Si vous "n'avez changé qu'une seule chose" et que le système a cessé de fonctionner, celui-là
chose était susceptible d'être responsable, directement ou indirectement, peu importe comment
tiré par les cheveux semble-t-il. Parfois, la chose qui a changé est en dehors de votre
contrôle : nouvelles versions du système d'exploitation, du compilateur, de la base de données ou d'autres tiers
le logiciel peut faire des ravages avec un code précédemment correct. De nouveaux bogues pourraient
arriver. Les bogues pour lesquels vous aviez une solution de contournement sont corrigés, brisant le
solution de contournement. Les API changent, les fonctionnalités changent ; bref c'est une toute nouvelle
jeu de balle, et vous devez retester le système dans ces nouvelles conditions. Donc
gardez un œil attentif sur le calendrier lorsque vous envisagez une mise à niveau ; vous pouvez
voulez attendre après la prochaine version.

Si, toutefois, vous n'avez pas d'endroit évident pour commencer à chercher, vous pouvez toujours compter sur
sur une bonne recherche binaire à l'ancienne. Voir si les symptômes sont présents à
l'un des deux endroits éloignés dans le code. Regardez ensuite au milieu. Si la
problème est présent, alors le bogue se situe entre le début et le milieu
indiquer; sinon, c'est entre le milieu et la fin. Tu peux
continuez de cette façon jusqu'à ce que vous réduisiez suffisamment l'endroit pour
Identifiez le problème.

L'élément
L'élément de
de surprise
surprise

Lorsque vous vous retrouvez surpris par un insecte (peut-être même en marmonnant "c'est
impossible" dans votre souffle où nous ne pouvons pas vous entendre), vous devez
réévaluer les vérités qui vous sont chères. Dans cette routine de liste chaînée, celle que vous
savait qu'il était à l'épreuve des balles et ne pouvait pas être la cause de ce bogue - est-ce que
tu testes toutes les conditions aux limites? Cet autre morceau de code que vous avez été
utilisé pendant des années - il ne pouvait pas encore y avoir de bogue. Pourrait-il?

Bien sûr que c'est possible. La quantité de surprise que vous ressentez quand quelque chose se passe
le mal est directement proportionnel au degré de confiance et de foi que vous avez en
le code en cours d'exécution. C'est pourquoi, face à un échec « surprenant », vous
devez réaliser qu'une ou plusieurs de vos hypothèses sont fausses. Ne brille pas
sur une routine ou un morceau de code impliqué dans le bogue parce que vous le "connaissez"
travaux. Prouve le. Prouvez-le dans ce contexte, avec ces données, avec ces limites
conditions.

Astuce
Astuce 27
27

Ne le supposez pas, prouvez-le

Lorsque vous rencontrez un bogue surprise, au-delà du simple fait de le corriger, vous devez
déterminer pourquoi cet échec n'a pas été détecté plus tôt. Demandez-vous si vous
besoin de modifier l'unité ou d'autres tests pour qu'ils l'aient attrapé.

De plus, si le bogue est le résultat de mauvaises données propagées via un


quelques niveaux avant de provoquer l'explosion, voir si meilleur paramètre
l'enregistrement de ces routines l'aurait isolé plus tôt (voir le

discussions sur le plantage précoce et affirmations aux pages 120 et 122,


respectivement).

Pendant que vous y êtes, y a-t-il d'autres endroits dans le code qui pourraient être
sensible à ce même bug? Il est maintenant temps de les trouver et de les réparer. Faire
sûr que quoi qu'il soit arrivé, vous saurez si cela se reproduit.

S'il a fallu beaucoup de temps pour corriger ce bogue, demandez-vous pourquoi. Y a-t-il quelque chose que vous
pouvez-vous faire pour faciliter la correction de ce bogue la prochaine fois ? Peut-être toi
pourrait intégrer de meilleurs crochets de test ou écrire un analyseur de fichiers journaux.

Enfin, si le bogue est le résultat d'une hypothèse erronée de quelqu'un, discutez de la


problème avec toute l'équipe : si une personne comprend mal, alors c'est
possible que beaucoup de gens le fassent.

Faites tout cela, et j'espère que vous ne serez pas surpris la prochaine fois.

Liste
Liste de
de contrôle
contrôle de
de débogage
débogage

• • Le problème signalé est-il le résultat direct de la cause sous-jacente


bug ou simple symptôme ?
• • Le bogue est-il vraiment dans le compilateur ? C'est dans l'OS ? Ou est-ce dans votre
code?
• • Si vous expliquiez ce problème en détail à un collègue, qu'est-ce qui
vous dites?
• • Si le code suspect réussit ses tests unitaires, les tests sont-ils terminés ?
assez? Que se passe-t-il si vous exécutez le test unitaire avec ces données ?
• • Les conditions à l'origine de ce bogue existent-elles ailleurs dans le
système?

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Programmation affirmée
• • Programmation par coïncidence
• • Automatisation omniprésente
• • Tests impitoyables

Défis
Défis

• • Le débogage est un défi suffisant.

Manipulation
Manipulation de
de texte
texte

Les programmeurs pragmatiques manipulent le texte de la même manière que les menuisiers
façonner le bois. Dans les sections précédentes, nous avons discuté de certains outils spécifiques—shells,
éditeurs, débogueurs que nous utilisons. Ceux-ci sont similaires à un travailleur du bois
burins, scies et rabots - des outils spécialisés pour bien faire un ou deux travaux.
Cependant, de temps en temps, nous devons effectuer une transformation non
facilement manipulé par l'ensemble d'outils de base. Nous avons besoin d'un texte général
outil de manipulation.

Les langages de manipulation de texte sont à la programmation de[8] cesont


que àles routeurs
travail du bois. Ils sont bruyants, désordonnés et quelque peu brutaux. Faire
erreurs avec eux, et des morceaux entiers peuvent être ruinés. Certaines personnes jurent
ils n'ont pas leur place dans la boîte à outils. Mais entre de bonnes mains, les routeurs et
les langages de manipulation de texte peuvent être incroyablement puissants et polyvalents. Toi
peut rapidement couper quelque chose en forme, faire des joints et sculpter. Utilisé
correctement, ces outils ont une finesse et une subtilité surprenantes. Mais ils prennent
le temps de maîtriser.

[8] Ici, le routeur signifie l'outil qui fait tourner les lames de coupe très, très rapidement, pas un dispositif d'interconnexion de réseaux.

Il existe un nombre croissant de bons langages de manipulation de texte. Unix


les développeurs aiment souvent utiliser la puissance de leurs shells de commande, augmentés
avec des outils tels awk
que et sed. Les personnes qui préfèrent un outil plus structuré
comme la nature orientée objet de Python [ URL 9 ]. Certaines personnes utilisent Tcl
[ URL 23 ] comme outil de prédilection. Il se trouve que nous préférons Perl [ URL 8 ] pour
pirater des scripts courts.

Ces langages sont des technologies habilitantes importantes. En les utilisant, vous pouvez
pirater rapidement des utilitaires et des idées de prototypes - des tâches qui peuvent prendre cinq ou
dix fois plus longtemps en utilisant les langages conventionnels. Et que se multipliant
facteur est d'une importance cruciale pour le type d'expérimentation que nous faisons.
Passer 30 minutes à essayer une idée folle est bien mieux que ça
passer cinq heures. Passer une journée à automatiser des composants importants d'un
le projet est acceptable ; passer une semaine pourrait ne pas l'être. Dans leur livre Le
Practice of Programming [ KP99 ], Kernighan et Pike ont construit le même
programme en cinq langues différentes. La version Perl était la plus courte (17
lignes, par rapport à C's 150). Avec Perl, vous pouvez manipuler du texte, interagir
avec des programmes, parler sur des réseaux, conduire des pages Web, effectuer des
arithmétique de précision et écrivez des programmes qui ressemblent à Snoopy jurant.

Astuce
Astuce 28
28

Apprendre un langage de manipulation de texte

Pour montrer la large applicabilité des langages de manipulation de texte,


voici un échantillon de certaines applications que nous avons développées au cours des dernières
années.

• • Maintenance du schéma de la base de données. Un ensemble de scripts Perl a pris un


fichier texte brut contenant une définition de schéma de base de données et à partir de celle-ci
généré :
oo Les instructions SQL pour créer la base de données
oo Fichiers de données plats pour remplir un dictionnaire de données
oo Bibliothèques de code C pour accéder à la base de données
oo Scripts pour vérifier l'intégrité de la base de données
oo Pages Web contenant des descriptions de schémas et des diagrammes
oo Une version XML du schéma
• • Accès aux propriétés Java. C'est un bon style de programmation OO pour
restreindre l'accès aux propriétés d'un objet, forçant les classes externes à obtenir
et définissez-les via des méthodes. Cependant, dans le cas courant où un
propriété est représentée à l'intérieur de la classe par une simple variable membre,
créer une méthode get et set pour chaque variable est fastidieux et
mécanique. Nous avons un script Perl qui modifie les fichiers source et
insère les définitions de méthode correctes pour toutes les
variables.
• • Génération de données de test. Nous avions des dizaines de milliers d'enregistrements de
des données de test, réparties sur plusieurs fichiers et formats différents, qui nécessitaient
à tricoter ensemble et à transformer en une forme adaptée au chargement
dans une base de données relationnelle. Perl l'a fait en quelques heures (et en
processus a trouvé quelques erreurs de cohérence dans les données d'origine).
• • Rédaction de livres. Nous pensons qu'il est important que tout code
présenté dans un livre aurait dû être testé en premier. La plupart du code dans
ce livre a été. Cependant, en utilisant le principe DRY (voir The Evils
de Duplication ) nous ne voulions pas copier et coller des lignes de code depuis
les programmes testés dans le livre. Cela aurait signifié que le
code a été dupliqué, garantissant pratiquement que nous oublions de
mettre à jour un exemple lorsque le programme correspondant a été modifié.
Pour certains exemples, nous ne voulions pas non plus vous ennuyer avec tous les
code de framework nécessaire pour que notre exemple compile et s'exécute. Nous
se tourna vers Perl. Un script relativement simple est invoqué lorsque nous formatons
le livre—il extrait un segment nommé d'un fichier source, fait la syntaxe
mise en surbrillance et convertit le résultat dans le langage de composition
nous utilisons.
• • Interface C vers Pascal Objet. Un client avait une équipe de développeurs
écriture de Pascal Objet sur PC. Leur code devait s'interfacer avec un
corps de code écrit en C. Nous avons développé un court script Perl qui
analysé
fonctionslesetfichiers d'en-tête
les structures deC,données
en extrayant les utilisaient.
qu'elles définitionsNous
de tous les fichiers
avons ensuite exportés
généré
Unités Pascal Objet avec enregistrements Pascal pour toutes les structures C, et
définitions de procédures importées pour toutes les fonctions C. Ce
le processus de génération est devenu une partie de la construction, de sorte que chaque fois que le C
en-tête changé, une nouvelle unité Object Pascal serait construite
automatiquement.
• • Génération de documentation Web. De nombreuses équipes de projet sont
publier leur documentation sur des sites Web internes. Nous avons
écrit de nombreux programmes Perl qui analysent les schémas de base de données, C ou
Fichiers source C++, makefiles et autres sources de projet pour produire le
documentation HTML requise. Nous utilisons également Perl pour envelopper le
documents avec en-têtes et pieds de page standard, et de les transférer
au site Web.

Nous utilisons presque tous les jours des langages de manipulation de texte. Beaucoup d'idées dans
ce livre peut y être mis en œuvre plus simplement que dans tout autre
langue dont nous sommes conscients. Ces langages facilitent l'écriture de code
générateurs, que nous verrons ensuite.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Les maux de la duplication

Des
Des exercices
exercices

11.
11. Votre programme C utilise un type énuméré pour représenter l'un des 100
États. Vous aimeriez pouvoir imprimer l'état sous forme de chaîne (comme
opposé à un nombre) à des fins de débogage. Écrivez un script qui
tli d

oPr d

e t

12.
12. A mi-chemin de l'écriture de ce livre, nous avons réalisé que nous n'avions pas mis le
utiliser la directive stricte dans beaucoup de nos exemples Perl. Écrire un scénario
qui passe par le .p1 vole dans un répertoire et ajoute un use strict à
la fin du bloc de commentaires initial à toutes les mouches qui n'ont pas déjà
un. N'oubliez pas de conserver une sauvegarde de toutes les mouches que vous changez.

Générateurs
Générateurs de
de codes
codes

Quand les menuisiers sont confrontés à la tâche de produire la même chose


encore et encore, ils trichent. Ils construisent eux-mêmes un gabarit ou un gabarit. Si ils
obtenir le bon gabarit une fois, ils peuvent reproduire un travail à maintes reprises.
Le gabarit enlève la complexité et réduit les chances de faire des erreurs,
laissant l'artisan libre de se concentrer sur la qualité.

En tant que programmeurs, nous nous retrouvons souvent dans une position similaire. Nous devons le faire
obtenir la même fonctionnalité, mais dans des contextes différents. Nous devons répéter
informations à différents endroits. Parfois, nous avons juste besoin de nous protéger
du syndrome du canal carpien en réduisant la saisie répétitive.

De la même manière qu'un menuisier investit du temps dans un gabarit, un programmeur peut
construire un générateur de code. Une fois construit, il peut être utilisé tout au long de la vie du
projet à peu de frais.

Astuce
Astuce 29
29

Écrire du code qui écrit du code

Il existe deux principaux types de générateurs de code :

1. 1. Les générateurs de code passifs sont exécutés une fois pour produire un résultat. Depuis
ce moment-là, le résultat devient autonome - il est divorcé
du générateur de code. Les sorciers dont il est question dans Evil Wizards,
ainsi que certains outils CASE, sont des exemples de code passif
générateurs.
2. 2. Les générateurs de code actifs sont utilisés chaque fois que leurs résultats sont
requis. Le résultat est jetable, il peut toujours être reproduit
par le générateur de code. Souvent, les générateurs de code actifs lisent une forme
de script ou de fichier de contrôle pour produire leurs résultats.

Générateurs
Générateurs de
de code
code passifs
passifs

Les générateurs de code passifs économisent la frappe. Ils sont essentiellement paramétrés
modèles, générant une sortie donnée à partir d'un ensemble d'entrées. Une fois le résultat
produit, il devient un fichier source à part entière dans le projet ; il sera édité,
compilé et placé sous contrôle de source comme n'importe quel autre fichier. Ses origines
sera oublié.

Les générateurs de code passifs ont de nombreuses utilisations :

• • Création de nouveaux fichiers source. Un générateur de code passif peut produire


modèles, directives de contrôle du code source, avis de droit d'auteur et
blocs de commentaires standard pour chaque nouveau fichier dans un projet. Nous avons notre
éditeurs configurés pour le faire chaque fois que nous créons un nouveau fichier : modifier un nouveau
programme Java, et le nouveau tampon de l'éditeur contiendra automatiquement un
le bloc de commentaires, la directive de package et la déclaration de classe de contour,
déjà rempli.
• • Effectuer des conversions ponctuelles entre les langages de programmation.
Nous avons commencé à écrire ce livre en utilisant le système troff, mais nous avons changé
à LaTeX après que 15 sections aient été complétées. Nous avons écrit un code
générateur qui a lu la source troff et l'a converti en LaTeX. C'était
environ 90 % précis ; le reste nous l'avons fait à la main. C'est intéressant
caractéristique des générateurs de code passifs : ils n'ont pas besoin d'être totalement
précis. Vous pouvez choisir combien d'efforts vous mettez dans le
générateur, par rapport à l'énergie que vous dépensez pour réparer sa sortie.
• • Produire des tables de recherche et d'autres ressources coûteuses
à calculer à l'exécution. Au lieu de calculer trigonométrique
fonctions, de nombreux premiers systèmes graphiques utilisaient des tables précalculées de
valeurs sinus et cosinus. Généralement, ces tableaux étaient produits par un
générateur de code passif puis copié dans la source.
Générateurs
Générateurs de
de code
code actifs
actifs

Alors que les générateurs de code passifs sont simplement une commodité, leur
les cousins sont une nécessité si vous voulez suivre le principe DRY. Avec un
générateur de code actif, vous pouvez prendre une seule représentation d'un morceau de
connaissances et convertissez-les dans toutes les formes dont votre application a besoin. C'est
pas de duplication, car les formes dérivées sont jetables et sont
généré au besoin par le générateur de code (d'où le mot actif).

Chaque fois que vous essayez d'obtenir deux environnements disparates pour
travailler ensemble, vous devriez envisager d'utiliser des générateurs de code actifs.

Vous développez peut-être une application de base de données. Ici, vous traitez
avec deux environnements—la base de données et le langage de programmation que vous
utilisent pour y accéder. Vous avez un schéma et vous devez définir des
structures reflétant la disposition de certaines tables de base de données. Vous pourriez juste
les coder directement, mais cela viole le principe DRY : la connaissance du
schéma serait alors exprimé en deux endroits. Lorsque le schéma change,
vous devez vous rappeler de changer le code correspondant. Si une colonne est
supprimé d'une table, mais la base de code n'est pas modifiée, vous pourriez même ne pas
obtenir une erreur de compilation. La première fois que vous le saurez, c'est lorsque vos tests
commencer à échouer (ou lorsque l'utilisateur appelle).

Une alternative consiste à utiliser un générateur de code actif - prenez le schéma et utilisez
pour générer le code source des structures, comme illustré à la Figure 3.3 .
Désormais, chaque fois que le schéma change, le code utilisé pour y accéder change également,
automatiquement. Si une colonne est supprimée, son champ correspondant dans le
la structure disparaîtra, et tout code de niveau supérieur qui utilise cette colonne
échouera à compiler. Vous avez attrapé l'erreur au moment de la compilation, pas dans
production. Bien sûr, ce schéma ne fonctionne que si vous créez le code
génération fait partie du processus de construction
[9] lui-même.

[9] Comment procédez-vous pour créer du code à partir d'un schéma de base de données ? Il existe plusieurs façons. Si le schéma est tenu dans un appartement

fichier (par exemple, créer


comme des instructions de table), un script relativement simple peut alors l'analyser et générer la source.

Alternativement, si vous utilisez un outil pour créer le schéma directement dans la base de données, vous devriez pouvoir extraire le

informations dont vous avez besoin directement à partir du dictionnaire de données de la base de données. Perl fournit des bibliothèques qui vous donnent accès à la plupart
principales bases de données.

Illustration
Illustration 3.3.
3.3. Le
Le générateur
générateur de
de code
code actif
actif crée
crée du
du code
code àà partir
partir d'une
d'une base
base de
de données
données

schéma
schéma

Un autre exemple d'environnements de fusion utilisant des générateurs de code se produit


lorsque différents langages de programmation sont utilisés dans la même application.
Afin de communiquer, chaque base de code aura besoin d'informations dans
common—structures de données, formats de message et noms de champ, par exemple.
Plutôt que de dupliquer ces informations, utilisez un générateur de code. Parfois
vous pouvez analyser les informations des fichiers source d'une langue et
l'utiliser pour générer du code dans une deuxième langue. Cependant, il est souvent plus simple de
exprimez-le dans une représentation plus simple et indépendante de la langue et générez le
code pour les deux langues, comme le montre la figure 3.4 à la page suivante. Aussi
voir la réponse à l'exercice 13 à la page 286 pour un exemple de séparation
l'analyse de la représentation du fichier plat à partir de la génération de code.

Illustration
Illustration 3.4.
3.4. Génération
Génération de
de code
code àà partir
partir d'une
d'une représentation
représentation indépendante
indépendante du
du langage.
langage.

Dans
Dans le
le fichier
fichier d'entrée,
d'entrée, les
les lignes
lignes commençant
commençant par
par 'M'
'M' marquent
marquent le
le début
début d'un
d'un message
message

définition,
définition, les
les lignes
lignes 'F'
'F' définissent
définissent les
les champs
champs et
et 'E'
'E' est
est la
la fin
fin du
du message.
message.

Les
Les générateurs
générateurs de
de code
code n'ont
n'ont pas
pas besoin
besoin d'être
d'être complexes
complexes

Tout ce discours sur l'actif et le passif qui peut vous laisser avec le
l'impression que les générateurs de code sont des bêtes complexes. Ils n'ont pas besoin de l'être.
Normalement, la partie la plus complexe est l'analyseur, qui analyse le fichier d'entrée.

Gardez le format d'entrée simple et le générateur de code devient simple.


Regardez la réponse à l'exercice 13 (page 286) : le code réel
génération est essentiellement
imprimer les relevés.

Les
Les générateurs
générateurs de
de code
code n'ont
n'ont pas
pas besoin
besoin de
de générer
générer de
de code
code

Bien que de nombreux exemples de cette section montrent des générateurs de code qui
produire la source du programme, cela ne doit pas toujours être le cas. Vous pouvez utiliser le code
générateurs pour écrire à peu près n'importe quelle sortie : HTML, XML, texte brut - n'importe
texte qui pourrait être une entrée ailleurs dans votre projet.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Les maux de la duplication


• • La puissance du texte brut
• • Sorciers maléfiques
• • Automatisation omniprésente

Des
Des exercices
exercices

13.
13. Écrivez un générateur de code qui prend le fichier d'entrée de la ,figure
et 3.4
génère une sortie dans deux langues de votre choix. Essayez de le rendre facile
pour ajouter de nouvelles langues.
Chapitre 4. Paranoïa pragmatique

Astuce
Astuce 30
30

Vous ne pouvez pas écrire un logiciel parfait

Cela a-t-il fait mal ? Ça ne devrait pas. Acceptez-le comme un axiome de la vie. Embrasse le.
Le célébrer. Parce que le logiciel parfait n'existe pas. Personne dans le brief
l'histoire de l'informatique n'a jamais écrit un logiciel parfait. C'est
peu de chances que vous soyez le premier. Et à moins que vous n'acceptiez cela comme un fait, vous
finir par perdre du temps et de l'énergie à poursuivre un rêve impossible.

Alors, compte tenu de cette réalité déprimante, comment un programmeur pragmatique la transforme-t-il
en avantage ? C'est le sujet de ce chapitre.

Tout le monde sait qu'ils sont personnellement le seul bon conducteur sur Terre.
Le reste du monde est là pour les attraper, soufflant à travers les panneaux d'arrêt,
se faufiler entre les voies, ne pas indiquer les virages, parler au téléphone,
lisant le journal, et ne respectant généralement pas nos normes. Alors on
conduire défensivement. Nous guettons les problèmes avant qu'ils ne surviennent, anticipons les
inattendu, et ne nous mettons jamais dans une position à partir de laquelle nous ne pouvons pas
nous tirer d'affaire.

L'analogie avec le codage est assez évidente. Nous interagissons constamment


avec le code d'autres personnes - un code qui pourrait ne pas être à la hauteur de notre
normes — et traitant des entrées qui peuvent ou non être valides. Alors on
apprennent à coder de manière défensive. En cas de doute, nous validons tout
informations que l'on nous donne. Nous utilisons des assertions pour détecter les mauvaises données. Nous vérifions
cohérence, impose des contraintes sur les colonnes de la base de données et se sent généralement bien
bien dans notre peau.

Mais les programmeurs pragmatiques vont encore plus loin. Ils ne font pas confiance
eux-mêmes non plus. Sachant que personne n'écrit de code parfait, y compris
eux-mêmes, les programmeurs pragmatiques codent pour se défendre contre leurs propres
erreurs. Nous décrivons la première mesure défensive dans Design by Contract :
les clients et les fournisseurs doivent s'entendre sur les droits et les responsabilités.

Dans Dead Programs Tell No Lies, nous voulons nous assurer que nous ne causerons aucun dommage
pendant que nous travaillons sur les bogues. Nous essayons donc de vérifier les choses souvent et
terminer le programme si les choses tournent mal.
La programmation assertive décrit une méthode simple de vérification le long de la
way — écrivez du code qui vérifie activement vos hypothèses.

Les exceptions, comme toute autre technique, peuvent causer plus de mal que de bien sinon
utilisé correctement. Nous discuterons des problèmes dans Quand utiliser les exceptions.

Au fur et à mesure que vos programmes deviennent plus dynamiques, vous vous retrouverez à jongler avec le système
ressources : mémoire, fichiers, périphériques, etc. Dans Comment équilibrer
ressources, nous vous proposerons des moyens de vous assurer de ne laisser tomber aucun des
des balles.

Dans un monde de systèmes imparfaits, d'échelles de temps ridicules, d'outils risibles et de


exigences impossibles, jouons la sécurité.

Quand tout le monde cherche à vous avoir, la paranoïa est juste une bonne idée.

Alien
Alien boisé
boisé

Conception
Conception par
par contrat
contrat

Rien n'étonne autant les hommes que le bon sens et la simplicité.

Ralph
Ralph Waldo
Waldo Emerson,
Emerson, Essais
Essais

La gestion des systèmes informatiques est difficile. Traiter avec les gens est encore plus difficile.
Mais en tant qu'espèce, nous avons eu plus de temps pour comprendre les problèmes de l'homme
interactions. Certaines des solutions que nous avons proposées au cours des dernières
millénaires peuvent également être appliqués à l'écriture de logiciels. Un des meilleurs
des solutions pour assurer l'utilisation en clair est le contrat.

Un contrat définit vos droits et responsabilités, ainsi que ceux du


autre fête. De plus, il existe un accord concernant les répercussions si
l'une ou l'autre des parties ne respecte pas le contrat.

Peut-être avez-vous un contrat de travail qui précise les heures que vous
travail et les règles de conduite que vous devez suivre. En contrepartie, l'entreprise paie
vous un salaire et d'autres avantages. Chaque partie respecte ses obligations et chacun
avantages.

C'est une idée utilisée dans le monde entier, formellement et informellement, pour aider
les humains interagissent. Peut-on utiliser le même concept pour aider les modules logiciels
interagir? La réponse est oui."

DBC
DBC

Bertrand Meyer [ Mey97b ] a développé le concept de Design by Contract pour


la langue Eiffel. [1] C'est une technique simple mais puissante qui se concentre sur
documenter (et accepter) les droits et responsabilités du logiciel
modules pour assurer l'exactitude du programme. Qu'est-ce qu'un programme correct ? Un
qui ne fait ni plus ni moins que ce qu'elle prétend faire. Documenter et
vérifier que la réclamation est au cœur de la conception par contrat (DBC, pour faire court).

[1] Basé en partie sur des travaux antérieurs de Dijkstra, Floyd, Hoare, Wirth et d'autres. Pour plus d'informations sur Eiffel lui-même, voir

[ URL 10 ] et [ URL 11 ].

Chaque fonction et méthode d'un système logiciel fait quelque chose. Avant cela
commence que quelque chose, la routine peut avoir une certaine attente de l'état
du monde, et il peut être en mesure de faire une déclaration sur l'état de la
monde quand il se termine. Meyer décrit ces attentes et affirmations comme
suit :
• • Conditions préalables. Qu'est-ce qui doit être vrai pour que la routine soit
appelé; les exigences de la routine. Une routine ne devrait jamais être appelée
lorsque ses conditions préalables seraient violées. C'est celui de l'appelant
responsabilité de transmettre de bonnes données (voir encadré page 115).
• • Postconditions. Ce que la routine est garantie de faire ; l'état
du monde lorsque la routine est terminée. Le fait que la routine ait un
la postcondition implique qu'elle se terminera : les boucles infinies ne sont pas
autorisé.
• • Invariants de classe. Une classe assure que cette condition est toujours
vrai du point de vue d'un appelant. Lors du traitement interne d'un
routine, l'invariant peut ne pas tenir, mais au moment où la routine se termine
et que le contrôle revient à l'appelant, l'invariant doit être vrai. (Note
qu'une classe ne peut donner un accès en écriture illimité à aucune donnée
membre qui participe à l'invariant.)

Examinons le contrat d'une routine qui insère une valeur de données dans un
liste unique et ordonnée. Dans iContract, un préprocesseur pour Java disponible chez
[ URL 17 ] ,

p u

Ici, nous disons que les nœuds de cette liste doivent toujours être en augmentation
commande. Lorsque vous insérez un nouveau nœud, il ne peut pas déjà exister, et nous vous garantissons
que le nœud sera trouvé après l'avoir inséré.

Vous écrivez ces préconditions, postconditions et invariants dans la cible


langage de programmation, peut-être avec quelques extensions. Par exemple,
iContract fournit des opérateurs logiques de prédicat—
forall, existe, et
implique — en plus des constructions Java normales. Vos affirmations peuvent interroger
l'état de tout objet auquel la méthode peut accéder, mais assurez-vous que le
query est exempt d'effets secondaires (voir page 124).

DBC et paramètres constants

Souvent, une postcondition utilisera des paramètres passés dans une méthode pour
vérifier le bon comportement. Mais si la routine est autorisée à changer le
paramètre transmis, vous pourrez peut-être contourner le
contracter. Eiffel ne permet pas que cela se produise, mais Java oui. Ici, nous
utiliser le mot-clé Java finale pour indiquer nos intentions que le
Le paramètre ne doit pas être modifié dans la méthode. Ce n'est pas
à toute épreuve–les sous-classes sont libres de redéclarer le paramètre comme
non définitif. Alternativement, vous pouvez utiliser la syntaxe iContract
variable @pre pour obtenir la valeur d'origine de la variable telle qu'elle existait sur
entrée dans la méthode.

Le contrat entre une routine et tout appelant potentiel peut donc être lu comme

Si toutes les conditions préalables de la routine sont remplies par l'appelant, la routine doit
garantir que toutes les postconditions et tous les invariants seront vrais lorsqu'il
complète.
Si l'une ou l'autre des parties ne respecte pas les termes du contrat, un recours
(ce qui avait été précédemment convenu) est invoquée : une exception est déclenchée ou la
programme se termine, par exemple. Quoi qu'il arrive, ne vous méprenez pas
que le non-respect du contrat est un bogue. Ce n'est pas quelque chose qui
ne devrait jamais arriver, c'est pourquoi les conditions préalables ne doivent pas être utilisées pour
effectuer des choses telles que la validation des entrées utilisateur.

Astuce
Astuce 31
31

Concevoir avec des contrats

En orthogonalité , nous vous recommandons d'écrire du code "timide". Ici, l'accent


est sur le code "paresseux": soyez strict dans ce que vous accepterez avant de commencer, et
promettre le moins possible en retour. N'oubliez pas que si votre contrat indique
que vous accepterez n'importe quoi et promettez au monde en retour, alors vous avez
beaucoup de code à écrire !

L'héritage et le polymorphisme sont les pierres angulaires de l'orientation objet.


langues et un domaine où les contrats peuvent vraiment briller. Supposez que vous êtes
utiliser l'héritage pour créer une relation "est-un-sorte-de", où une classe
"est-une-sorte-de" une autre classe. Vous voulez probablement adhérer au Liskov
Principe de substitution [Lis88] :

Les sous-classes doivent être utilisables via l'interface de la classe de base sans le
besoin pour l'utilisateur de connaître la différence.

En d'autres termes, vous voulez vous assurer que le nouveau sous-type que vous avez
créé vraiment "est-un-klnd-de" le type de base - qu'il prend en charge le même
méthodes, et que les méthodes ont le même sens. Nous pouvons le faire
avec des contrats. Nous n'avons besoin de spécifier un contrat qu'une seule fois, dans la classe de base, pour
l'appliquer automatiquement à chaque future sous-classe. Une sous-classe peut,
éventuellement, accepter un plus large éventail d'entrées ou donner des garanties plus solides. Mais
il doit accepter au moins autant et garantir autant que sa société mère.

Par exemple, considérons la classe de base Java


java.awt.Component. Tu peux
traiter tout composant visuel dans AWT ou Swing commeComposant,
un sans
sachant que la sous-classe réelle est un bouton, un canevas, un menu ou autre.
Chaque composant individuel peut fournir des fonctionnalités supplémentaires spécifiques,
am si
aM si
qui fournit des méthodes correctement nommées qui font la mauvaise chose. Tu peux
créer facilement une méthode de peinture qui ne peint pas, ou une méthode setFont qui
ne définit pas la police. AWT n'a pas de contrats pour attraper le fait que vous
n'a pas respecté l'accord.

Sans contrat, tout ce que le compilateur peut faire est de s'assurer qu'une sous-classe
est conforme à une signature de méthode particulière. Mais si on met une classe de base
contrat en place, nous pouvons maintenant nous assurer que toute future sous-classe ne peut pas modifier
le sens de nos méthodes. Par exemple, vous voudrez peut-être établir un

contrat pour setFont tel que le suivant, qui garantit que la police que vous
s e
Mise
Mise en
en œuvre
œuvre de
de la
la DBC
DBC

Le plus grand avantage de l'utilisation de DBC peut être qu'il force le problème de
exigences et garanties au premier plan. En énumérant simplement à
au moment de la conception, quelle est la plage du domaine d'entrée, quelles sont les conditions aux limites
sont, et ce que la routine promet de livrer - ou, plus important encore, ce que
il ne promet pas de livrer - est un énorme bond en avant pour mieux écrire
logiciel. En ne déclarant pas ces choses, vous revenez à la programmation en
coïncidence , où de nombreux projets commencent, se terminent et échouent.

Dans les langues qui ne prennent pas en charge DBC dans le code, cela peut aller jusqu'à
vous pouvez y aller, et ce n'est pas trop mal. DBC est, après tout, une technique de conception.
Même sans vérification automatique, vous pouvez mettre le contrat dans le code comme
commentaires et toujours obtenir un avantage très réel. Si rien d'autre, le commenté
les contrats vous donnent un point de départ pour chercher en cas de problème.

Assertions
Assertions

Bien que la documentation de ces hypothèses soit un bon début, vous pouvez obtenir beaucoup
plus grand avantage en demandant au compilateur de vérifier votre contrat pour vous. Tu peux
émuler partiellement cela dans certaines langues en utilisant des assertions (voir Assertive
La programmation ). Pourquoi seulement partiellement ? Ne pouvez-vous pas utiliser des assertions pour faire
tout ce que DBC peut faire ?

Malheureusement, la réponse est non. Pour commencer, il n'y a pas de support pour
propagation des assertions dans une hiérarchie d'héritage. Cela signifie que si
vous remplacez une méthode de classe de base qui a un contrat, les assertions qui
mettre en œuvre ce contrat ne sera pas appelé correctement (sauf si vous dupliquez
manuellement dans le nouveau code). Vous devez vous rappeler d'appeler la classe
invariant (et tous les invariants de classe de base) manuellement avant de quitter chaque
méthode. Le problème fondamental est que le contrat n'est pas automatiquement
forcée.

De plus, il n'y a pas de concept intégré d'"anciennes" valeurs ; c'est-à-dire les valeurs telles qu'elles
existait à l'entrée d'une méthode. Si vous utilisez des assertions pour appliquer
contrats, vous devez ajouter du code à la condition préalable pour enregistrer toute information
vous voudrez utiliser dans la postcondition. Comparez cela avec iContract, où
la postcondition peut simplement faire« référence
Variable @pre », ou avec Eiffel, qui
p er

Enfin, le système d'exécution et les bibliothèques ne sont pas conçus pour prendre en charge
contrats, ces appels ne sont donc pas contrôlés. C'est une grande perte, car c'est
souvent à la frontière entre votre code et les bibliothèques qu'il utilise que le
la plupart des problèmes sont détectés (voir Dead Programs Tell No Lies pour plus
discussion détaillée).

Support
Support linguistique
linguistique

Langages prenant en charge DBC (comme Eiffel et Sather


[ URL 12 ]) vérifie automatiquement les pré- et postconditions dans le compilateur et
système d'exécution. Vous obtenez le plus grand avantage dans ce cas parce que tous les
la base de code (les bibliothèques aussi) doivent honorer leurs contrats.

Mais qu'en est-il des langages plus populaires tels que C, C++ et Java ? Pour
ces langages, il existe des préprocesseurs qui traitent les contrats embarqués
dans le code source d'origine sous forme de commentaires spéciaux. Le préprocesseur développe
ces commentaires au code qui vérifie les assertions.

Pour C et C++, vous voudrez peut-être étudier Nana [ URL 18 ]. Nana n'est pas
gérer l'héritage, mais il utilise le débogueur au moment de l'exécution pour surveiller
affirmations d'une manière inédite.

Pour Java, il y a iContract [ URL 17 ]. Il prend des commentaires (sous forme JavaDoc)
et génère un nouveau fichier source avec la logique d'assertion incluse.

Les préprocesseurs ne sont pas aussi bons qu'une installation intégrée. Ils peuvent être salissants pour
intégrer dans votre projet, et les autres bibliothèques que vous utilisez n'auront pas de contrats.
Mais ils peuvent toujours être très utiles ; lorsqu'un problème est découvert ceci
façon - surtout un que vous n'auriez jamais trouvé - c'est presque comme
la magie.

DBC
DBC et
et Crashing
Crashing Early
Early

DBC correspond bien à notre concept de plantage précoce (voir Programmes morts
Ne dis pas de mensonges). Supposons que vous ayez une méthode qui calcule les racines carrées (comme
comme dans la classe Eiffel DOUBLE ). Il a besoin d'une condition préalable qui limite la

domaine aux nombres positifs. Une précondition Eiffel est déclarée avec le
mot-clé exigent, et une postcondition est déclarée avec assurer, vous pouvez donc
éc eri

Qui est responsable ?

Qui est responsable d'avoir rempli la condition préalable, l'appelant ou le


la routine est-elle appelée ? lorsqu'il est implémenté dans le cadre du langage,
la réponse n'est ni l'une ni l'autre : la routine mais avant que la routine elle-même ne soit
entré. Ainsi, s'il existe une vérification explicite des paramètres à
fait, il doit être effectué par l'appelant, car la routine elle-même
ne verra jamais les paramètres qui violent sa condition préalable. (Pour
langues sans prise en charge intégrée, vous devrez mettre entre parenthèses
appelée routine avec un préambule et/ou postambule qui vérifie ces
affirmations.)

Considérez un programme qui lit un nombre à partir de la console, calculez


sa racine carrée (en appelant s
La fonction a une condition préalable : son argument ne doit pas être négatif. Si
l'utilisateur saisit un nombre négatif sur la console, c'est au
code d'appel pour s'assurer qu'il n'est jamais transmissqrt.
à Cet appel
le code a de nombreuses options : il peut se terminer, il peut émettre un avertissement
et lire un autre numéro, ou cela pourrait rendre le numéro positif et
ajouter un "i" au résultat renvoyé par sqrt. Quel que soit son choix, ce
n'est certainement pas le problème de sqrt.

En exprimant le domaine de la fonction racine carrée dans le


condition préalable de la routine sqrt, vous déplacez le fardeau de l'exactitude
à l'appel—à sa place. vous pouvez ensuite concevoir le routine sqrt
sûr de savoir que son entrée sera à portée.
Si votre algorithme de calcul de la racine carrée échoue (ou n'est pas dans les
tolérance d'erreur spécifiée), vous obtenez un message d'erreur et une trace de pile à
vous montrer la chaîne d'appel.

Si vous passezsqrt un paramètre négatif, le runtime Eiffel imprime l'erreur


"sqrt_arg_must_be_positive", ainsi qu'une trace de pile. C'est mieux que
l'alternative dans des langages tels que Java, C et C++, où le passage d'un
nombre négatif à sqrt renvoie la valeur spéciale NaN (Not a Number). Il
peut-être quelque temps plus tard dans le programme que vous essayez de faire des calculs
surNaN, avec des résultats surprenants.

Il est beaucoup plus facile de trouver et de diagnostiquer le problème en plantant tôt, au


site du problème.

Autres
Autres utilisations
utilisations des
des invariants
invariants

Jusqu'à présent, nous avons discuté des conditions préalables et postérieures qui s'appliquent aux individus.
méthodes et invariants qui s'appliquent à toutes les méthodes d'une classe, mais il
sont d'autres façons utiles d'utiliser les invariants.

Invariants
Invariants de
de boucle
boucle

Obtenir les bonnes conditions aux limites sur une boucle non trMal peut être
problématique. Les boucles sont sujettes au problème de la banane (je sais épeler
« banane », mais je ne sais pas quand m'arrêter), erreurs de clôture (ne sachant pas
s'il faut compter les poteaux de clôture ou les espaces entre eux), et le
erreur omniprésente "off by one" [ URL 52
].

Les invariants peuvent aider dans ces situations : un invariant de boucle est une déclaration de
l'objectif final d'une boucle, mais est généralisé de sorte qu'il est également valable avant
la boucle s'exécute et à chaque itération de la boucle. Tu peux y penser
comme une sorte de contrat miniature. L'exemple classique est une routine qui trouve
al av

(arr[m:n] est une commodité de notation signifiant une tranche du tableau de


index m à n.) L'invariant doit être vrai avant l'exécution de la boucle, et le corps
de la boucle doit s'assurer qu'il reste vrai pendant l'exécution de la boucle. Dans ce
façon dont nous savons que l'invariant est également valable lorsque la boucle se termine, et
donc que notre résultat est valide. Les invariants de boucle peuvent être codés explicitement comme
assertions, mais ils sont également utiles comme outils de conception et de documentation.

Invariants
Invariants sémantiques
sémantiques

Vous pouvez utiliser des invariants sémantiques pour exprimer des exigences inviolables, une sorte
de "contrat philosophique".

Nous avons déjà écrit un commutateur de transaction par carte de débit. Une exigence majeure était
que l'utilisateur
appliqué d'une carte
à leur compte deuxdefois.
débit
Enne devraittermes,
d'autres jamais quel
effectuer la même
que soit le typetransaction
de
le mode d'échec peut se produire, l'erreur doit être du côté de non
traiter une transaction plutôt que de traiter une transaction en double.

Cette loi simple, directement inspirée des exigences, s'est avérée très
utile pour trier les scénarios de récupération d'erreurs complexes, et guidé le
conception détaillée et mise en œuvre dans de nombreux domaines.

Veillez à ne pas confondre les exigences qui sont des lois fixes et inviolables avec
ceux qui ne sont que des politiques susceptibles de changer avec une nouvelle direction
régime. C'est pourquoi nous utilisons le terme d'invariants sémantiques - il doit être
central au sens même d'une chose, et non soumis aux caprices de
policy (à quoi servent les règles métier plus dynamiques).

Lorsque vous trouvez une exigence qui se qualifie, assurez-vous qu'elle devient une
partie bien connue de la documentation que vous produisez, qu'elle soit
il s'agit d'une liste à puces dans le document d'exigences qui est signé
triple exemplaire ou juste une grosse note sur le tableau blanc commun que tout le monde voit.
Essayez de l'énoncer clairement et sans ambiguïté. Par exemple, dans la carte de débit
exemple, on pourrait écrire

E RR EN FAVEUR DU CONSOMMATEUR .

Il s'agit d'une déclaration claire, concise et sans ambiguïté qui s'applique dans de nombreux
différents domaines du système. C'est notre contrat avec tous les utilisateurs du système,
notre garantie de comportement.

Contrats
Contrats et
et agents
agents dynamiques
dynamiques

Jusqu'à présent, nous avons parlé de contrats comme fixes, immuables


Caractéristiques. Mais dans le paysage des agents autonomes, cela n'a pas besoin
être le cas. Selon la définition d'"autonome", les agents sont libres de rejeter
demandes qu'ils ne veulent pas honorer. Ils sont libres de renégocier
contrat - "Je ne peux pas fournir cela, mais si vous me donnez ceci, alors je pourrais fournir
autre chose."

Il est certain que tout système qui s'appuie sur la technologie des agents a un rôle critique à jouer
dépendance vis-à-vis des accords contractuels, même s'ils sont dynamiquement
généré.

Imaginez : avec suffisamment de composants et d'agents capables de négocier leur propre


contrats entre eux pour atteindre un objectif, nous pourrions simplement résoudre le
crise de productivité logicielle en laissant le logiciel la résoudre pour nous.

Mais si nous ne pouvons pas utiliser les contrats à la main, nous ne pourrons pas les utiliser
automatiquement. Alors la prochaine fois que vous concevez un logiciel, concevez son
contrat aussi.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Orthogonalité
• • Les programmes morts ne mentent pas
• • Programmation affirmée
• • Comment équilibrer les ressources
• • Le découplage et la loi de Déméter
• • Couplage temporel
• • Programmation par coïncidence
• • Code facile à tester
• • Des équipes pragmatiques
Défis
Défis
• • Points à méditer : Si DBC est si puissant, pourquoi n'est-il pas utilisé plus
largement? Est-ce difficile de trouver le contrat ? Est-ce que ça te fait
pensez à des problèmes que vous préférez ignorer pour l'instant ? Cela vous oblige-t-il à
PENSER!? Clairement, c'est un outil dangereux !

Des
Des exercices
exercices

14.
14. Qu'est-ce qui fait un bon contrat ? N'importe qui peut ajouter des conditions préalables et
postconditions, mais vous seront-elles utiles ? Pire encore, vont-ils
fait plus de mal que de bien ? Pour l'exemple ci-dessous et pour
ceux des Exercices 15 et 16, décidez si le contrat spécifié est
bon, mauvais ou laid, et expliquez pourquoi.

Prenons d'abord un exemple Eiffel. Ici, nous avons une routine pour
ajouter une chaîne à une liste circulaire doublement liée (rappelez-vous que
les préconditions sont étiquetées avec require et les postconditions avec
a s

15.
15. Ensuite, essayons un exemple en Java, un peu similaire à l'exemple
dans l'exercice 14. insertNumber insère un entier dans une liste ordonnée.
eL s

16.
16. Voici un fragment d'une classe de pile en Java. Est-ce un bon contrat ?

/
17.
17. Les exemples classiques de DBC (comme dans les Exercices 14-16) montrent une
implémentation d'un ADT (Abstract Data Type) - généralement une pile ou
file d'attente. Mais peu de gens écrivent vraiment ce genre de messages de bas niveau
Des classes .

Donc, pour cet exercice, concevez une interface vers un mixeur de cuisine. Ce sera
éventuellement être un mélangeur basé sur le Web, compatible Internet et CORBA,
mais pour l'instant nous avons juste besoin de l'interface pour le contrôler. Il a dix vitesses
paramètres (0 signifie désactivé). Vous ne pouvez pas le faire fonctionner à vide, et vous pouvez changer
la vitesse une seule unité à la fois (c'est-à-dire de 0 à 1, et de 1 à 2,
pas de 0 à 2).

Voici les méthodes. Ajouter les conditions préalables et postérieures appropriées et


u n ainv

18.
18. Combien y a-t-il de nombres dans la série 0,5,10,15,…, 100 ?

Les
Les programmes
programmes morts
morts ne
ne mentent
mentent pas
pas

Avez-vous remarqué que parfois d'autres personnes peuvent détecter que les choses ne sont pas
bien avec vous avant de vous rendre compte du problème vous-même ? C'est le même
avec le code des autres. Si quelque chose commence à mal tourner avec l'un de nos
programmes, c'est parfois une routine de bibliothèque qui l'attrape en premier. Peut-être un
pointeur errant nous a fait écraser un descripteur de fichier avec quelque chose
sans signification. Le prochain appel à lire l'attrapera. Peut-être un dépassement de tampon
a détruit un compteur que nous sommes sur le point d'utiliser pour déterminer la quantité de mémoire à
allouer. Peut-être que nous aurons un échec de malloc. Une erreur de logique quelques
il y a un million d'instructions signifie que le sélecteur d'une instruction case n'est pas
plus le 1, 2 ou 3 attendu. Nous allons frapper le cas par défaut (ce qui est l'une des raisons

pourquoi chaque instruction case/switch doit avoir une valeur par défaut
clause - nous voulons savoir quand "l'impossible" s'est produit).

Il est facile de tomber dans la mentalité "ça ne peut pas arriver". La plupart d'entre nous ont écrit
code qui n'a pas vérifié qu'un fichier s'est bien fermé, ou qu'une trace
la déclaration a été rédigée comme prévu. Et toutes choses étant égales par ailleurs, il est probable
dont nous n'avions pas besoin - le code en question n'échouerait pas dans des conditions normales
conditions. Mais nous codons défensivement. Nous recherchons des pointeurs malveillants dans
d'autres parties de notre programme saccageant la pile. Nous vérifions que le
les versions correctes des bibliothèques partagées ont été effectivement chargées.

Toutes les erreurs vous donnent des informations. Vous pourriez vous convaincre que l'erreur
ne peut pas arriver, et choisissez de l'ignorer. Au lieu de cela, les programmeurs pragmatiques disent
eux-mêmes que s'il y a une erreur, quelque chose de très, très mauvais a
arrivé.

Astuce
Astuce 32
32

Accident précoce

Crash,
Crash, ne
ne pas
pas jeter
jeter
L'un des avantages de détecter les problèmes le plus tôt possible est que vous pouvez
planter plus tôt. Et souvent, planter votre programme est la meilleure chose que vous
peut faire. L'alternative peut être de continuer, en écrivant des données corrompues sur certains
base de données vitale ou commander la machine à laver dans son vingtième
cycle d'essorage consécutif.

Le langage et les bibliothèques Java ont adopté cette philosophie. Quand


quelque chose d'inattendu se produit dans le système d'exécution, il jette un
Exception d'exécution. S'il n'est pas détecté, cela remontera jusqu'au niveau supérieur du
programme et le faire s'arrêter, affichant une trace de pile.

Vous pouvez faire la même chose dans d'autres langues. Si vous n'avez pas d'exception
mécanisme, ou si vos bibliothèques ne lèvent pas d'exceptions, assurez-vous que vous
g éer

ov di

sEn u

En c a

De toute évidence, il est parfois inapproprié de simplement quitter un programme en cours d'exécution.
Vous avez peut-être réclamé des ressources qui pourraient ne pas être libérées, ou vous pouvez
besoin d'écrire des messages de journal, de ranger les transactions ouvertes ou d'interagir avec
d'autres processus. Les techniques dont nous discutons dans Quand utiliser , sera
les exceptions
aide ici. Cependant, le principe de base reste le même : lorsque votre code
découvre que quelque chose qui était censé être impossible vient de se produire,
votre programme n'est plus viable. Tout ce qu'il fait à partir de maintenant
devient suspect, alors mettez-y fin dès que possible. Un programme mort
fait normalement beaucoup moins de dégâts qu'un infirme.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Conception par contrat


• • Quand utiliser les exceptions

Programmation
Programmation assertive
assertive

Il y a un luxe à se reprocher. Quand nous nous blâmons, nous ne sentons personne


d'autre a le droit de nous blâmer.

Oscar
Oscar Wilde,
Wilde, Le
Le Portrait
Portrait de
de Dorian
Dorian Gray
Gray

Il semble qu'il y ait un mantra que chaque programmeur doit mémoriser


tôt dans sa carrière. C'est un principe fondamental de l'informatique, un noyau
croyance que nous apprenons à appliquer les exigences, les conceptions, le code, les commentaires, juste
sur tout ce que nous faisons. Ça va
J CELA NE PEUT JAMAIS SE PRODUIRE…

"Ce code ne sera plus utilisé dans 30 ans, donc les dates à deux chiffres conviennent."
« Cette application ne sera jamais utilisée à l'étranger, alors pourquoi l'internationaliser ?
"count ne peut pas être négatif." "Ce printf ne peut pas échouer."

Ne pratiquons pas ce genre d'auto-tromperie, en particulier lors du codage.

Astuce
Astuce 33
33

Si cela ne peut pas se produire, utilisez des assertions pour vous assurer que cela ne se produira pas

Chaque fois que vous vous surprenez à penser "mais bien sûr cela ne pourrait jamais
arrive", ajoutez du code pour le vérifier. La façon la plus simple de le faire est d'utiliser des assertions.
Dans la plupart des implémentations C et C++, vous trouverez une affirmer
certaine
ouforme de
Macro _assert qui vérifie une condition booléenne. Ces macros peuvent être
ein s
p u

Les assertions sont également des contrôles utiles sur le fonctionnement d'un algorithme. Peut-être avez-vous
éc tri

Bien sûr, la condition passée à une assertion ne doit pas avoir d'effet secondaire
(voir encadré page 124). Rappelez-vous également que les assertions peuvent être désactivées
a u

N'utilisez pas d'assertions à la place d'une véritable gestion des erreurs. Vérification des assertions
d e

Et juste parce que les macros assert fournies appellent exit lorsqu'une assertion
échoue, il n'y a aucune raison pour que les versions que vous écrivez échouent. Si vous avez besoin de libérer

ressources, avoir un échec d'assertion générer une exception, longjmp à un


point de sortie ou appelez un gestionnaire d'erreurs. Assurez-vous simplement que le code que vous exécutez dans
ces millisecondes qui meurent ne reposent pas sur les informations qui ont déclenché le
échec de l'assertion en premier lieu.

Laisser
Laisser les
les assertions
assertions activées
activées

Il y a un malentendu courant sur les affirmations, promulguées par le


les personnes qui écrivent des compilateurs et des environnements de langage. Il se passe quelque chose
comme ça:
Les affirmations impair une surcharge de code. Parce qu'ils vérifient les choses qui
ne devraient jamais arriver, ils ne seront déclenchés que par un bogue dans le code. Une fois
le code a été testé et expédié, ils ne sont plus nécessaires, et
doit être désactivé pour que le code s'exécute plus rapidement. Les affirmations sont un
installation de débogage.

Il y a deux hypothèses manifestement fausses ici. Premièrement, ils supposent que


testing trouve tous les bogues. En réalité, pour tout programme complexe, vous êtes
peu de chances de tester même un infime pourcentage des permutations de votre code
sera mis à travers (voir Ruthless Testing ). Deuxièmement, les optimistes sont
en oubliant que votre programme s'exécute dans un monde dangereux. Lors des tests,
les rats ne rongeront probablement pas un câble de communication, quelqu'un
jouer à un jeu n'épuisera pas la mémoire et les fichiers journaux ne rempliront pas le disque dur.
Ces choses peuvent se produire lorsque votre programme s'exécute dans un environnement de production
environnement. Votre première ligne de défense consiste à vérifier toute erreur possible,
et votre deuxième utilise des assertions pour essayer de détecter celles que vous avez manquées.

Désactiver les assertions lorsque vous livrez un programme à la production, c'est comme
franchir un fil sans filet parce que vous l'avez traversé une fois en
pratique. Il y a une valeur considérable, mais il est difficile d'obtenir une assurance-vie.

Même si vous rencontrez des problèmes de performances, désactivez uniquement les assertions qui
t'a vraiment frappé. L'exemple de tri ci-dessus peut être un élément essentiel de

Assertion et effets secondaires

C'est gênant quand le code que nous ajoutons pour détecter les erreurs
finit par créer de nouvelles erreurs. Cela peut arriver avec des assertions si
l'évaluation de la condition a des effets secondaires. par exemple, en Java, il
serait mauvais de coder quelque chose comme

ewhil (

L'appel .nextElement() dans ASSERT a pour effets secondaires de déplacer


l'itérateur après l'élément en cours de récupération, et donc la boucle sera
traiter seulement la moitié des éléments de la collection. Il vaudrait mieux
éc eriv

Ce problème est une sorte de "Heisenbug" - un débogage qui modifie le


comportement du système système en cours de débogage (voir ]).[ URL 52

votre application, et peut devoir être rapide. Ajouter le chèque signifie un autre
passer par les données, ce qui pourrait être inacceptable. Rendez cela particulier
[2] mais laissez le reste dedans.
cocher en option,

[2] Dans les langages basés sur C, vous pouvez soit utiliser le préprocesseur, soit utiliser des instructions if pour rendre les assertions facultatives. Beaucoup

les implémentations désactivent la génération de code


assert
pour
macro si un indicateur de compilation est défini (ou non défini). Sinon, vous
peut placer le code dans un if instruction avec une condition constante, que de nombreux compilateurs (y compris les plus courants

systèmes Java) seront optimisés.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::
• • Débogage
• • Conception par contrat
• • Comment équilibrer les ressources
• • Programmation par coïncidence

Des
Des exercices
exercices

19.
19. Une rapide vérification de la réalité. Laquelle de ces choses "impossibles" peut arriver ?

1. 1. Un mois de moins de 28 jours


2. 2. stat("." ,&sb) == -1 (c'est-à-dire, impossible d'accéder au

annuaire)
3 .
4. 4. Un triangle avec une somme d'angle intérieur \u8800 180°
5. 5. Une minute qui n'a pas 60 secondes
6 .

20.
20. Développer une simple classe de vérification d'assertions pour Java .

Quand
Quand utiliser
utiliser les
les exceptions
exceptions

Dans Dead Programs Tell No Lies , nous avons suggéré qu'il est bon de
recherchez toutes les erreurs possibles, en particulier les erreurs inattendues. Cependant,
en pratique, cela peut conduire à un code assez laid ; la logique normale de votre
programme peut finir par être totalement obscurci par la gestion des erreurs, en particulier si
vous êtes abonné à l'école "une routine doit avoir une seule déclaration de retour"
de programmation (nous ne le faisons pas). Nous avons vu du code qui ressemble à quelque chose comme
s u

Heureusement, si le langage de programmation prend en charge les exceptions, vous pouvez


réécrivez ce code de manière beaucoup plus nette :
er t

Le flux normal de contrôle est maintenant clair, avec toute la gestion des erreurs déplacée
vers un seul endroit.

Qu'est-ce
Qu'est-ce qui
qui est
est exceptionnel
exceptionnel ??

L'un des problèmes avec les exceptions est de savoir quand les utiliser. Nous
croient que les exceptions devraient rarement être utilisées dans le cadre du fonctionnement normal d'un programme
couler; les exceptions doivent être réservées aux événements imprévus. Supposons qu'un
une exception non détectée mettra fin à votre programme et vous demandera : "Est-ce que
ce code s'exécute toujours si je supprime tous les gestionnaires d'exceptions ?" Si la réponse est
"non", alors peut-être que des exceptions sont utilisées dans des cas non exceptionnels
circonstances.

Par exemple, si votre code tente d'ouvrir un fichier en lecture et que ce fichier ne
n'existe pas, faut-il lever une exception ?

Notre réponse est : "Cela dépend." Si le fichier aurait dû être là, alors un
exception est justifiée. Quelque chose d'inattendu s'est produit : un fichier que vous étiez
s'attendre à exister semble avoir disparu. D'autre part, si vous
n'ont aucune idée si le fichier doit exister ou non, alors il ne semble pas
exceptionnel si vous ne le trouvez pas, et un retour d'erreur est approprié.

Prenons un exemple du premier cas. Le code suivant ouvre le fichier


/etc/passwd, qui devrait exister sur tous les systèmes Unix. S'il échoue, il passe
l'exception FileNotFoundException à son appelant.

p u

Cependant, le deuxième cas peut impliquer l'ouverture d'un fichier spécifié par l'utilisateur
sur la ligne de commande. Ici, une exception n'est pas justifiée, et le code semble
d iféer
Notez que l'appel FileInputStream peut toujours générer une exception, qui
la routine passe. Cependant, l'exception sera générée uniquement sous
circonstances vraiment exceptionnelles; simplement essayer d'ouvrir un fichier qui ne
exist générera un retour d'erreur conventionnel.

Astuce
Astuce 34
34

Utiliser les exceptions pour les problèmes exceptionnels

Pourquoi suggérons-nous cette approche des exceptions ? Eh bien, une exception


représente un transfert de contrôle immédiat et non local - c'est une sorte de
goto en cascade. Les programmes qui utilisent des exceptions dans le cadre de leur fonctionnement normal
traitement souffrent de tous les problèmes de lisibilité et de maintenabilité des
code classique des spaghettis. Ces programmes cassent l'encapsulation : routines et
leurs appelants sont plus étroitement couplés via la gestion des exceptions.

Les
Les gestionnaires
gestionnaires d'erreurs
d'erreurs sont
sont une
une alternative
alternative

Un gestionnaire d'erreurs est une routine appelée lorsqu'une erreur est détectée. Toi
peut enregistrer une routine pour gérer une catégorie spécifique d'erreurs. Quand l'un de
ces erreurs se produisent, le gestionnaire sera appelé.

Il y a des moments où vous voudrez peut-être utiliser des gestionnaires d'erreurs, soit au lieu de
ou à côté des exceptions. De toute évidence, si vous utilisez un langage tel que C,
qui ne prend pas en charge les exceptions, c'est l'une de vos quelques autres options (voir
le défi à la page suivante). Cependant, les gestionnaires d'erreurs peuvent parfois être
utilisé même dans les langages (tels que Java) qui ont une bonne gestion des exceptions
schéma intégré.

Considérez la mise en œuvre d'une application client-serveur, en utilisant Java


Fonction RMI (Remote Method Invocation). En raison de la façon dont le RMI est
mis en œuvre, chaque appel à une routine distante doit être prêt à gérer un
RemoteException. L'ajout de code pour gérer ces exceptions peut devenir
fastidieux, et signifie qu'il est difficile d'écrire du code qui fonctionne avec les deux
routines locales et distantes. Une solution de contournement possible consiste à envelopper votre télécommande
objets dans une classe qui n'est pas distante. Cette classe implémente alors une erreur
interface de gestion, permettant au code client d'enregistrer une routine à appeler
lorsqu'une exception distante est détectée.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Les programmes morts ne mentent pas

Défis
Défis

• • Les langages qui ne prennent pas en charge les exceptions ont souvent d'autres
transfert non local du mécanisme de contrôle (C a longjmp/setjmp, pour
exemple). Considérez comment vous pourriez implémenter une sorte d'ersatz
mécanisme d'exception utilisant ces facilités. Quels sont les bénéfices
et périls ? Quelles mesures spéciales devez-vous prendre pour vous assurer que
les ressources ne sont pas orphelines ? Est-il judicieux d'utiliser ce type de
solution chaque fois que vous codez en C?

Des
Des exercices
exercices
21.
21. Lors de la conception d'une nouvelle classe de conteneur, vous identifiez les éléments suivants

conditions d'erreur possibles :

1. 1. Pas de mémoire disponible pour un nouvel élément dans la routine d'ajout


2. 2. Entrée demandée introuvable dans la routine d'extraction
3. 3. pointeur nul passé à la routine d'ajout

Comment chacun doit-il être manipulé ? Si une erreur est générée, si un


l'exception doit-elle être déclenchée ou la condition doit-elle être ignorée ?

Comment
Comment équilibrer
équilibrer les
les ressources
ressources

« Je t'ai mis au monde, disait mon père », et je peux t'emmener


dehors. Cela ne fait aucune différence pour moi. Je vais juste en faire un autre comme toi."

Bill
Bill Cosby,
Cosby, Paternité
Paternité

Nous gérons tous des ressources à chaque fois que nous codons : mémoire, transactions, threads,
mouches, minuteries - toutes sortes de choses avec une disponibilité limitée. La plupart du temps,
l'utilisation des ressources suit un schéma prévisible : vous allouez la ressource, utilisez
puis désallouez-le.

Cependant, de nombreux développeurs n'ont pas de plan cohérent pour faire face à
allocation et désallocation des ressources. Alors laissez-nous vous suggérer une astuce simple :

Astuce
Astuce 35
35

Finissez ce que vous commencez

Cette astuce est facile à appliquer dans la plupart des cas. Cela signifie simplement que le
la routine ou l'objet qui alloue une ressource doit être responsable de
le désaffecter. Voyons comment cela s'applique en regardant un exemple de certains
mauvais code - une application qui ouvre un fichier, lit les informations client
à partir de celui-ci, met à jour un champ et réécrit le résultat. Nous avons éliminé l'erreur
am pni

ov di
À première vue, la routine updateCustomer semble plutôt bonne. Il semble
mettre en œuvre la logique dont nous avons besoin - lecture d'un enregistrement, mise à jour du solde,
et réécrire l'enregistrement. Cependant, cette propreté cache une grande
problème. Les routines readCustomer et writeCustomer sont étroitement couplés [3]

— ils partagent la variable globale cFile.readCustomer ouvre le fichier et


stocke le pointeur de fichier dans cFile, et writeCustomer utilise ce pointeur stocké
pour fermer le fichier lorsqu'il est terminé. Cette variable globale n'apparaît même pas dans
le routine updateCustomer.

[3] Pour une discussion sur les dangers du code couplé, voir Decoupling and the Law of Demeter .

Pourquoi est-ce mauvais ? Considérons le malheureux programmeur de maintenance


à qui on dit que la spécification a changé - l'équilibre devrait être
mis à jour uniquement si la nouvelle valeur n'est pas négative. Elle va à la source et
changements
u p

} }

Tout semble correct lors des tests. Cependant, lorsque le code entre en production,
il s'effondre après plusieurs heures, se plaignant d'un trop grand nombre de fichiers ouverts. Parce que
writeBalance n'est pas appelé dans certaines circonstances, le fichier n'est pas
se fermer.

Une très mauvaise solution à ce problème serait de traiter le cas particulier de


u p

Cela résoudra le problème - le fichier sera désormais fermé quel que soit le nouveau
équilibre,
le Global mais le correctif
cFichier. signifie
On tombe dansdésormais que
un piège, et lestrois routines
choses vontsont couplées via
commencer
descente rapide si nous continuons sur ce parcours.

Le conseil Finissez ce que vous commencez nous dit que, idéalement, la routine qui alloue
une ressource devrait aussi le libérer. Nous pouvons l'appliquer ici en refactorisant le code
lég èer

ov di

Maintenant, toute la responsabilité du fichier est dans la routine updateCustomer. Il


ouvre le fichier et (finissant ce qu'il commence) le ferme avant de quitter. Le
la routine équilibre l'utilisation du fichier : l'ouverture et la fermeture sont au même endroit,
et il est évident que pour chaque ouverture il y aura une clôture correspondante.
La refactorisation supprime également une variable globale laide.

Allocations
Allocations d'imbrication
d'imbrication

Le modèle de base pour l'allocation des ressources peut être étendu pour les routines qui
besoin de plus d'une ressource à la fois. Il n'y a plus que deux
suggestions:

1. 1. Libérez les ressources dans l'ordre inverse de celui dans lequel vous
les allouer. De cette façon, vous n'aurez pas de ressources orphelines si une ressource
contient des références à un autre.
2. 2. Lors de l'allocation du même ensemble de ressources à différents endroits
votre code, attribuez-les toujours dans le même ordre. Cela réduira
la possibilité d'un blocage. (Si le processus A revendique la ressource1 et est
sur le point de réclamer la ressource2, tandis que le processus B a réclamé la ressource2 et
essaie d'obtenirressource1, les deux processus attendront indéfiniment.)

Peu importe le type de ressources que nous utilisons : transactions,


mémoire, fichiers, threads, fenêtres - le modèle de base s'applique : quiconque
alloue une ressource devrait être responsable de la désallouer. Cependant, dans
certaines langues, nous pouvons développer davantage le concept.

Objets
Objets et
et exceptions
exceptions

L'équilibre entre allocations et désallocations rappelle un


constructeur et destructeur de la classe. La classe représente une ressource, la
constructeur vous donne un objet particulier de ce type de ressource, et le
destructor le supprime de votre portée.

Si vous programmez dans un langage orienté objet, vous le trouverez peut-être


utile pour encapsuler des ressources dans des classes. Chaque fois que vous avez besoin d'un
type de ressource, vous instanciez un objet de cette classe. Quand l'objet va
hors de portée, ou est récupéré par le ramasse-miettes, le destructeur de l'objet
libère ensuite la ressource enveloppée.

Cette approche présente des avantages particuliers lorsque vous travaillez avec des langues
comme C++, où les exceptions peuvent interférer avec la désallocation des ressources.

Équilibrage
Équilibrage et
et exceptions
exceptions

Les langages qui prennent en charge les exceptions peuvent compliquer la désallocation des ressources.
Si une exception est levée, comment garantissez-vous que tout ce qui est alloué
avant l'exception est rangé? La réponse dépend dans une certaine mesure de
la langue.

Équilibrage
Équilibrage des
des ressources
ressources avec
avec des
des exceptions
exceptions C++
C++

C++ prend en charge un mécanisme d'exception try…catch. Malheureusement, cela signifie


qu'il y a toujours au moins deux chemins possibles lors de la sortie d'une routine
q u

Notez que le nœud que nous créons est libéré à deux endroits—une fois dans la routine
chemin de sortie normal et une fois dans le gestionnaire d'exceptions. C'est une évidence
violation du principe DRY et un problème de maintenance en attente de
arriver.

Cependant, nous pouvons utiliser la sémantique de C++ à notre avantage. Objets locaux
sont automatiquement détruits en sortant de leur bloc englobant. Ce
nous donne quelques options. Si les circonstances le permettent, nous pouvons changer "n"
d 'u
Ici, nous nous appuyons sur C++ pour gérer la destruction de l'objet Node
automatiquement, qu'une exception soit levée ou non.

Si le passage d'un pointeur n'est pas possible, le même effet peut être obtenu
en enveloppant la ressource (dans ce cas, oPun

Désormais, la classe wrapper, NodeResource, garantit que lorsque ses objets sont
détruits les nœuds correspondants sont également détruits. Pour plus de commodité, le
wrapper fournit un opérateur de déréférencement
->, afin que ses utilisateurs puissent accéder
directement les champs de l'objet Node contenu.

Parce que cette technique est si utile, la bibliothèque C++ standard fournit la
classe de modèle auto_ptr, qui vous donne des wrappers automatiques pour
o b

Équilibrage
Équilibrage des
des ressources
ressources en
en Java
Java

Contrairement à C++, Java implémente une forme paresseuse de destruction automatique d'objets.
Les objets non référencés sont considérés comme candidats à la récupération de place,
et leur méthode finalize sera appelée si jamais la collecte des ordures
les réclamer. Bien qu'il s'agisse d'une commodité pour les développeurs, qui n'obtiennent plus le
responsable de la plupart des fuites de mémoire, il est difficile d'implémenter des ressources
nettoyage à l'aide du schéma C++. Heureusement, les concepteurs de Java
la langue a judicieusement ajouté une fonctionnalité de langue pour compenser,
e le
clause. Lorsqu'un Le bloc try contient une clause finally, le code de cette clause est
garantie d'être exécutée si une instruction du bloc try est exécutée. Il
n'a pas d'importance si une exception est levée (ou même si le code dans le
try block exécute un return )—le code de la clause finally sera exécuté.
C e
} }

La routine utilise un fichier temporaire, que nous voulons supprimer, quel que soit
comment la routine se termine.Le bloc
Le finally nous permet d'exprimer cela de manière concise.

Lorsque
Lorsque vous
vous ne
ne pouvez
pouvez pas
pas équilibrer
équilibrer les
les ressources
ressources

Il y a des moments où le modèle d'allocation des ressources de base n'est tout simplement pas
approprié. Généralement, cela se trouve dans les programmes qui utilisent des données dynamiques
structures. Une routine allouera une zone de mémoire et la reliera à
une structure plus grande, où il peut rester pendant un certain temps.

L'astuce ici est d'établir un invariant sémantique pour l'allocation de mémoire.


Vous devez décider qui est responsable des données dans un ensemble de données agrégées
structure. Que se passe-t-il lorsque vous libérez la structure de niveau supérieur ? Toi
ont trois options principales :

1. 1. La structure supérieure est également chargée de libérer


sous-structures qu'il contient. Ces structures récursivement
supprimer les données qu'ils contiennent, etc.
2. 2. La structure de niveau supérieur est simplement désallouée. Toutes structures
vers lesquels il pointe (qui ne sont pas référencés ailleurs) sont orphelins.
3. 3. La structure racine refuse de se désallouer si elle contient
toutes les sous-structures.

Le choix ici dépend des circonstances de chaque donnée individuelle


structure. Cependant, vous devez le rendre explicite pour chacun et implémenter
votre décision de manière cohérente. La mise en œuvre de l'une de ces options dans un
un langage procédural tel que C peut être un problème : structures de données
eux-mêmes ne sont pas actifs. Notre préférence dans ces circonstances est d'écrire
un module pour chaque grande structure qui fournit une allocation standard et
facilités de désaffectation pour cette structure. (Ce module peut également fournir
fonctionnalités telles que l'impression de débogage, la sérialisation, la désérialisation et
crochets de traversée.)

Enfin, si le suivi des ressources devient difficile, vous pouvez écrire votre propre
forme de ramasse-miettes automatique limité en implémentant une référence
schéma de comptage sur vos objets alloués dynamiquement. Le livre Plus
Effective C++ [ Mey96 ] consacre une section à ce sujet.

Vérification
Vérification du
du solde
solde

Parce que les programmeurs pragmatiques ne font confiance à personne, y compris à nous-mêmes, nous nous sentons
que c'est toujours une bonne idée de construire du code qui vérifie réellement que

les ressources sont en effet libérées de manière appropriée. Pour la plupart des applications, cela
signifie normalement produire des emballages pour chaque type de ressource, et utiliser
ces wrappers pour garder une trace de toutes les allocations et désallocations. A certains
points dans votre code, la logique du programme dictera que les ressources seront
dans un certain état : utilisez les emballages pour vérifier cela.

Par exemple, un programme de longue durée qui traite les demandes sera probablement
avoir un seul point au sommet de sa boucle de traitement principale où il attend
la prochaine demande d'arriver. C'est un bon endroit pour s'assurer que la ressource
l'utilisation n'a pas augmenté depuis la dernière exécution de la boucle.

A un niveau inférieur, mais non moins utile, vous pouvez investir dans des outils qui (parmi
d'autres choses) vérifiez vos programmes en cours d'exécution pour les fuites de mémoire. Purifier
( http://www.rational.com ) et Insure++ ( http://www.parasoft.com ) sont
choix populaires.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Conception par contrat


• • Programmation affirmée
• • Le découplage et la loi de Déméter

Défis
Défis

• • Bien qu'il n'existe aucun moyen garanti de s'assurer que vous


ressources toujours gratuites, certaines techniques de conception, lorsqu'elles sont appliquées
systématiquement, aidera. Dans le texte, nous avons discuté de la façon dont l'établissement d'un
invariant sémantique pour les principales structures de données pourrait diriger la mémoire
décisions de désaffectation. Considérez comment la conception
, pourrait
paraider
contrat
affiner cette idée.

Des
Des exercices
exercices

22. C
22. e
après avoir libéré la mémoire à laquelle il fait référence. Pourquoi est-ce un bon
idée?

23.
23. Certains développeurs Java mettent un point d'honneur à définir une variable objet sur
NULL après avoir fini d'utiliser l'objet. Pourquoi est-ce une bonne idée ?

Chapitre 5. Plier ou casser

La vie ne s'arrête pas.

Le code que nous écrivons non plus. Afin de suivre l'actualité d'aujourd'hui
rythme de changement presque effréné, nous devons faire tout notre possible pour écrire du code
c'est aussi lâche—aussi flexible—que possible. Sinon, nous pourrions trouver notre code
devient rapidement obsolète ou trop fragile pour être réparé, et peut finalement être laissé
en retard dans la course folle vers l'avenir.

En Réversibilité , nous avons évoqué les périls des décisions irréversibles. Dans ce
chapitre, nous vous dirons comment prendre des décisions réversibles, afin que votre code puisse
rester flexible et adaptable face à un monde incertain.

Nous devons d'abord examiner le couplage, c'est-à-dire les dépendances entre les modules de code.
Dans Le découplage et la loi de Déméter, nous montrerons comment rester séparés
les concepts se séparent et diminuent le couplage.

Une bonne façon de rester flexible est d'écrire moins de code. Changer de code vous laisse
ouvert à la possibilité d'introduire de nouveaux bugs. La métaprogrammation va
expliquer comment déplacer complètement les détails du code, où ils peuvent être
changé plus facilement et en toute sécurité.
Dans Couplage
couplage. temporel, sur
Comptez-vous nousle examinerons
« tic » venant deux
avantaspects
le « tac du
» ? temps en relation avec
Pas si vous
veulent rester flexibles.

Un concept clé dans la création de code flexible est la séparation d'un modèle de données
à partir d'une vue ou d'une présentation de ce modèle. Nous découplerons les modèles de
vues dans C'est juste une vue.

Enfin, il existe une technique pour découpler encore plus les modules en
fournir un lieu de rencontre où les modules peuvent échanger des données de manière anonyme
et de manière asynchrone. C'est le sujet des tableaux noirs.

Armé de ces techniques, vous pouvez écrire du code qui "roulera avec le
coups de poing."

Le
Le découplage
découplage et
et la
la loi
loi de
de Déméter
Déméter

De bonnes clôtures font de bons voisins.

Robert
Robert Frost,
Frost, "Réparer
"Réparer le
le mur"
mur"

Dans Orthogoality et Design by Contract , nous avons suggéré d'écrire "timide"


le code est bénéfique. Mais "timide" fonctionne de deux manières : ne pas se révéler aux autres,
et n'interagissez pas avec trop de gens.

Les espions, les dissidents, les révolutionnaires, etc. sont souvent organisés en petits
groupes de personnes appelés cellules. Bien que les individus de chaque cellule puissent savoir
les uns des autres, ils n'ont aucune connaissance de ceux des autres cellules. Si une cellule est
découvert, aucune quantité de sérum de vérité ne révélera les noms des autres
à l'extérieur de la cellule. L'élimination des interactions entre les cellules protège tout le monde.

Nous pensons que c'est un bon principe à appliquer également au codage. Organiser
votre code dans des cellules (modules) et limitez l'interaction entre eux. Si
un module est alors compromis et doit être remplacé, l'autre
les modules devraient pouvoir continuer.

Minimiser
Minimiser le
le couplage
couplage

Qu'y a-t-il de mal à avoir des modules qui se connaissent les uns les autres ? Rien dans
principe - nous n'avons pas besoin d'être aussi paranoïaques que des espions ou des dissidents. Cependant,
vous devez faire attention au nombre d'autres modules avec lesquels vous interagissez
et, plus important encore, comment vous en êtes venu à interagir avec eux.

Supposons que vous rénoviez votre maison ou construisiez une maison à partir de zéro. UN
l'arrangement typique implique un "entrepreneur général". Vous embauchez le
l'entrepreneur pour faire le travail, mais l'entrepreneur peut ou non faire le
construction personnellement; le travail peut être offert à divers sous-traitants.
Mais en tant que client, vous n'êtes pas impliqué dans les relations avec les sous-traitants
directement - l'entrepreneur général suppose que cet ensemble de maux de tête sur votre
au nom de.

Nous aimerions suivre ce même modèle dans le logiciel. Lorsque nous demandons à un objet un
service particulier, nous aimerions que le service soit effectué en notre nom. Nous
ne voulons pas que l'objet nous donne un objet tiers que nous devons traiter
avec pour obtenir le service requis.

Par exemple, supposons que vous écriviez une classe qui génère un graphe de
données des enregistreurs scientifiques. Vous avez des enregistreurs de données répartis dans le monde entier ;
chaque objet enregistreur contient un objet de localisation donnant sa position et son heure
zone. Vous souhaitez permettre à vos utilisateurs de sélectionner un enregistreur et de tracer ses données, étiquetées
a ev
a

Mais maintenant, la routine de traçage est inutilement couplée à trois classes -


Sélection, enregistreur et emplacement. Ce style de codage de façon spectaculaire
augmente le nombre de classes dont notre classe dépend. Pourquoi est-ce un
mauvaise chose? Cela augmente le risque qu'un changement non lié ailleurs dans
le système affectera votre code. Par exemple, si Fred apporte une modification à
Emplacement tel qu'il ne contienne plus directement de fuseau horaire, vous devez
change aussi ton code.

Plutôt que de creuser vous-même une hiérarchie, demandez simplement ce que vous
b e

Nous avons ajouté une méthode à Selection pour obtenir le fuseau horaire en notre nom : le
la routine de traçage ne se soucie pas de savoir si le fuseau horaire provient du
Recorder directement, à partir d'un objet contenu dans Recorder, ou si
La sélection constitue un fuseau horaire entièrement différent. La routine de sélection, en
tourner, devrait probablement juste demander à l'enregistreur son fuseau horaire, le laissant jusqu'à
l'enregistreur pour l'obtenir à partir de son objet Location contenu.

Traverser directement les relations entre les objets peut rapidement conduire à une
explosion combinatoire [1] des relations de dépendance. Tu peux voir
symptômes de ce phénomène de plusieurs façons :

[1] Si n objets se connaissent tous, alors un changement sur un seul objet peut avoir pour résultat que les n - 1 autres objets ont besoin

changements.

1. 1. Grands projets C ou C++ où la commande pour lier un test unitaire est


plus long que le programme de test lui-même
2. 2. Modifications "simples" d'un module qui se propagent à travers
modules non liés dans le système
3. 3. Les développeurs qui ont peur de changer de code parce qu'ils ne le font pas
sûr de ce qui pourrait être affecté

Les systèmes avec de nombreuses dépendances inutiles sont très difficiles (et
coûteux) à entretenir et ont tendance à être très instables. Afin de garder le

dépendances au minimum, nous utiliserons la loi de Déméter pour concevoir notre


méthodes et fonctions.

La
La loi
loi de
de Déméter
Déméter pour
pour les
les fonctions
fonctions

La loi de Déméter pour les fonctions [ LH89 ] tente de minimiser le couplage


entre les modules d'un programme donné. Il essaie de vous empêcher de
accéder à un objet pour accéder aux méthodes d'un troisième objet. La loi est
résumé à la figure 5.1 à la page suivante.

Figure
Figure 5.1.
5.1. Loi
Loi de
de Déméter
Déméter pour
pour les
les fonctions
fonctions
En écrivant du code "timide" qui respecte au maximum la Loi de Déméter,
nous pouvons atteindre notre objectif :

Astuce
Astuce 36
36

Minimiser le couplage entre les modules

Cela
Cela fait-il
fait-il vraiment
vraiment une
une différence
différence ??

Bien que cela sonne bien en théorie, suivre la loi de Déméter est-il vraiment
aider à créer un code plus maintenable ?

Des études ont montré [ BBM96 ] que les classes en C++ avec des ensembles de réponses plus grands
sont plus sujettes aux erreurs que les classes avec des ensembles de réponses plus petits (une réponse
set est défini comme étant le nombre de fonctions directement invoquées par les méthodes de
la classe).

Parce que suivre la loi de Déméter réduit la taille de l'ensemble de réponses


dans la classe appelante, il s'ensuit que les classes conçues de cette manière seront également
ont tendance à avoir moins d'erreurs (voir] pour
[ URLplus
56 d'articles et d'informations sur
le projet Demeter).

L'utilisation de la loi de Déméter rendra votre code plus adaptable et robuste,


mais à un coût : en tant que « contractant général », votre module doit déléguer et
gérer directement tous les sous-traitants, sans impliquer les clients de
votre module. En pratique, cela signifie que vous écrirez un grand
nombre de méthodes wrapper qui transmettent simplement la requête à un
déléguer. Ces méthodes d'encapsulation imposeront à la fois un coût d'exécution et une
l'espace aérien, qui peut être important, voire prohibitif, dans certains
applications.

Comme pour toute technique, vous devez peser le pour et le contre pour votre
application particulière. Dans la conception de schéma de base de données, il est courant de
« dénormaliser » le schéma pour une amélioration des performances : violer le
règles de normalisation en échange de rapidité. Un compromis similaire peut être
fait ici aussi. En effet, en inversant la Loi de Déméter et en resserrant
en couplant plusieurs modules, vous pourrez réaliser un gain de performances important.
Tant qu'il est bien connu et acceptable que ces modules soient couplés,
ton dessin est bien.

Découplage physique

Dans cette section, nous nous intéressons en grande partie à la conception pour garder
choses logiquement découplées au sein des systèmes. Cependant, il y a
un autre type d'interdépendance qui devient très significatif à mesure que
les systèmes grandissent. Dans son livre Large-scale C++ software Design
[ Lak96 ], John Lakos aborde les questions entourant la
les relations entre les fichiers, les répertoires et les bibliothèques qui font
un système. Les grands projets qui ignorent ces conceptions physiques
les problèmes se terminent par des cycles de construction mesurés en jours et
des tests unitaires qui peuvent traîner dans tout le système en tant que code de support,
entre autres problèmes. M. Lakos soutient de manière convaincante que la logique
et la conception physique doivent aller de pair - que défaire le
les dommages causés à un grand corps de code par des dépendances cycliques sont
extrêmement difficile. Nous recommandons ce livre si vous êtes impliqué dans

développements à grande échelle, même si C++ n'est pas votre implémentation


langue.

Sinon, vous risquez de vous retrouver sur la voie d'un avenir fragile et inflexible.
Ou pas d'avenir du tout.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Orthogonalité
• • Réversibilité
• • Conception par contrat
• • Comment équilibrer les ressources
• • C'est juste une vue
• • Des équipes pragmatiques
• • Tests impitoyables

Défis
Défis

• • Nous avons expliqué comment l'utilisation de la délégation facilite l'obéissance


la loi de Déméter et donc de réduire le couplage. Cependant, écrire tout
des méthodes nécessaires pour transférer les appels vers les classes déléguées est ennuyeuse
et sujet aux erreurs. Quels sont les avantages et les inconvénients de
écrire un préprocesseur qui génère ces appels automatiquement ?
Ce préprocesseur doit-il être exécuté une seule fois ou doit-il être utilisé comme
partie de la construction?

Des
Des exercices
exercices

24.
24. Nous avons discuté du concept de découplage physique dans l'encadré sur le
page en regard. Lequel des en-têtes C++ suivants vole le plus étroitement
couplé au reste du système ?

personne1.h
personne1.h personne2.h
personne2.h ::

#icn d ul

c c al
p p rivé :

p p u
25.
25. Pour l'exemple ci-dessous et pour ceux des Exercices 26 et 27, déterminez
si les appels de méthode indiqués sont autorisés conformément à la loi de
Déméter. Ce premier est en Java .

p u

26.
26. Cet exemple est également en Java.

p u

27.
27. Cet exemple est en C++ .

ov di

Métaprogrammation
Métaprogrammation

Aucune quantité de génie ne peut vaincre une préoccupation pour le détail

La
La huitième
huitième loi
loi de
de Levy
Levy

Les détails gâchent notre code vierge, surtout s'ils changent fréquemment.
Chaque fois que nous devons entrer et changer le code pour tenir compte de certains
changement dans la logique commerciale, ou dans la loi, ou dans les goûts personnels de la direction
du jour, nous courons le risque de casser le système, d'introduire un nouveau
bogue.

Alors on dit "fini les détails !" Sortez-les du code. Pendant qu'on y est,
nous pouvons rendre notre code hautement configurable et "soft", c'est-à-dire facilement
adaptable aux changements.

Configuration
Configuration dynamique
dynamique

Tout d'abord, nous voulons rendre nos systèmes hautement configurables. Pas seulement des choses
tels que les couleurs de l'écran et le texte d'invite, mais des éléments profondément enracinés tels que
le choix des algorithmes, des produits de base de données, de la technologie middleware et
style d'interface utilisateur. Ces éléments doivent être implémentés en tant que configuration
options, pas par l'intégration ou l'ingénierie.

Astuce
Astuce 37
37
Configurez, n'intégrez pas

Utiliser des métadonnées pour décrire les options de configuration d'une application : réglage
paramètres, les préférences de l'utilisateur, le répertoire d'installation, etc.

Qu'est-ce que les métadonnées exactement ? À proprement parler, les métadonnées sont des données sur des données.
L'exemple le plus courant est probablement un schéma de base de données ou des données
dictionnaire. Un schéma contient des données qui décrivent les champs (colonnes) en termes
des noms, des longueurs de stockage et d'autres attributs. Tu devrais être capable de
accéder à ces informations et les manipuler comme vous le feriez pour toute autre donnée
la base de données.

Nous utilisons le terme dans son sens le plus large. Les métadonnées sont toutes les données qui décrivent
l'application - comment elle doit s'exécuter, quelles ressources elle doit utiliser, etc.
En règle générale, les métadonnées sont consultées et utilisées au moment de l'exécution, et non au moment de la compilation.
Vous utilisez des métadonnées tout le temps, du moins vos programmes le font. Supposez que vous
cliquez sur une option pour masquer la barre d'outils de votre navigateur Web. Le navigateur va
stocker cette préférence, sous forme de métadonnées, dans une sorte de base de données interne.

Cette base de données peut être dans un format propriétaire ou utiliser une norme
mécanisme. Sous Windows, soit un fichier d'initialisation (utilisant le
suffixe.ini ) ou des entrées dans le registre du système sont typiques. Sous Unix, le X
Le système de fenêtres fournit des fonctionnalités similaires à l'aide de l'application par défaut
des dossiers. Java utilise des fichiers de propriétés. Dans tous ces environnements, vous spécifiez un
clé pour récupérer une valeur. Alternativement, plus puissant et flexible
les implémentations de métadonnées utilisent un langage de script intégré (voir
Langues du domaine, pour plus de détails).

Le navigateur Netscape a en fait implémenté des préférences en utilisant à la fois


ces techniques. Dans la version 3, les préférences étaient enregistrées sous forme de clé/valeur simple
p a

uPl s

Applications
Applications basées
basées sur
sur les
les métadonnées
métadonnées

Mais nous voulons aller au-delà de l'utilisation de métadonnées pour de simples préférences. Nous voulons
pour configurer et piloter au maximum l'application via les métadonnées.
Notre objectif est de penser de manière déclarative (spécifiant ce qui doit être fait, pas comment)
et créer des programmes hautement dynamiques et adaptables. Nous le faisons en adoptant
une règle générale : programmer pour le cas général, et mettre les spécificités
ailleurs, en dehors de la base de code compilée.

Astuce
Astuce 38
38

Mettre des abstractions dans les détails du code dans les métadonnées

Il y a plusieurs avantages à cette approche :

• • Cela vous oblige à découpler votre conception, ce qui se traduit par une
programme flexible et adaptable.
• • Cela vous oblige à créer une conception abstraite plus robuste en
différer les détails - les différer complètement du programme.
• • Vous
peut pouvez personnaliser
également l'application
utiliser ce niveau sans la recompiler.
de personnalisation pour Toi
fournir des solutions de contournement faciles
pour les bogues critiques dans les systèmes de production en direct.

• • Les métadonnées peuvent être exprimées d'une manière beaucoup plus proche du
domaine problématique qu'un langage de programmation à usage général
pourrait être (voir Langues du domaine
).
• • Vous pouvez même être en mesure de mettre en œuvre plusieurs projets différents
utilisant le même moteur d'application, mais avec des métadonnées différentes.

Nous voulons différer la définition de la plupart des détails jusqu'au dernier moment, et laisser
les détails aussi doux - aussi faciles à changer - que possible. En élaborant une solution
qui nous permet d'apporter des changements rapidement, nous avons de meilleures chances de faire face
avec le flot de changements de direction qui submergent de nombreux projets (voir
Réversibilité ).

Logique
Logique métier
métier

Vous avez donc fait du choix du moteur de base de données une option de configuration, et
fourni des métadonnées pour déterminer le style de l'interface utilisateur. Pouvons-nous faire plus?
Certainement.

Parce que la politique et les règles commerciales sont plus susceptibles de changer que tout autre
aspect du projet, il est logique de les maintenir dans un cadre très flexible
format.

Par exemple, votre application d'achat peut inclure diverses informations d'entreprise
Stratégies. Peut-être que vous payez les petits fournisseurs en 45 jours et les grands en 90
jours. Faire les définitions des types de fournisseurs, ainsi que les périodes de temps
eux-mêmes, configurables. Profitez-en pour généraliser.

Peut-être que vous écrivez un système avec des exigences de flux de travail épouvantables.
Les actions démarrent et s'arrêtent selon des règles métier complexes (et changeantes).
Envisagez de les encoder dans une sorte de système basé sur des règles (ou expert),
intégré dans votre application. De cette façon, vous le configurerez en écrivant
règles, pas couper le code.

Une logique moins complexe peut être exprimée à l'aide d'un mini-langage, supprimant
besoin de recompiler et de redéployer lorsque l'environnement change. Regarde
à la page 58 pour un exemple.

Quand configurer

Comme mentionné dans Le pouvoir du texte brut , nous vous recommandons


représenter les métadonnées de configuration en texte brut - cela rend la vie
tellement plus facile.

Mais quand un programme doit-il lire cette configuration ? Beaucoup


les programmes n'analyseront ces éléments qu'au démarrage, ce qui est
malheureux. Si vous devez modifier la configuration, cela vous oblige à
pour redémarrer l'application. Une approche plus souple consiste à écrire
programmes qui peuvent recharger leur configuration pendant qu'ils sont en cours d'exécution.
Cette flexibilité a un coût : elle est plus complexe à mettre en œuvre.

Réfléchissez donc à la manière dont votre application sera utilisée : s'il s'agit d'une application de longue durée
processus serveur, vous voudrez fournir un moyen de relire et
appliquer les métadonnées pendant l'exécution du programme. Pour un petit client
Application graphique qui redémarre rapidement, vous n'en aurez peut-être pas besoin.

Ce phénomène n'est pas limité au code d'application. Nous avons tous été
ennuyé par les systèmes d'exploitation qui nous obligent à redémarrer lorsque nous
installer une application simple ou modifier un paramètre inoffensif.

Un
Un exemple
exemple :: Enterprise
Enterprise Java
Java Beans
Beans

Enterprise Java Beans (EJB) est un framework pour simplifier la programmation


dans un environnement distribué basé sur les transactions. Nous le mentionnons ici
parce que les EJB illustrent comment les métadonnées peuvent être utilisées à la fois pour configurer
applications et de réduire la complexité d'écriture du code.

Supposons que vous vouliez créer un logiciel Java qui participera à


transactions sur différentes machines, entre différents fournisseurs de bases de données,
et avec différents modèles de thread et d'équilibrage de charge.

La bonne nouvelle, c'est que vous n'avez pas à vous soucier de tout cela. Vous écrivez un
haricot—un objet autonome qui suit certaines conventions—et placez-le
dans un conteneur de grains qui gère une grande partie des détails de bas niveau sur votre
au nom de. Vous pouvez écrire le code d'un bean sans inclure aucune transaction
gestion des opérations ou des threads ; EJB utilise des métadonnées pour spécifier comment
les transactions doivent être traitées.

L'allocation de threads et l'équilibrage de charge sont spécifiés en tant que métadonnées pour le
service de transaction sous-jacent utilisé par le conteneur. Cette séparation
nous permet une grande flexibilité pour configurer dynamiquement l'environnement, à
Durée.

Le conteneur du bean peut gérer les transactions au nom du bean dans l'un des
plusieurs styles différents (y compris une option où vous contrôlez votre propre
commits et rollbacks). Tous les paramètres qui affectent le bean's
comportement sont spécifiés dans le descripteur de déploiement du bean, un
objet qui contient les métadonnées dont nous avons besoin.

Les systèmes distribués tels que les EJB ouvrent la voie à un nouveau monde de
systèmes configurables et dynamiques.

Configuration
Configuration coopérative
coopérative

Nous avons parlé des utilisateurs et des développeurs configurant des applications dynamiques.
Mais que se passe-t-il si vous laissez les applications se configurer mutuellement ?
qui s'adapte à son environnement ? Non planifié, impulsif
configuration de logiciels existants est un concept puissant.

Les systèmes d'exploitation se configurent déjà sur le matériel au démarrage,


et les navigateurs Web se mettent automatiquement à jour avec de nouveaux composants.

Vos applications plus volumineuses ont probablement déjà des problèmes de gestion
différentes versions de données et différentes versions de bibliothèques et d'exploitation
systèmes. Peut-être qu'une approche plus dynamique aidera.

N'écrivez
N'écrivez pas
pas Dodo-Code
Dodo-Code

Sans métadonnées, votre code n'est pas aussi adaptable ou flexible qu'il pourrait l'être. Est
c'est une mauvaise chose? Eh bien, ici dans le monde réel, les espèces qui ne s'adaptent pas
mourir.

Le dodo ne s'est pas adapté à la présence des humains et de leur bétail sur le
l'île Maurice, et s'est rapidement éteinte. [2] C'était la première
l'extinction documentée d'une espèce par l'homme.

[2] Cela n'a pas aidé que les colons battent à mort les oiseaux placides (lire stupides) avec des clubs de sport.
Ne laissez pas votre projet (ou votre carrière) prendre le chemin du dodo.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Orthogonalité
• • Réversibilité
• • Langues du domaine
• • La puissance du texte brut

Défis
Défis

• • Pour votre projet actuel, tenez compte de la part de l'application


peuvent être déplacés du programme lui-même vers les métadonnées. Quel serait

à quoi ressemble le "moteur" résultant ? Seriez-vous capable de le réutiliser


moteur dans le cadre d'une application différente ?

Des
Des exercices
exercices

28.
28. Laquelle des choses suivantes serait mieux représentée sous forme de code
au sein d'un programme, et lesquelles en externe comme métadonnées ?

1. 1. Affectation des ports de communication


2. 2. Un support d'éditeur pour la mise en évidence de la syntaxe de divers
langues
3. 3. Le support d'un éditeur pour différents périphériques graphiques
4. 4. Une machine d'état pour un parseur ou un scanner
5. 5. Exemples de valeurs et de résultats à utiliser dans les tests unitaires

Couplage
Couplage temporel
temporel

Qu'est-ce que le couplage temporel, demandez-vous peut-être. Il était temps.

Le temps est un aspect souvent ignoré des architectures logicielles. La seule fois
qui nous préoccupe, c'est le temps sur l'horaire, le temps qu'il nous reste jusqu'à ce que nous
navire, mais ce n'est pas de cela dont nous parlons ici. Au lieu de cela, nous parlons
sur le rôle du temps en tant qu'élément de conception du logiciel lui-même. Il y a
deux aspects du temps qui sont importants pour nous : la simultanéité (les choses
qui se passe en même temps) et l'ordre (les positions relatives des choses
à l'heure).

Nous n'abordons généralement pas la programmation avec l'un ou l'autre de ces aspects dans
esprit. Lorsque les gens s'assoient pour la première fois pour concevoir une architecture ou écrire un
programme, les choses ont tendance à être linéaires. C'est ainsi que la plupart des gens pensent—font
ceci et ensuite toujours faire cela. Mais penser de cette façon conduit à
couplage : couplage dans le temps. La méthode A doit toujours être appelée avant la méthode
B; un seul rapport peut être exécuté à la fois ; vous devez attendre que l'écran
redessiner avant que le clic sur le bouton ne soit reçu. Le tic doit arriver avant le tac.

Cette approche n'est pas très flexible, et pas très réaliste.

[3] et de penser à découpler à tout moment


Nous devons permettre la concurrence
ou ordonner les dépendances. Ce faisant, nous pouvons gagner en flexibilité et réduire tout
dépendances temporelles dans de nombreux domaines de développement : analyse de flux de travail,
architecture, conception et déploiement.
[3] Nous n'entrerons pas ici dans les détails de la programmation concurrente ou parallèle ; un bon manuel d'informatique devrait

couvrir les bases, y compris la planification, l'impasse, la famine, l'exclusion mutuelle/les sémaphores, etc.

Flux
Flux de
de travail
travail

Sur de nombreux projets, nous devons modéliser et analyser les flux de travail des utilisateurs comme
partie de l'analyse des besoins. Nous aimerions savoir ce qui peut arriver au
en même temps, et ce qui doit se passer dans un ordre strict. Une façon de faire est de
capturer leur description du flux de travail en utilisant une notation telle que l'UML
Diagramme d'activité.
[4]

[4] Pour plus d'informations sur tous les types de diagrammes UML, voir [ FS97 ].

Un diagramme d'activités est constitué d'un ensemble d'actions dessinées sous forme de cases arrondies.
La flèche quittant une action mène soit à une autre action (qui peut commencer
une fois la première action terminée) ou à une ligne épaisse appelée une synchronisation
bar. Une fois que toutes les actions menant à une barre de synchronisation sont terminées,
vous pouvez ensuite suivre les flèches qui quittent la barre. Une action sans
les flèches qui y mènent peuvent être lancées à tout moment.

Vous pouvez utiliser des diagrammes d'activité pour maximiser le parallélisme en identifiant
activités qui pourraient être réalisées en parallèle, mais qui ne le sont pas.

Astuce
Astuce 39
39

Analyser le flux de travail pour améliorer la simultanéité

Par exemple, dans notre projet blender (Exercice 17, page 119), les utilisateurs peuvent
décrivez d'abord leur flux de travail actuel comme suit.

1. 1. Ouvrir le mixeur
2. 2. Ouvrir le mélange de piña colada
3. 3. Mettre le mélange dans le mélangeur
4. 4. Mesurer 1/2 tasse de rhum blanc
5. 5. Verser le rhum
6. 6. Ajouter 2 tasses de glace
7. 7. Fermez le mélangeur
8. 8. Liquéfier pendant 2 minutes
9. 9. Ouvrir le mixeur
10. 10. Obtenez des lunettes
11. 11. Obtenez des parapluies roses
12. 12. Servir

Même s'ils décrivent ces actions en série, et peuvent même effectuer


en série, nous remarquons que beaucoup d'entre eux pourraient être exécutés en parallèle,
comme nous le montrons dans le diagramme d'activité de la Figure 5.2 à la page suivante.

Figure
Figure 5.2.
5.2. Diagramme
Diagramme d'activité
d'activité UML
UML :: faire
faire une
une piña
piña colada
colada
Il peut être révélateur de voir où les dépendances existent réellement. Dans ce
exemple, les tâches de niveau supérieur (1, 2, 4, 10 et 11) peuvent toutes se produire simultanément,
à l'avant. Les tâches 3, 5 et 6 peuvent se dérouler en parallèle plus tard.

Si vous participiez à un concours de fabrication de piña colada, ces optimisations pourraient


toute la différence.

Architecture
Architecture

Nous avons écrit un système de traitement des transactions en ligne (OLTP) en quelques années
il y a. Dans sa forme la plus simple, tout ce que le système avait à faire était de lire une demande et de traiter
la transaction par rapport à la base de données. Mais nous avons écrit un trois niveaux,
application distribuée multitraitement : chaque composant était un
entité indépendante qui fonctionnait en même temps que tous les autres composants. Alors que
cela ressemble à plus de travail, ce n'était pas : profiter du temps
le découplage a facilité l'écriture. Regardons de plus près ce projet.

Le système prend en charge les demandes d'un grand nombre de communications de données
lignes et traite les transactions par rapport à une base de données principale.

La conception répond aux contraintes suivantes :

• • Les opérations de base de données prennent un temps relativement long.


• • Pour chaque transaction, nous ne devons pas bloquer les services de communication
pendant le traitement d'une transaction de base de données.
• • Les performances de la base de données souffrent d'un trop grand nombre
séances.
• • Plusieurs transactions sont en cours simultanément sur chaque donnée
doubler.

La solution qui nous a donné les meilleures performances et l'architecture la plus propre
ressemblait à quelque chose comme . la figure 5.3

Figure
Figure 5.3.
5.3. Présentation
Présentation de
de l'architecture
l'architecture OLTP
OLTP

Chaque case représente un processus distinct ; les processus communiquent via le travail
files d'attente. Chaque processus d'entrée surveille une ligne de communication entrante, et
fait des requêtes au serveur d'application. Toutes les requêtes sont asynchrones : comme
dès que le processus d'entrée fait sa demande en cours, il revient à
surveiller la ligne pour plus de trafic. De même, le serveur d'application effectue
requêtes du processus de base de[5] et est averti lorsque la personne
données,
la transaction est terminée.

[5] Même si nous montrons la base de données comme une seule entité monolithique, ce n'est pas le cas. Le logiciel de base de données est partitionné en

plusieurs processus et threads client, mais cela est géré en interne par le logiciel de base de données et ne fait pas partie de notre

exemple.
Cet exemple montre également un moyen d'obtenir un équilibrage de charge rapide et sale entre
processus de consommation multiples : le modèle du consommateur affamé.

Dans un modèle consommateur affamé, vous remplacez le planificateur central par un


nombre de tâches de consommation indépendantes et une file d'attente de travail centralisée. Chaque

la tâche consommateur saisit un morceau de la file d'attente de travail et continue sur le


entreprise de le traiter. Au fur et à mesure que chaque tâche termine son travail, elle revient à la
file d'attente pour un peu plus. De cette façon, si une tâche particulière s'enlise, le
d'autres peuvent prendre le relais, et chaque composant individuel peut procéder à
son propre rythme. Chaque composant est temporellement découplé des autres.

Astuce
Astuce 40
40

Conception à l'aide de services

Au lieu de composants, nous avons vraiment créé des services, indépendants,


objets concurrents derrière des interfaces bien définies et cohérentes.

Conception
Conception pour
pour la
la simultanéité
simultanéité

L'acceptation croissante de Java en tant que plate-forme a exposé davantage de développeurs à


programmation multithread. Mais programmer avec des threads impose quelques
contraintes de conception - et c'est une bonne chose. Ces contraintes sont en fait
si utile que nous voulons les respecter chaque fois que nous programmons. Ça aidera
découplons notre code et combattons la programmation par coïncidence
.

Avec le code linéaire, il est facile de faire des suppositions qui conduisent à des erreurs
la programmation. Mais la concurrence vous oblige à réfléchir un peu
plus attentivement, vous n'êtes plus seul à la fête. Parce que les choses peuvent
se produisent maintenant au "même moment", vous pouvez soudainement voir des
dépendances.

Pour commencer, toutes les variables globales ou statiques doivent être protégées contre
accès simultané. C'est peut-être le bon moment de vous demander pourquoi vous avez besoin d'un
variable globale en premier lieu. De plus, vous devez vous assurer que
vous présentez des informations d'état cohérentes, quel que soit l'ordre des appels.
Par exemple, quand est-il valide d'interroger l'état de votre objet ? Si votre objet
est dans un état invalide entre certains appels, vous pouvez compter sur un
coïncidence que personne ne puisse appeler votre objet à ce moment-là.

Supposons que vous ayez un sous-système de fenêtrage où les widgets sont les premiers
créé puis affiché à l'écran en deux étapes distinctes. Vous n'êtes pas
autorisé à définir l'état dans le widget jusqu'à ce qu'il soit affiché. Selon la façon dont le
code est configuré, vous pouvez compter sur le fait qu'aucun autre objet ne peut utiliser
le widget créé jusqu'à ce que vous l'ayez affiché à l'écran.

Mais cela peut ne pas être vrai dans un système concurrent. Les objets doivent toujours être dans
un état valide lorsqu'il est appelé, et ils peuvent être appelés aux moments les plus difficiles.
Vous devez vous assurer qu'un objet est dans un état valide chaque fois qu'il pourrait
être appelé. Souvent, ce problème apparaît avec des classes qui définissent des
constructeur et routines d'initialisation (où le constructeur ne quitte pas
l'objet dans un état initialisé). En utilisant des invariants de classe, discutés dans
Conception par contrat, vous aidera à éviter ce piège.

Interfaces
Interfaces plus
plus propres
propres

Penser à la concurrence et aux dépendances ordonnées dans le temps peut vous conduire à
c o
qui décompose une chaîne en jetons.

[6] mais ce n'est pas le pire : regardez


La conception de strtok n'est pas thread-safe,
la dépendance temporelle. Vous devez faire le premier appel à strtok avec le
variable que vous voulez analyser, et tous les appels successifs
NULLavecà la
unplace. Si
vous passez dans unvaleur
non-NULL, il redémarre l'analyse sur ce tampon à la place.
Sans même tenir compte des threads, supposons que vous vouliez utiliser strtok pour
analyser deux chaînes distinctes en même temps :

[6] Il utilise des données statiques pour maintenir la position actuelle dans le tampon. Les données statiques ne sont pas protégées contre les

accès, il n'est donc pas thread-safe. De plus, cela encombre le premier argument que vous transmettez, ce qui peut conduire à de mauvais

s u

eL c
entre les appels. Vous devez utiliser strtok sur un seul tampon à la fois.

Maintenant, en Java, la conception d'un analyseur de chaînes doit être différente. Ce doit être
t ehr

StringTokenizer est une interface beaucoup plus propre et plus maintenable. Il


contient pas de surprises et ne causera pas de bogues mystérieux à l'avenir, car
strtok pourrait.

Astuce
Astuce 41
41

Toujours concevoir pour la simultanéité

Déploiement
Déploiement

Une fois que vous avez conçu une architecture avec un élément de concurrence, il
devient plus facile de penser à gérer de nombreux services concurrents : le
modèle devient omniprésent.
Vous pouvez maintenant être flexible quant à la manière dont l'application est déployée : autonome,
client-serveur ou n-tiers. En concevant votre système comme des services indépendants,
vous pouvez également rendre la configuration dynamique. En planifiant pour
simultanéité et découplage des opérations dans le temps, vous avez toutes ces
options, y compris l'option autonome, où vous pouvez choisir de ne pas être
concurrent.

Aller dans l'autre sens (essayer d'ajouter de la simultanéité à un non-concurrent


application) est beaucoup plus difficile. Si nous concevons pour permettre la concurrence, nous pouvons
répondre plus facilement aux exigences d'évolutivité ou de performances lorsque le temps
vient - et si le moment ne vient jamais, nous avons toujours l'avantage d'un nettoyeur
conception.

N'est-il pas temps?

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Conception par contrat


• • Programmation par coïncidence

Défis
Défis

• • Combien de tâches effectuez-vous en parallèle lorsque vous vous préparez


pour travailler le matin ? Pourriez-vous exprimer cela dans une activité UML
diagramme? Pouvez-vous trouver un moyen de vous préparer plus rapidement en
augmentation de la simultanéité ?

C'est
C'est juste
juste une
une vue
vue

Pourtant, un homme entend

Ce qu'il veut entendre

Et ignore le reste

La la la…

Simon
Simon et
et Garfunkel,
Garfunkel, "Le
"Le boxeur"
boxeur"

Dès le début, on nous apprend à ne pas écrire un programme en un seul gros morceau, mais
qu'il faut "diviser pour mieux régner" et séparer un programme en modules.
Chaque module a ses propres responsabilités ; en fait, une bonne définition d'un
module (ou classe) est qu'il a une seule responsabilité bien définie.

Mais une fois que vous séparez un programme en différents modules basés sur
responsabilité, vous avez un nouveau problème. A l'exécution, comment les objets parlent
l'un à l'autre ? Comment gérez-vous les dépendances logiques entre eux ?
Autrement dit, comment synchronisez-vous les changements d'état (ou les mises à jour des valeurs de données)
dans ces différents objets ? Cela doit être fait dans un environnement propre et flexible
manière - nous ne voulons pas qu'ils en sachent trop les uns sur les autres. Nous voulons
chaque module pour être comme l'homme dans la chanson et juste entendre ce qu'il veut
entendre.

Nous allons commencer par le concept d'événement. Un événement est tout simplement spécial
message qui dit "quelque chose d'intéressant vient de se passer" (intéressant, de
bien sûr, réside dans l'œil du spectateur). Nous pouvons utiliser des événements pour signaler des changements
dans un objet qui pourrait intéresser un autre objet.

L'utilisation d'événements de cette manière minimise le couplage entre ces objets.


l'expéditeur de l'événement n'a pas besoin d'avoir une connaissance explicite du
destinataire. En fait, il pourrait y avoir plusieurs récepteurs, chacun focalisé sur son
propre agenda (dont l'expéditeur est parfaitement inconscient).
Cependant, nous devons faire preuve de prudence dans l'utilisation des événements. Dans une première version
de Java, par exemple, une routine recevait tous les événements destinés à un
application particulière. Pas exactement la route vers un entretien facile ou
évolution.

Publier/S'abonner
Publier/S'abonner

Pourquoi est-il mauvais de pousser tous les événements à travers une seule routine ? Il viole
encapsulation d'objet - qu'une routine doit maintenant avoir intime
connaissance des interactions entre de nombreux objets. Il augmente également la
couplage—et nous essayons de réduire le couplage. Parce que les objets
eux-mêmes doivent également avoir connaissance de ces événements, vous êtes
va probablement violer le principe DRY, l'orthogonalité, et peut-être
même des sections de la Convention de Genève. Vous avez peut-être vu ce genre de
code - il est généralement dominé par un énorme
déclaration de cas ou multiway
si donc. Nous pouvons faire mieux.

Les objets doivent pouvoir s'enregistrer pour ne recevoir que les événements dont ils ont besoin, et
ne doivent jamais recevoir d'événements dont ils n'ont pas besoin. Nous ne voulons pas spammer nos
objets! Au lieu de cela, nous pouvons utiliser un protocole de publication/abonnement, illustré à l'aide de
le diagramme de séquence UML de la Figure 5.4 à la page suivante.
[7]

[7] Voir aussi le pattern Observer dans [ GHJV95 ] pour plus d'informations.

Figure
Figure 5.4.
5.4. Protocole
Protocole de
de publication/abonnement
publication/abonnement

Un diagramme de séquence montre le flux de messages entre plusieurs objets,


avec des objets disposés en colonnes. Chaque message est affiché sous la forme d'un
flèche de la colonne de l'expéditeur à la colonne du destinataire. Un astérisque dans le
label signifie que plusieurs messages de ce type peuvent être envoyés.

Si nous sommes intéressés par certains événements générés par un Editeur, tout ce que nous avons
faire est de nous enregistrer. Le L'éditeur garde une trace de tous les intéressés
Objets abonnés ; lorsque l'Éditeur génère un événement d'intérêt, il
appellera tour à tour chaque Abonné et l'informera que l'événement a
s'est produit.

Il existe plusieurs variations sur ce thème, reflétant d'autres


styles de communication. Les objets peuvent utiliser la publication/l'abonnement sur un peer-to-peer
base (comme nous l'avons vu ci-dessus); ils peuvent utiliser un "bus logiciel" où un centralisé
l'objet maintient la base de données des auditeurs et distribue les messages
de manière appropriée. Vous pourriez même avoir un schéma où les événements critiques deviennent
diffusée à tous les auditeurs, inscrits ou non. Une implémentation possible
d'événements dans un environnement distribué est illustré par l'événement CORBA
Service, décrit dans l'encadré de la page suivante.
Nous pouvons utiliser ce mécanisme de publication/abonnement pour implémenter un très
concept de conception important : la séparation d'un modèle des vues du
modèle. Commençons par un exemple basé sur une interface graphique, utilisant la conception Smalltalk dans
duquel ce concept est né.

Modèle
Modèle Vue
Vue Contrôleur
Contrôleur

Supposons que vous disposiez d'un tableur. En plus des chiffres de


la feuille de calcul elle-même, vous avez également un graphique qui affiche les nombres sous forme de
graphique à barres et une boîte de dialogue de total cumulé qui affiche la somme d'une colonne dans
la feuille de calcul.

Le service événementiel CORBA

Le service d'événement CORBA permet aux objets participants d'envoyer et


recevoir des notifications d'événements via un bus commun, le canal d'événements.
Le canal d'événements arbitre la gestion des événements et découple également
les producteurs d'événements des consommateurs d'événements. Il fonctionne de deux manières fondamentales :
pousser et tirer.

En mode push, les fournisseurs d'événements informent le canal de l'événement qu'un


événement s'est produit. La chaîne distribue alors automatiquement
cet événement à tous les objets client qui ont enregistré un intérêt.

En mode pull, les clients interrogent périodiquement le canal d'événements, qui en


tour interroge le fournisseur qui offre des données d'événement correspondant à la
demande.

Bien que le service d'événements CORBA puisse être utilisé pour mettre en œuvre toutes les
les modèles d'événements abordés dans cette section, vous pouvez également les afficher comme un
animal différent. CORBA facilite la communication entre les objets
écrit dans différents langages de programmation fonctionnant sur
machines dispersées géographiquement avec des architectures différentes.
Assis au sommet de CORBA, le service événementiel vous offre une manière découplée
d'interagir avec des applications du monde entier, écrites par des personnes
vous n'avez jamais rencontré, en utilisant des langages de programmation que vous préférez ne pas
savoir a propos.

Évidemment, nous ne voulons pas avoir trois copies distinctes des données. Alors on
créer un modèle - les données elles-mêmes, avec des opérations courantes pour les manipuler.
Ensuite, nous pouvons créer des vues séparées qui affichent les données de différentes manières :
sous forme de feuille de calcul, de graphique ou de zone de totaux. Chacune de ces vues peut
avoir son propre contrôleur. La vue graphique peut avoir un contrôleur qui permet
vous permet d'effectuer un zoom avant ou arrière, ou de vous déplacer autour des données, par exemple. Rien de tout cela
affecte les données elles-mêmes, juste cette vue.

C'est le concept clé derrière le Model-View-Controller (idiome MVC0 :


séparer le modèle à la fois de l'interface graphique qui le représente et des contrôles
qui gèrent la vue. [8]

[8] La vue et le contrôleur sont étroitement couplés, et dans certaines implémentations de MVC, la vue et le contrôleur sont un seul

composant.

Ce faisant, vous pouvez profiter de certaines possibilités intéressantes. Toi


peut prendre en charge plusieurs vues du même modèle de données. Vous pouvez utiliser
spectateurs sur de nombreux modèles de données différents. Vous pouvez même prendre en charge plusieurs
contrôleurs pour fournir des mécanismes d'entrée non traditionnels.

Astuce
Astuce 42
42

Séparer les vues des modèles


En desserrant le couplage entre le modèle et la vue/contrôleur, vous
achetez-vous beaucoup de flexibilité à faible coût. En fait, cette technique est l'une des
les moyens les plus importants de maintenir la réversibilité (voir Réversibilité ).

Arborescence
Arborescence Java
Java

Un bon exemple de conception MVC peut être trouvé dans le widget d'arborescence Java. Le
widget arbre (qui affiche un arbre cliquable et traversable) est en fait un ensemble de
plusieurs classes différentes organisées dans un modèle MVC.

Pour produire un widget arborescent entièrement fonctionnel, tout ce que vous avez à faire est de fournir un
source de données conforme à la Interface TreeModel. Votre code maintenant
devient le modèle de l'arbre.

La vue est créée par les classes TreeCellRenderer et TreeCellEditor,


qui peut être hérité et personnalisé pour fournir différentes couleurs,
polices et icônes dans le widget.JTree agit en tant que contrôleur pour l'arborescence
widget et fournit des fonctionnalités de visualisation générales.

Parce que nous avons découplé le modèle de la vue, nous simplifions la


beaucoup programmer. Vous n'avez pas à penser à programmer un
widget arbre plus. Au lieu de cela, vous fournissez simplement une source de données.

Supposons que le vice-président vienne vers vous et veuille une candidature rapide
qui lui permet de naviguer dans l'organigramme de l'entreprise, qui se tient dans
une ancienne base de données sur le mainframe. Il suffit d'écrire un wrapper qui prend le
données mainframe, les présente comme
TreeModel,
un et voilà : vous disposez d'un
widget d'arborescence navigable.

Maintenant, vous pouvez devenir fantaisiste et commencer à utiliser les classes de visualisation ; vous pouvez changer
comment les nœuds sont rendus et utilisez des icônes, des polices ou des couleurs spéciales. Quand le
VP revient et dit que les nouvelles normes d'entreprise dictent l'utilisation d'un
Icône tête de mort et os croisés pour certains employés, vous pouvez apporter les modifications
pour
TreeCellRenderer sans toucher à aucun autre code.

Au-delà
Au-delà des
des interfaces
interfaces graphiques
graphiques

Bien que MVC soit généralement enseigné dans le contexte du développement d'interfaces graphiques, il est
vraiment une technique de programmation à usage général. La vue est un
interprétation du modèle (peut-être un sous-ensemble) - il n'est pas nécessaire
graphique. Le contrôleur est davantage un mécanisme de coordination et ne
doivent être liés à n'importe quel type de périphérique d'entrée.

• • Modèle. Le modèle de données abstrait représentant l'objet cible.


Le modèle n'a aucune connaissance directe des vues ou des contrôleurs.
• • Voir. Une façon d'interpréter le modèle. Il souscrit aux changements de
le modèle et les événements logiques du contrôleur.
• • Manette. Un moyen de contrôler la vue et de fournir le modèle
avec de nouvelles données. Il publie des événements à la fois sur le modèle et sur la vue.

Prenons un exemple non graphique.


Le baseball est une institution unique. Où d'autre pouvez-vous apprendre de tels joyaux de
anecdotes car "c'est devenu le match le plus marqué joué un mardi, en
la pluie, sous des lumières artificielles, entre des équipes dont les noms commencent par un
voyelle?" Supposons que nous soyons chargés de développer un logiciel pour prendre en charge
ces annonceurs intrépides qui doivent consciencieusement rapporter les scores, les
les statistiques et les anecdotes.

De toute évidence, nous avons besoin d'informations sur le jeu en cours - les équipes qui jouent,
les conditions, le joueur au bâton, le score, etc. Ces faits forment notre
des modèles; ils seront mis à jour au fur et à mesure que de nouvelles informations arriveront (un lanceur est
changé, un joueur frappe, il commence à pleuvoir…).

Nous aurons alors un certain nombre d'objets de vue qui utilisent ces modèles. Une vue
peut rechercher des runs afin de pouvoir mettre à jour le score actuel. Un autre peut recevoir
notifications de nouveaux batteurs, et récupérer un bref résumé de leur
statistiques cumulées depuis le début de l'année. Un troisième spectateur peut regarder les données et vérifier
nouveaux records du monde. Nous pourrions même avoir un visualiseur de trivia, responsable de
venir avec ces faits étranges et inutiles qui ravissent le public.

Mais nous ne voulons pas inonder le pauvre présentateur avec toutes ces vues
directement. Au lieu de cela, chaque vue générera des notifications de
événements "intéressants", et laissez un objet de niveau supérieur planifier ce qui se passe
montré.[9]

[9] Le fait qu'un avion survole n'est probablement pas intéressant à moins que ce ne soit le 100e avion à survoler cette nuit-là.

Ces objets spectateurs sont soudainement devenus des modèles pour le niveau supérieur
objet, qui lui-même pourrait alors être un modèle pour différents visualiseurs de mise en forme.
Un visualiseur de mise en forme peut créer le script de téléprompteur pour le
annonceur, un autre pourrait générer des sous-titres vidéo directement sur le satellite
liaison montante, un autre peut mettre à jour les pages Web du réseau ou de l'équipe (voir
Figure 5.5 ).

Figure
Figure 5.5.
5.5. Reportage
Reportage de
de baseball,
baseball, les
les téléspectateurs
téléspectateurs s'abonnent
s'abonnent aux
aux modèles.
modèles.

Ce type de réseau de visionneuses de modèles est une conception courante (et précieuse)
technique. Chaque lien dissocie les données brutes des événements qui ont créé
it—chaque nouveau spectateur est une abstraction. Et parce que les relations sont un
réseau (pas seulement une chaîne linéaire), nous avons beaucoup de flexibilité. Chaque modèle
peut avoir plusieurs visualiseurs et un visualiseur peut fonctionner avec plusieurs modèles.

Dans les systèmes avancés tels que celui-ci, il peut être pratique d'avoir un débogage
vues—vues spécialisées qui vous montrent des détails détaillés du modèle.
L'ajout d'une installation pour tracer des événements individuels peut être un gain de temps important car
Bien.

Toujours
Toujours en
en couple
couple (après
(après toutes
toutes ces
ces années)
années)

Malgré la diminution du couplage que nous avons obtenue, les auditeurs et les événements
les générateurs (abonnés et éditeurs) ont encore une certaine connaissance de chacun
autre. En Java, par exemple, ils doivent se mettre d'accord sur une interface commune
définitions et conventions d'appel.

Dans la section suivante, nous examinerons les moyens de réduire encore plus le couplage en
en utilisant un formulaire de publication et d'abonnement où aucun des participants n'a besoin
se connaissent ou s'appellent directement.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Orthogonalité
• • Réversibilité
• • Le découplage et la loi de Déméter

• • Tableaux noirs
• • Tout est écrit

Des
Des exercices
exercices

29.
29. Supposons que vous disposiez d'un système de réservation de compagnie aérienne qui inclut le
c o

Si vous ajoutez un passager à la liste d'attente, il sera mis sur le vol


automatiquement lorsqu'une place se libère.

Il y a un énorme travail de reportage qui passe par la recherche de


vols surréservés ou complets pour suggérer quand des vols supplémentaires pourraient être
programmé. Cela fonctionne bien, mais cela prend des heures à fonctionner.

On aimerait avoir un peu plus de souplesse dans le traitement des listes d'attente
passagers, et nous devons faire quelque chose à propos de ce gros rapport—il
prend trop de temps à courir. Utilisez les idées de cette section pour reconcevoir ce
interface.

Tableaux
Tableaux noirs
noirs

L'écriture est sur le mur...

Vous n'associez peut-être généralement pas l'élégance aux détectives de la police, imaginant
à la place une sorte de cliché de beignet et de café. Mais considérez comment
les détectives peuvent utiliser un tableau noir pour coordonner et résoudre un meurtre
enquête.

Supposons que l'inspecteur en chef commence par installer un grand tableau noir dans le
salle de conférence. Il écrit dessus une seule question :

H. D UMPTY (HOMME, OEUF) : ACCIDENT OU MEURTRE ?


Humpty est-il vraiment tombé ou a-t-il été poussé ? Chaque détective peut faire
contributions à ce mystère de meurtre potentiel en ajoutant des faits, des déclarations
des témoins, toute preuve médico-légale qui pourrait survenir, etc. Comme le
les données s'accumulent, un détective peut remarquer une connexion et publier
observation ou spéculation aussi. Ce processus se poursuit, à travers tous les quarts de travail,
avec de nombreuses personnes et agents différents, jusqu'à ce que l'affaire soit close. Un échantillon
tableau noir est illustré à la Figure 5.6 à la page suivante.

Illustration
Illustration 5.6.
5.6. Quelqu'un
Quelqu'un aa trouvé
trouvé un
un lien
lien entre
entre le
le jeu
jeu d'Humpty
d'Humpty

les
les dettes
dettes et
et les
les journaux
journaux téléphoniques.
téléphoniques. Peut-être
Peut-être recevait-il
recevait-il un
un téléphone
téléphone menaçant
menaçant

appels.
appels.

Certaines caractéristiques clés de l'approche du tableau noir sont :

• • Aucun des détectives n'a besoin de connaître l'existence d'un


autre détective - ils regardent le tableau pour de nouvelles informations et ajoutent
leurs découvertes.
• • Les détectives peuvent être formés dans différentes disciplines, avoir
différents niveaux d'éducation et d'expertise, et peuvent même ne pas travailler dans
la même enceinte. Ils partagent le désir de résoudre l'affaire, mais c'est
tous.
• • Différents détectives peuvent aller et venir au cours de la
processus, et peut travailler des quarts de travail différents.
• • Il n'y a aucune restriction sur ce qui peut être placé sur le
tableau noir. Il peut s'agir d'images, de phrases, de preuves matérielles, etc.
sur.

Nous avons travaillé sur un certain nombre de projets qui impliquaient un flux de travail ou
processus de collecte de données distribuées. Avec chacun, concevoir une solution autour
un simple modèle de tableau noir nous a donné une métaphore solide avec laquelle travailler : tous les
les fonctionnalités énumérées ci-dessus utilisant des détectives sont tout aussi applicables aux objets et
module de codes.

Un système de tableau noir nous permet de découpler nos objets les uns des autres
complètement, offrant un forum où les consommateurs et les producteurs de connaissances
peut échanger des données de manière anonyme et asynchrone. Comme vous pouvez le deviner,
cela réduit également la quantité de code que nous devons écrire.

Implémentations
Implémentations du
du tableau
tableau noir
noir

Les systèmes de tableau noir informatisés ont été inventés à l'origine pour être utilisés dans
applications d'intelligence artificielle où les problèmes à résoudre étaient
vaste et complexe—reconnaissance de la parole, raisonnement basé sur les connaissances
systèmes, et ainsi de suite.

Systèmes distribués modernes de type tableau noir tels que JavaSpaces et T


Espaces [ URL 50, URL 25 ] sont basés sur un modèle de paires clé/valeur d'abord
popularisé à Linda [ CG90 ], où le concept était connu sous le nom d'espace tuple.

Avec ces systèmes, vous pouvez stocker des objets Java actifs, et pas seulement des données, sur
le tableau noir, et les récupérer par appariement partiel des champs (via
modèles et caractères génériques) ou par sous-types. Par exemple, supposons que vous ayez un
taperAuteur, qui est un sous-type de Personne. Vous pouvez rechercher un tableau noir
c o
valeur de "Shakespeare". Vous auriez Bill Shakespeare l'auteur, mais pas
Fred Shakespeare le jardinier.

Les principales opérations dans JavaSpaces sont :

Nom
Nom Fonction
Fonction
lire Rechercher et récupérer des données de l'espace.
écrire Mettre un élément dans l'espace.
take Semblable à read, mais supprime également l'élément de l'espace.
notifier Configurez une notification pour qu'elle se produise chaque fois qu'un objet correspondant au modèle est écrit.

T Spaces prend en charge un ensemble similaire d'opérations, mais avec des noms et des
sémantique légèrement différente. Les deux systèmes sont construits comme un produit de base de données ;
ils fournissent des opérations atomiques et des transactions distribuées pour garantir que les données
intégrité.

Puisque nous pouvons stocker des objets, nous pouvons utiliser un tableau noir pour concevoir des algorithmes
basé sur un flux d'objets, pas seulement de données. C'est comme si nos détectives pouvaient épingler
les gens au tableau noir - les témoins eux-mêmes, pas seulement leurs déclarations.
N'importe qui peut poser des questions à un témoin dans la poursuite de l'affaire, poster le
transcription, et déplacez ce témoin vers une autre zone du tableau noir, où

il pourrait répondre différemment (si vous permettez au témoin de lire le


tableau noir aussi).

Un grand avantage de systèmes comme ceux-ci est que vous avez un seul,
interface cohérente avec le tableau noir. Lors de la construction d'un
application distribuée, vous pouvez passer beaucoup de temps à créer des
Appels d'API pour chaque transaction et interaction distribuée dans le système.
Avec l'explosion combinatoire des interfaces et des interactions, le projet
peut vite devenir un cauchemar.

Organisation de votre tableau noir

Lorsque les détectives travaillent sur de grosses affaires, le tableau noir peut être-
deviennent encombrés et il peut devenir difficile de localiser les données sur le
conseil. La solution est de partitionner le tableau noir et de commencer à
organiser les données sur le tableau noir en quelque sorte.

Différents systèmes logiciels gèrent ce partitionnement dans différents


façons; certains utilisent des zones assez plates ou des groupes d'intérêts, tandis que d'autres
adopter une structure arborescente plus hiérarchisée.

Le style de programmation tableau noir élimine le besoin d'autant de


interfaces, ce qui rend le système plus élégant et cohérent.

Exemple
Exemple d'application
d'application

Supposons que nous écrivions un programme pour accepter et traiter une hypothèque ou un prêt
applications. Les lois qui régissent ce domaine sont odieusement complexes, avec
les gouvernements fédéral, étatiques et locaux ont tous leur mot à dire. Le prêteur doit
prouver qu'ils ont divulgué certaines choses et doivent demander certaines
informations - mais ne doit pas poser certaines autres questions, et ainsi de suite, et ainsi de suite
sur.

Au-delà des miasmes du droit applicable, nous avons également les problèmes suivants
à affronter.

• • Il n'y a aucune garantie sur l'ordre dans lequel les données arrivent. Pour
Par exemple, les requêtes pour une vérification de crédit ou une recherche de titre peuvent prendre un
beaucoup de temps, tandis que des éléments tels que le nom et l'adresse
peut être disponible immédiatement.
• • La collecte de données peut être effectuée par différentes personnes, distribuées
dans différents bureaux, dans différents fuseaux horaires.

• • Certaines collectes de données peuvent être effectuées automatiquement par d'autres


systèmes. Ces données peuvent également arriver de manière asynchrone.
• • Néanmoins, certaines données peuvent encore dépendre d'autres données.
Par exemple, vous ne pourrez peut-être pas lancer la recherche de titre pour une voiture
jusqu'à ce que vous obteniez une preuve de propriété ou d'assurance.
• • L'arrivée de nouvelles données peut soulever de nouvelles questions et politiques.
Supposons que la vérification de crédit revienne avec un rapport moins qu'élogieux ;
maintenant vous avez besoin de ces cinq formulaires supplémentaires et peut-être d'un échantillon de sang.

Vous pouvez essayer de gérer toutes les combinaisons et circonstances possibles en utilisant un
système de flux de travail. De nombreux systèmes de ce type existent, mais ils peuvent être complexes et
programmeur intensif. Au fur et à mesure que les réglementations changent, le flux de travail doit être
réorganisé : les personnes peuvent être amenées à modifier leurs procédures et
le code devra peut-être être réécrit.

Un tableau noir, associé à un moteur de règles qui encapsule les


exigences légales, est une solution élégante aux difficultés rencontrées ici.
L'ordre d'arrivée des données n'a pas d'importance : lorsqu'un fait est publié, il peut déclencher la
règles appropriées. La rétroaction est également facilement gérée : la sortie de n'importe quel ensemble
de règles peuvent s'afficher sur le tableau noir et provoquer le déclenchement d'encore plus
Règles applicables.

Astuce
Astuce 43
43

Utiliser des tableaux noirs pour coordonner le flux de travail

Nous pouvons utiliser le tableau noir pour coordonner des faits et des agents disparates, tandis que
tout en maintenant l'indépendance et même l'isolement des participants.

Vous pouvez obtenir les mêmes résultats avec plus de méthodes de force brute, de
bien sûr, mais vous aurez un système plus fragile. Quand ça casse, tout le roi
les chevaux et tous les hommes du roi pourraient ne plus faire fonctionner votre programme.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • La puissance du texte brut


• • C'est juste une vue

Défis
Défis
• • Utilisez-vous des systèmes de tableau noir dans le monde réel—le message
tableau près du réfrigérateur, ou le grand tableau blanc au travail ? Quoi
les rend efficaces ? Les messages sont-ils déjà affichés avec un
format? Est-ce que ça importe?

Des
Des exercices
exercices

30.
30. Pour chacune des applications suivantes, un système de tableau noir serait-il
approprié ou non ? Pourquoi?

1. 1. Traitement d'images. Vous aimeriez avoir un certain nombre de parallèles


processus saisissent des morceaux d'une image, les traitent et placent le
morceau terminé en arrière.
2. 2. Calendrier de groupe. Vous avez des gens dispersés à travers
le globe, dans différents fuseaux horaires, et parlant différemment
langues, essayant de programmer une réunion.
3. 3. Outil de surveillance du réseau. Le système rassemble
statistiques de performances et collecte des rapports de panne. Vous aimeriez
mettre en œuvre certains agents pour utiliser ces informations pour rechercher
problème dans le système.

Chapitre 6. Pendant que vous codez

La sagesse conventionnelle dit qu'une fois qu'un projet est dans la phase de codage, le
le travail est majoritairement mécanique, transcrivant la conception en exécutable
déclarations. Nous pensons que cette attitude est la principale raison pour laquelle
de nombreux programmes sont laids, inefficaces, mal structurés, impossibles à maintenir,
et tout simplement faux.

Le codage n'est pas mécanique. Si c'était le cas, tous les outils CASE que les gens ont épinglés
leurs espoirs au début des années 1980 auraient longtemps remplacé les programmeurs
il y a. Il y a des décisions à prendre à chaque minute, des décisions qui exigent
une réflexion et un jugement minutieux si le programme qui en résulte doit profiter d'une longue,
une vie précise et productive.

Les développeurs qui ne réfléchissent pas activement à leur code programment en


coïncidence - le code peut fonctionner, mais il n'y a pas de raison particulière à cela. Dans
Programmation by Coincidence, nous prônons une implication plus positive
avec le processus de codage.
Alors que la plupart du code que nous écrivons s'exécute rapidement, nous développons occasionnellement
des algorithmes qui ont le potentiel d'enliser même les processeurs les plus rapides.
Dans Algorithm Speed, nous discutons des moyens d'estimer la vitesse du code, et nous
donner quelques conseils sur la façon de repérer les problèmes potentiels avant qu'ils ne surviennent.

Les programmeurs pragmatiques réfléchissent de manière critique à tout code, y compris le nôtre.
Nous voyons constamment des possibilités d'amélioration dans nos programmes et nos conceptions.
Dans Refactoring, nous examinons des techniques qui nous aident à réparer le code existant même
alors que nous sommes au milieu d'un projet.

Quelque chose qui devrait être à l'arrière de votre esprit chaque fois que vous êtes
produire du code est que vous devrez un jour le tester. Rendre le code facile à tester,
et vous augmenterez la probabilité qu'il soit réellement testé, une pensée
nous développons dans Code That's Easy to Test.

Enfin, dans Evil Wizards, nous vous suggérons de faire attention aux outils qui
écrire des tonnes de code en votre nom à moins que vous ne compreniez ce qu'ils sont
action.

La plupart d'entre nous peuvent conduire une voiture en grande partie sur pilote automatique - nous ne le faisons pas explicitement
ordonnons à notre pied d'appuyer sur une pédale ou à notre bras de tourner le volant.
pensez "ralentissez et tournez à droite". Cependant, de bons conducteurs prudents sont
en examinant constamment la situation, en vérifiant les problèmes potentiels et
se mettre en bonne position en cas d'imprévu. Le

il en va de même pour le codage - il peut s'agir en grande partie de routine, mais gardez votre esprit
à propos de vous pourrait bien empêcher une catastrophe.

Programmation
Programmation par
par coïncidence
coïncidence

Avez-vous déjà regardé de vieux films de guerre en noir et blanc ? Le soldat fatigué
avance prudemment hors des broussailles. Il y a une clairière devant : y a-t-il
des mines terrestres, ou est-il sécuritaire de traverser? Rien n'indique qu'il s'agit d'un
champ de mines - aucun signe, fil de fer barbelé ou cratères. Le soldat pique le sol
devant lui avec sa baïonnette et grimace, s'attendant à une explosion. Là
n'en est pas un. Alors il avance laborieusement à travers le champ pendant un certain temps,
poussant et poussant comme il va. Finalement, convaincu que le champ est sûr,
il se redresse et marche fièrement en avant, seulement pour être réduit en pièces.

Les premières sondes du soldat pour les mines n'ont rien révélé, mais c'était simplement
chanceux. Il a été conduit à une fausse conclusion, avec des résultats désastreux.

En tant que développeurs, nous travaillons également dans des champs de mines. Il y a des centaines de pièges juste
attendant de nous rattraper chaque jour. En nous souvenant de l'histoire du soldat, nous devrions être
méfiez-vous de tirer de fausses conclusions. Il faut éviter de programmer en
coïncidence - s'appuyant sur la chance et les succès accidentels - en faveur de
programmer délibérément.

Comment
Comment programmer
programmer par
par coïncidence
coïncidence

Supposons que Fred reçoive une tâche de programmation. Fred tape du code,
essaie, et ça a l'air de marcher. Fred tape un peu plus de code, l'essaie, et il
semble toujours fonctionner. Après plusieurs semaines de codage de cette façon, le programme
cesse soudainement de fonctionner, et après des heures à essayer de le réparer, il ne fonctionne toujours pas
savoir pourquoi. Fred pourrait bien passer beaucoup de temps à poursuivre cette
morceau de code autour sans jamais pouvoir le réparer. Peu importe ce qu'il
fait, ça ne semble jamais fonctionner correctement.

Fred ne sait pas pourquoi le code échoue parce qu'il ne savait pas pourquoi
travaillé en premier lieu. Cela a semblé fonctionner, compte tenu des "tests" limités que
Fred l'a fait, mais ce n'était qu'une coïncidence. Porté par une fausse confiance, Fred
chargé en avant dans l'oubli. Maintenant, la plupart des gens intelligents savent peut-être
quelqu'un comme Fred, mais nous savons mieux. Nous ne nous fions pas aux coïncidences—faites
nous?
Parfois, nous pourrions. Parfois, il peut être assez facile de confondre un heureux
coïncidence avec un plan déterminé. Regardons quelques exemples.

Accidents
Accidents de
de mise
mise en
en œuvre
œuvre

Les accidents de mise en œuvre sont des choses qui se produisent simplement parce que c'est
la façon dont le code est actuellement écrit. Vous finissez par compter sur des sans-papiers
erreur ou conditions aux limites.

Supposons que vous appeliez une routine avec de mauvaises données. La routine répond dans un
manière particulière, et vous codez en fonction de cette réponse. Mais l'auteur n'a pas
l'intention que la routine fonctionne de cette façon - cela n'a même jamais été envisagé.
Lorsque la routine est "réparée", votre code peut se casser. Au plus extrême
cas, la routine que vous avez appelée peut même ne pas être conçue pour faire ce que vous voulez,
mais ça a l'air de bien fonctionner. Appeler les choses dans le mauvais ordre, ou dans le
am u

Ici, on dirait que Fred essaie désespérément de sortir quelque chose sur le
filtrer. Mais ces routines n'ont jamais été conçues pour être appelées ainsi ;
bien qu'ils semblent fonctionner, ce n'est vraiment qu'une coïncidence.

Pour ajouter l'insulte à l'injure, lorsque le composant est enfin dessiné, Fred
n'essaiera pas de revenir en arrière et de retirer les faux appels. "Ça marche maintenant, mieux
laisser assez bien seul…"

Il est facile de se laisser berner par cette ligne de pensée. Pourquoi prendre le risque de
jouer avec quelque chose qui fonctionne? Eh bien, nous pouvons penser à plusieurs
les raisons:

• • Il se peut que cela ne fonctionne pas vraiment—cela peut sembler le cas.


• • La condition aux limites sur laquelle vous comptez peut n'être qu'un accident. Dans
circonstances différentes (une résolution d'écran différente, peut-être), il
pourraient se comporter différemment.
• • Le comportement non documenté peut changer avec la prochaine version du
bibliothèque.
• • Des appels supplémentaires et inutiles ralentissent votre code.
• • Des appels supplémentaires augmentent également le risque d'introduire de nouveaux bogues de
les leurs.

Pour le code que vous écrivez que d'autres appelleront, les principes de base du bon
modularisation et de dissimulation de la mise en œuvre derrière de petites

des interfaces bien documentées peuvent toutes aider. Un contrat bien défini (voir
Conception par contrat
) peut aider à éliminer les malentendus.

Pour les routines que vous appelez, ne vous fiez qu'au comportement documenté. Si vous ne pouvez pas, pour
quelle que soit la raison, alors documentez bien votre hypothèse.
Accidents
Accidents de
de contexte
contexte
Vous pouvez également avoir des "accidents de contexte". Supposons que vous écriviez un
module utilitaire. Juste parce que vous codez actuellement pour une interface graphique
environnement, le module doit-il s'appuyer sur la présence d'une interface graphique ? Es-tu
s'appuyer sur des utilisateurs anglophones ? Utilisateurs lettrés ? Qu'est-ce que tu es d'autre
compter là-dessus n'est pas garanti?

Hypothèses
Hypothèses implicites
implicites

Les coïncidences peuvent induire en erreur à tous les niveaux, de la génération des exigences
jusqu'aux tests. Les tests sont particulièrement chargés de fausses causalités et
résultats fortuits. Il est facile de supposer que X cause Y, mais comme nous l'avons dit
dans Debugging : ne le supposez pas, prouvez-le.

À tous les niveaux, les gens opèrent avec de nombreuses hypothèses à l'esprit, mais celles-ci
les hypothèses sont rarement documentées et sont souvent en conflit entre
différents développeurs. Des hypothèses qui ne reposent pas sur des données bien établies
les faits sont le fléau de tous les projets.

Astuce
Astuce 44
44

Ne programmez pas par hasard

Comment
Comment programmer
programmer délibérément
délibérément

Nous voulons passer moins de temps à produire du code, détecter et corriger les erreurs le plus tôt possible
dans le cycle de développement que possible, et créer moins d'erreurs pour commencer.
Cela aide si nous pouvons programmer délibérément :

• • Soyez toujours conscient de ce que vous faites. Fred a laissé les choses aller
lentement hors de contrôle, jusqu'à ce qu'il finisse par bouillir, comme la grenouille dans Stone
Soupe et grenouilles bouillies.

• • Ne codez pas les yeux bandés. Tenter de créer une application que vous
ne comprends pas bien ou d'utiliser une technologie qui ne m'est pas familière
avec, est une invitation à se laisser tromper par les coïncidences.
• • Procédez à partir d'un plan, que ce plan soit dans votre tête, sur le
dos d'une serviette à cocktail, ou sur une impression murale à partir d'un CASE
outil.
• • Ne comptez que sur des choses fiables. Ne comptez pas sur les accidents ou
hypothèses. Si vous ne pouvez pas faire la différence en particulier
circonstances, imaginez le pire.
• • Documentez vos hypothèses. Conception par contrat, peut aider
clarifier vos hypothèses dans votre propre esprit, ainsi que vous aider
les communiquer aux autres.
• • Ne vous contentez pas de tester votre code, mais testez également vos hypothèses.
Ne devinez pas; essayez-le en fait. Rédigez une assertion pour tester votre
hypothèses (voir Programmation Assertive ). Si votre affirmation est juste,
vous avez amélioré la documentation dans votre code. Si vous découvrez
votre hypothèse est fausse, alors comptez-vous chanceux.
• • Priorisez vos efforts. Passez du temps sur les aspects importants; plus
que probablement, ce sont les parties difficiles. Si vous n'avez pas les bases
ou infrastructure correcte, des cloches et des sifflets brillants seront
non pertinent.
• • Ne soyez pas esclave de l'histoire. Ne laissez pas le code existant dicter l'avenir
code. Tout code peut être remplacé s'il n'est plus approprié. Même
dans un programme, ne laissez pas ce que vous avez déjà fait vous limiter
ce que vous faites ensuite - soyez prêt à refactoriser (voir Refactoring ). Ce
décision peut avoir une incidence sur le calendrier du projet. L'hypothèse est que le
l'impact sera inférieur au coût de ne pas effectuer le changement.
[1]

[ ]
[1] Vous pouvez aussi aller trop loin ici. Nous avons connu un développeur qui réécrivait toutes les sources qu'on lui donnait parce qu'il avait
ses propres conventions de nommage.

Alors la prochaine fois que quelque chose semble fonctionner, mais que vous ne savez pas pourquoi, assurez-vous
ce n'est pas juste une coïncidence.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Soupe aux cailloux et grenouilles bouillies


• • Débogage
• • Conception par contrat
• • Programmation affirmée
• • Couplage temporel
• • Refactorisation
• • Tout est écrit

Des
Des exercices
exercices

31.
31. Pouvez-vous identifier des coïncidences dans le fragment de code C suivant ?
S u

32.
32. Ce morceau de code C peut fonctionner de temps en temps, sur certaines machines.
L e
à cn

33.
33. Ce code provient d'une suite de traçage Java à usage général. Le
La fonction écrit une chaîne dans un fichier journal. Il réussit son test unitaire, mais échoue
lorsqu'un des développeurs Web l'utilise. Sur quelle coïncidence repose-t-il
s u

Vitesse
Vitesse de
de l'algorithme
l'algorithme

Dans Estimation, nous avons parlé d'estimer des choses telles que le temps qu'il faut
marcher à travers la ville, ou combien de temps un projet prendra pour se terminer. Cependant,
il existe un autre type d'estimation que les programmeurs pragmatiques utilisent
presque quotidiennement : estimer les ressources utilisées par les algorithmes : temps,
processeur, mémoire, etc.

Ce type d'estimation est souvent crucial. Étant donné le choix entre deux façons de
faire quelque chose, que choisissez-vous ? Vous savez combien de temps dure votre programme
avec 1 000 enregistrements, mais comment passera-t-il à 1 000 000 ? Quelles parties du
le code a besoin d'être optimisé ?

Il s'avère qu'il est souvent possible de répondre à ces questions en utilisant des
sens, quelques analyses et une façon d'écrire des approximations appelées les "grandes
Notation O".

Qu'entendons-nous
Qu'entendons-nous par
par estimation
estimation d'algorithmes
d'algorithmes ??

La plupart des algorithmes non triviaux gèrent une sorte d'entrée de variable - trier n
chaînes, en inversant une matrice m × n ou en déchiffrant un message avec un n-bit
clé. Normalement, la taille de cette entrée affectera l'algorithme : plus le
entrée, plus le temps d'exécution est long ou plus la mémoire utilisée est importante.

Si la relation était toujours linéaire (de sorte que le temps augmentait en


proportionnellement à la valeur de n), cette section n'aurait pas d'importance. Cependant,
les algorithmes les plus significatifs ne sont pas linéaires. La bonne nouvelle est que beaucoup sont
sous-linéaire. Une recherche binaire, par exemple, n'a pas besoin de regarder chaque
candidat lors de la recherche d'une correspondance. La mauvaise nouvelle est que d'autres algorithmes sont
considérablement pire que linéaire ; les durées d'exécution ou les besoins en mémoire augmentent
beaucoup plus rapide que n. Un algorithme qui prend une minute pour traiter dix items
peut prendre toute une vie pour en traiter 100.

Nous constatons que chaque fois que nous écrivons quelque chose contenant des boucles ou récursif
appels, nous vérifions inconsciemment les exigences d'exécution et de mémoire. Ce
est rarement un processus formel, mais plutôt une confirmation rapide que ce que nous sommes
faire est raisonnable dans les circonstances. Cependant, nous trouvons parfois
procédons nous-mêmes à une analyse plus détaillée. C'est alors que le O()
la notation est utile.

La
La notation
notation O()
O()

La notation O() est une manière mathématique de traiter les approximations.


Lorsque nous écrivons qu'une routine de tri particulière trie n enregistrements en O(n
2) temps,

nous disons simplement que le temps pris dans le pire des cas variera comme le carré
de n. Doublez le nombre d'enregistrements, et le temps augmentera approximativement
quadruple. Pensez au O comme signifiant de l'ordre de. La notation O() met
une limite supérieure sur la valeur de la chose que nous mesurons (temps, mémoire,
et ainsi de suite). Si on dit qu'une fonction prend O(n alors nous savons que le
2) temps,

la limite supérieure du temps nécessaire ne croîtra pas plus vite que n nous
2. Parfois

proposer des fonctions O () assez complexes, mais parce que l'ordre le plus élevé
terme dominera la valeur à mesure que n augmente, la convention est de supprimer tous
termes d'ordre inférieur, et de ne pas s'embêter à montrer une multiplication constante

facteurs. Sur2/2+ 3n) est identique à O(n 2/2), ce qui équivaut à O(n 2).

C'est en fait une faiblesse de la notation O()—un O(n 2) l'algorithme peut

être 1 000 fois plus rapide qu'un autre O(n2) algorithme, mais vous ne le saurez pas

de la notation.

La figure 6.1 montre plusieurs notations O() courantes que vous rencontrerez, ainsi que
avec un graphique comparant les temps d'exécution des algorithmes dans chaque catégorie.
De toute évidence, les choses commencent rapidement à devenir incontrôlables
2). une fois que nous avons dépassé O(n

Figure
Figure 6.1.
6.1. Exécutions
Exécutions de
de divers
divers algorithmes
algorithmes
Par exemple, supposons que vous ayez une routine qui prend 1 s pour traiter 100
enregistrements. Combien de temps faudra-t-il pour traiter 1 000 ? Si votre code est O(1), alors il
prendra encore 1 s. Si c'est O(lg(n)), alors vous attendrez probablement environ 3 s.
O(n) montrera une augmentation linéaire à 10 s, tandis qu'un O(n lg(n)) prendra quelques
33 s. Si vous avez la malchance d'avoir un O(n 2) routine, puis asseyez-vous pour
100 s pendant qu'il fait son travail. Et si vous utilisez un algorithme exponentiel
O(2 n ), vous voudrez peut-être vous préparer une tasse de café. Votre routine devrait se terminer dans
environ 10 263 ans. Faites-nous savoir comment l'univers se termine.

La notation O() ne s'applique pas uniquement au temps ; vous pouvez l'utiliser pour représenter n'importe quel
autres ressources utilisées par un algorithme. Par exemple, il est souvent utile d'être
capable de modéliser la consommation mémoire (voir Exercice 35).

Estimation
Estimation de
de bon
bon sens
sens

Vous pouvez estimer l'ordre de nombreux algorithmes de base en utilisant votre bon sens.

• • Boucles simples. Si une boucle simple va de 1 à n, alors le


l'algorithme est probablement O(n) — le temps augmente linéairement avec n.
Les exemples incluent des recherches exhaustives, la recherche de la valeur maximale
dans un tableau et générer des sommes de contrôle.
• • Boucles imbriquées. Si vous imbriquez une boucle dans une autre, votre
devient O(m × n), où m et n sont les limites des deux boucles.
Cela se produit généralement dans les algorithmes de tri simples, tels que bulle
sort, où la boucle externe analyse tour à tour chaque élément du tableau,
et la boucle interne détermine où placer cet élément dans le
résultat trié. De tels algorithmes de tri tendent à être O(n2).
• • Hachage binaire. Si votre algorithme réduit de moitié l'ensemble des choses, il
considère chaque fois autour de la boucle, alors il est susceptible d'être
logarithmique, O(lg(n)) (voir Exercice 37). Une recherche binaire d'un trié
liste, en parcourant un arbre binaire et en trouvant le premier bit défini dans un
les mots machine peuvent tous être O(lg(n)).
• • Diviser et conquérir. Des algorithmes qui partitionnent leur entrée,
travailler sur les deux moitiés indépendamment, puis combiner le résultat
peut être O(n lg(n)). L'exemple classique est le tri rapide, qui fonctionne en
partitionner les données en deux moitiés et trier récursivement chacune.
2
Bien que techniquement O(n ), car son comportement se dégrade lorsqu'il est
alimenté en entrée triée, le temps d'exécution moyen du tri rapide est O(n lg(n)).
• • Combinatoire. Chaque fois que les algorithmes commencent à regarder le
permutations des choses, leurs durées de fonctionnement peuvent devenir incontrôlables.
En effet, les permutations impliquent des factorielles (il y a 5! = 5 × 4 ×
3 × 2 × 1 = 120 permutations des chiffres de 1 à 5). Temps un
algorithme combinatoire pour cinq éléments : il faudra six fois plus de temps
pour le faire fonctionner pendant six, et 42 fois plus longtemps pour sept. Les exemples comprennent

algorithmes pour de nombreux problèmes difficiles reconnus - le


problème du voyageur de commerce, emballer les choses de manière optimale dans un
conteneur, en partitionnant un ensemble de nombres de sorte que chaque ensemble ait le
même total, et ainsi de suite. Souvent, les heuristiques sont utilisées pour réduire le
temps d'exécution de ces types d'algorithmes en particulier problème
domaines.

Vitesse
Vitesse d'algorithme
d'algorithme en
en pratique
pratique

Il est peu probable que vous passiez beaucoup de temps au cours de votre carrière à écrire
routines. Ceux des bibliothèques à votre disposition seront probablement plus performants
tout ce que vous pouvez écrire sans effort substantiel. Cependant, la base
les types d'algorithmes que nous avons décrits précédemment apparaissent maintes et maintes fois.
Chaque fois que vous vous retrouvez à écrire une boucle simple, vous savez que vous avez
un algorithme O(n). Si cette boucle contient une boucle interne, alors vous regardez
O(m × n). Vous devriez vous demander quelle peut être l'ampleur de ces valeurs. Si
les nombres sont bornés, alors vous saurez combien de temps le code prendra pour
courir. Si les chiffres dépendent de facteurs externes (tels que le nombre de
enregistrements dans une exécution par lots pendant la nuit, ou le nombre de noms dans une liste de
personnes), alors vous voudrez peut-être vous arrêter et considérer l'effet que de grandes
les valeurs peuvent avoir sur votre temps d'exécution ou votre consommation de mémoire.

Astuce
Astuce 45
45

Estimez l'ordre de vos algorithmes

Il existe certaines approches que vous pouvez adopter pour résoudre les problèmes potentiels. Si
tu as un algorithme qui est O(n 2), essayez de trouver un diviser pour mieux régner

approche qui vous mènera à O(n lg(n)).

Si vous n'êtes pas sûr de la durée de votre code ou de la quantité de mémoire qu'il faudra
utiliser, essayez de l'exécuter, en faisant varier le nombre d'enregistrements d'entrée ou tout ce qui est susceptible de
impact sur le temps d'exécution. Tracez ensuite les résultats. Vous devriez bientôt avoir une bonne idée
de la forme de la courbe. S'agit-il d'une courbe vers le haut, d'une ligne droite ou d'un aplatissement ?
désactivé à mesure que la taille d'entrée augmente ? Trois ou quatre points devraient vous donner une idée.

Considérez également ce que vous faites dans le code lui-même. Un simple O(n
2) boucle

pourrait bien mieux fonctionner qu'un complexe, O(n lg(n)) un pour des valeurs plus petites de
n, en particulier si l'algorithme O(n lg(n)) a une boucle interne coûteuse.

Au milieu de toute cette théorie, n'oubliez pas qu'il y a des pratiques


considérations aussi. Le temps d'exécution peut sembler augmenter de manière linéaire pour les petites

jeux d'entrée. Mais nourrir le code des millions d'enregistrements et du coup le temps
se dégrade lorsque le système commence à s'effondrer. Si vous testez une routine de tri avec
touches d'entrée aléatoires, vous pourriez être surpris la première fois qu'il rencontre
entrée ordonnée. Les programmeurs pragmatiques essaient de couvrir à la fois les aspects théoriques
et bases pratiques. Après toutes ces estimations, le seul moment qui compte est
la vitesse de votre code, s'exécutant dans l'environnement de production, avec de vrais
[2] Cela nous amène à notre prochain conseil.
données.

[2] En fait, en testant les algorithmes de tri utilisés comme exercice pour cette section sur un Pentium 64 Mo, les auteurs ont manqué de

mémoire réelle lors de l'exécution du tri par base avec plus de sept millions de nombres. Le tri a commencé à utiliser l'espace d'échange, et

fois dégradé de façon spectaculaire.

Astuce
Astuce 46
46

Testez vos estimations

S'il est difficile d'obtenir des minutages précis, utilisez des profileurs de code pour compter les
nombre de fois que les différentes étapes de votre algorithme sont exécutées et tracez
ces chiffres par rapport à la taille de l'entrée.

Le
Le meilleur
meilleur n'est
n'est pas
pas toujours
toujours le
le meilleur
meilleur

Vous devez également être pragmatique quant au choix des algorithmes appropriés—le
le plus rapide n'est pas toujours le meilleur pour le travail. Étant donné un petit ensemble d'entrées, un
le tri par insertion simple fonctionnera aussi bien qu'un tri rapide, et
vous prendra moins de temps pour écrire et déboguer. Vous devez également faire attention si le
l'algorithme que vous choisissez a un coût d'installation élevé. Pour les petits ensembles d'entrées, cette configuration
peut éclipser le temps d'exécution et rendre l'algorithme inapproprié.

Méfiez-vous également des optimisations prématurées. C'est toujours une bonne idée de faire
assurez-vous qu'un algorithme est vraiment un goulot d'étranglement avant d'investir votre temps précieux
essayer de l'améliorer.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Estimation

Défis
Défis

• • Chaque développeur devrait avoir une idée de la façon dont les algorithmes sont
conçu et analysé. Robert Sedgewick a écrit une série de

livres accessibles sur le sujet ([ Sed83 , SF96 , Sed92 ] et autres).


Nous vous recommandons d'ajouter un de ses livres à votre collection, et
mettre un point d'honneur à le lire.
• • Pour ceux qui aiment plus de détails que ceux fournis par Sedgewick, lisez
Les livres définitifs sur l'art de la programmation informatique de Donald Knuth,
qui analysent un large éventail d'algorithmes [ Knu97a , Knu97b , Knu98 ].
• • Dans l'exercice 34, nous examinons le tri de tableaux d'entiers longs. Quoi
est l'impact si les clés sont plus complexes, et la surcharge de la clé
la comparaison est élevée? La structure de la clé affecte-t-elle l'efficacité du
algorithmes de tri, ou le tri le plus rapide est-il toujours le plus rapide ?

Des
Des exercices
exercices

34.
34. Nous avons codé un ensemble de routines de tri simples, qui peuvent être téléchargées
sur notre site Web (http://www.pragmaticprogrammer.com ). Exécutez-les
sur les différentes machines mises à votre disposition. Vos chiffres suivent-ils
courbes attendues ? Que pouvez-vous en déduire des vitesses relatives de
vos engins ? Quels sont les effets de diverses optimisations du compilateur
paramètres? Le tri par base est-il bien linéaire ?

35.
35. La routine ci-dessous imprime le contenu d'un arbre binaire. En supposant
l'arbre est équilibré, à peu près combien d'espace de pile la routine aura-t-elle
utiliser lors de l'impression d'un arbre de 1 000 000 d'éléments ? (Suppose que
el s
36.
36. Pouvez-vous voir un moyen de réduire les exigences de pile de la routine
dans l'exercice 35 (en plus de réduire la taille du tampon) ?

37.
37. nous avons affirmé qu'un hachage binaire est O(lg(n)). Pouvez-vous prouver cela?

Refactoring
Refactoring

Changement et décomposition dans tout autour, je vois…

HF
HF Lyte,
Lyte, "Reste
"Reste avec
avec moi"
moi"

À mesure qu'un programme évolue, il deviendra nécessaire de repenser les décisions antérieures
et retravailler des parties du code. Ce processus est parfaitement naturel. Code
doit évoluer; ce n'est pas quelque chose de statique.

Malheureusement, la métaphore la plus courante pour le développement de logiciels est


construction de bâtiments (Bertrand Meyer [ Mey97b] utilise le terme "Logiciel
construction"). Mais utiliser la construction comme métaphore directrice implique
ces étapes :

1. 1. Un architecte dessine des plans.

2. 2. Les entrepreneurs creusent les fondations, construisent la superstructure, câblent


et d'aplomb, et appliquez les touches de finition.

3. 3. Les locataires emménagent et vivent heureux pour toujours, appelant l'immeuble


maintenance pour résoudre tout problème.

Eh bien, le logiciel ne fonctionne pas tout à fait de cette façon. Plutôt que de construire,
le logiciel ressemble plus à du jardinage - il est plus organique que concret. Toi
planter beaucoup de choses dans un jardin selon un plan et des conditions initiaux.
Certains prospèrent, d'autres sont destinés à finir en compost. Vous pouvez déplacer
plantations les unes par rapport aux autres pour profiter des jeux de lumière
et l'ombre, le vent et la pluie. Les plantes envahies sont fendues ou taillées, et
les couleurs qui s'opposent peuvent être déplacées vers des endroits plus esthétiques.
Vous arrachez les mauvaises herbes et vous fertilisez les plantations qui ont besoin d'un peu plus
aider. Vous surveillez en permanence la santé du jardin et faites
ajustements (au sol, aux plantes, à l'aménagement) selon les besoins.

Les gens d'affaires sont à l'aise avec la métaphore de la construction de bâtiments :


c'est plus scientifique que le jardinage, c'est reproductible, il y a un rapport rigide
hiérarchie de gestion, etc. Mais nous ne construisons pas
gratte-ciel - nous ne sommes pas aussi limités par les limites de la physique et
monde réel.

La métaphore du jardinage est beaucoup plus proche des réalités du logiciel


développement. Peut-être qu'une certaine routine est devenue trop importante ou essaie de
accomplir trop - il doit être divisé en deux. Choses qui ne fonctionnent pas
comme prévu doivent être désherbés ou taillés.

La réécriture, le remaniement et la réarchitecture du code sont collectivement connus sous le nom de


refactorisation.
Quand
Quand devriez-vous
devriez-vous refactoriser
refactoriser ??

Lorsque vous rencontrez une pierre d'achoppement parce que le code ne correspond pas tout à fait
plus, ou vous remarquez deux choses qui devraient vraiment être fusionnées, ou
tout le reste vous semble "faux", n'hésitez pas à le changer
Il n'y a d'autre instant que le présent. Un certain nombre de choses peuvent entraîner le code à
qualifier pour le refactoring :

• • Duplication. Vous avez découvert une violation du DRY


principe ( Les maux de la duplication ).
• • Conception non orthogonale. Vous avez découvert du code ou du design
qui pourrait être rendue plus orthogonale ( Orthogonalité ).
• • Connaissances obsolètes. Les choses changent, les exigences dérivent et
votre connaissance du problème augmente. Le code doit suivre.
• • Performance. Vous devez déplacer des fonctionnalités d'un domaine de
le système à un autre pour améliorer les performances.

Refactorisation de votre code : déplacement des fonctionnalités et mise à jour plus tôt
décisions - est vraiment un exercice de gestion de la douleur. Avouons-le, changer
autour du code source peut être assez pénible : cela fonctionnait presque, et maintenant
c'est vraiment déchiré. De nombreux développeurs hésitent à commencer à déchirer le code
juste parce que ce n'est pas tout à fait correct.

Complications
Complications du
du monde
monde réel
réel

Donc, vous allez voir votre patron ou votre client et lui dites : « Ce code fonctionne, mais j'ai besoin
encore une semaine pour le refactoriser."

Nous ne pouvons pas imprimer leur réponse.

La pression du temps est souvent utilisée comme excuse pour ne pas refactoriser. Mais cette excuse
ne tient tout simplement pas le coup : échouez à refactoriser maintenant, et il y aura beaucoup plus de temps
investissement pour résoudre le problème plus tard - quand il y a plus
dépendances à prendre en compte. Y aura-t-il plus de temps disponible alors? Pas dedans
notre expérience.

Vous voudrez peut-être expliquer ce principe au patron en utilisant un médecin


analogie : considérez le code qui doit être refactorisé comme une "croissance". Le retirer
nécessite une chirurgie invasive. Vous pouvez entrer maintenant et le sortir pendant qu'il est encore
petit. Ou, vous pouvez attendre pendant qu'il grandit et se propage, mais enlevez-le ensuite
sera à la fois plus cher et plus dangereux. Attendez encore plus longtemps et vous
peut perdre entièrement le patient.

Astuce
Astuce 47
47

Refactoriser tôt, refactoriser souvent

Gardez une trace des choses qui doivent être refactorisées. Si vous ne pouvez pas refactoriser
quelque chose immédiatement, assurez-vous qu'il est placé sur le calendrier.
Assurez-vous que les utilisateurs du code concerné savent qu'il doit être
refactorisés et comment cela pourrait les affecter.

Comment
Comment refactoriser
refactoriser ??
Le refactoring a commencé dans la communauté Smalltalk et, avec d'autres
tendances (telles que les modèles de conception), a commencé à gagner un public plus large. Mais
en tant que sujet, c'est encore assez nouveau; il n'y a pas beaucoup de publications dessus. La première
+ 99 ], ainsi que [ URL 47 ]) est en cours de publication
livre majeur sur le refactoring ([ FBB
à peu près à la même époque que ce livre.

Au fond, le refactoring est une refonte. Tout ce que vous ou d'autres sur votre
conçu par l'équipe peut être repensé à la lumière de nouveaux faits, plus profond
compréhensions, exigences changeantes, etc. Mais si vous procédez à
déchirer de grandes quantités de code avec un abandon sauvage, vous pouvez vous retrouver dans un
pire position que lorsque vous avez commencé.

De toute évidence, le refactoring est une activité qui doit être entreprise lentement,
délibérément et soigneusement. Martin Fowler propose les conseils simples suivants
comment refactoriser sans faire plus de mal que de bien (voir l'encadré sur
[ FS97 ]):

1. 1. N'essayez pas de refactoriser et d'ajouter des fonctionnalités en même temps.


2. 2. Assurez-vous d'avoir de bons tests avant de commencer le refactoring. Courir
les tests aussi souvent que possible. Ainsi, vous saurez rapidement si votre
les changements ont cassé quoi que ce soit.

Refactorisation automatique

Historiquement, les utilisateurs de Smalltalk ont toujours apprécié un navigateur de classe


dans le cadre de l'IDE. À ne pas confondre avec les navigateurs Web, classe
les navigateurs permettent aux utilisateurs de naviguer et d'examiner les hiérarchies de classes
et méthodes.

Généralement, les navigateurs de classes vous permettent d'éditer du code, de créer de nouvelles méthodes

et cours, etc. La variante suivante de cette idée est la


navigateur de refactorisation.

Un navigateur de refactoring peut effectuer semi-automatiquement des


opérations de refactorisation pour vous : fractionnement d'une longue routine en
les plus petits, propageant automatiquement les changements de méthode et
noms de variables, glisser-déposer pour vous aider à déplacer le code, etc.
sur.

Au moment où nous écrivons ce livre, cette technologie n'est pas encore apparue en dehors de
le monde Smalltalk, mais cela est susceptible de changer à la même vitesse
que Java change—rapidement. En attendant, le pionnier
Le navigateur de refactorisation Small Talk est disponible en ligne].à l'adresse [ URL 20

3. 3. Prenez des mesures courtes et délibérées : déplacez un champ d'une classe à


un autre, fusionner deux méthodes similaires dans une superclasse. Refactoring
implique souvent de nombreux changements localisés qui entraînent une
changement à plus grande échelle. Si vous gardez vos pas petits et testez après chaque
étape, vous éviterez un débogage prolongé.

Nous parlerons plus en détail des tests à ce niveau dans Code facile à tester , et
tests à plus grande échelle dans Ruthless Testing , mais le point de M. Fowler
maintenir de bons tests de régression est la clé d'un refactoring en toute confiance.

Il peut également être utile de s'assurer que les changements drastiques apportés à un module, tels que
comme altérant son interface ou sa fonctionnalité de manière incompatible
manière-casser la construction. C'est-à-dire que les anciens clients de ce code devraient tomber dans
compiler. Vous pouvez alors retrouver rapidement les anciens clients et faire le nécessaire
changements pour les mettre à jour.

Donc, la prochaine fois que vous voyez un morceau de code qui n'est pas tout à fait comme il se doit, corrigez les deux
elle et tout ce qui en dépend. Gérer la douleur : si ça fait mal maintenant, mais
va faire encore plus mal plus tard, autant en finir avec ça.
Rappelez-vous
les fenêtres. les leçons de l'entropie logicielle
, ne pas vivre avec cassé

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Le chat a mangé mon code source


• • Entropie logicielle
• • Soupe aux cailloux et grenouilles bouillies
• • Les maux de la duplication
• • Orthogonalité
• • Programmation par coïncidence

• • Code facile à tester


• • Tests impitoyables

Des
Des exercices
exercices

38.
38. Le code suivant a évidemment été mis à jour plusieurs fois au cours de la
a sn

39.
39. La classe Java suivante doit prendre en charge quelques formes supplémentaires. Refactoriser
al c
}

40.
40. Ce code Java fait partie d'un framework qui sera utilisé tout au long
votre projet. Refactorisez-le pour qu'il soit plus général et plus facile à étendre dans le
a ve

Code
Code facile
facile àà tester
tester

Le logiciel IC est une métaphore que les gens aiment lancer quand
[3]composants.
discuter de la réutilisabilité et du développement basé sur des L'idée est que
les composants logiciels doivent être combinés comme des puces de circuits intégrés
sont combinés. Cela ne fonctionne que si les composants que vous utilisez sont connus
être fiable.

[3] Le terme "Software IC" (Integrated Circuit) semble avoir été inventé en 1986 par Cox et Novobilski dans leur

Livre Objective-C Programmation Orientée Objet [ CN91 ].

Les puces sont conçues pour être testées, pas seulement en usine, pas seulement lorsqu'elles
sont installés, mais aussi sur le terrain lorsqu'ils sont déployés. Plus complexe
les puces et les systèmes peuvent avoir une fonction d'auto-test intégrée (BIST) complète qui
exécute en interne des diagnostics de base ou un mécanisme d'accès aux tests
(TAM) qui fournit un harnais de test qui permet à l'environnement externe de
fournir des stimuli et recueillir les réponses de la puce.

Nous pouvons faire la même chose dans le logiciel. Comme nos collègues quincailliers, nous
besoin d'intégrer la testabilité dans le logiciel dès le début et de tester
soigneusement chaque pièce avant d'essayer de les assembler.

Tests
Tests unitaires
unitaires

Les tests au niveau de la puce pour le matériel sont à peu près équivalents aux tests unitaires dans
logiciel—tests effectués sur chaque module, isolément, pour vérifier son comportement.
Nous pouvons avoir une meilleure idée de la façon dont un module réagira dans le vaste monde
une fois que nous l'avons testé à fond sous contrôle (même artificiel)
conditions.

Un test unitaire logiciel est un code qui teste un module. Généralement, le test unitaire
établira une sorte d'environnement artificiel, puis invoquera des routines dans
le module testé. Il vérifie ensuite les résultats renvoyés, soit
par rapport à des valeurs connues ou par rapport aux résultats d'exécutions précédentes du même
test (test de régression).

Plus tard, lorsque nous assemblons nos "CI logiciels" dans un système complet, nous allons
avoir confiance que les pièces individuelles fonctionnent comme prévu, puis nous
peut utiliser les mêmes installations de test unitaire pour tester le système dans son ensemble. On parle
à propos de cette vérification à grande échelle du système dans Ruthless. Testing

Avant d'aller aussi loin, cependant, nous devons décider quoi tester à l'unité
niveau. En règle générale, les programmeurs jettent quelques bits de données aléatoires sur le code
et appelez-le testé. Nous pouvons faire beaucoup mieux, en utilisant les idées derrière le design by
contracter.

Test
Test contre
contre contrat
contrat

Nous aimons considérer les tests unitaires comme des tests contre contrat (voir Design by
Contracter ). Nous voulons écrire des cas de test qui garantissent qu'une unité donnée honore
son contrat. Cela nous dira deux choses : si le code respecte le contrat,
et si le contrat signifie ce que nous pensons qu'il signifie. Nous voulons tester
que le module offre les fonctionnalités qu'il promet, sur une large gamme de
cas de test et conditions aux limites.

Qu'est-ce que cela signifie en pratique ? Regardons la routine racine carrée que nous
er cn

a s

Cela nous dit ce qu'il faut tester :

• • Passez un argument négatif et assurez-vous qu'il est rejeté.


• • Passez un argument de zéro pour vous assurer qu'il est accepté (c'est
la valeur limite).
• • Passer des valeurs comprises entre zéro et le maximum exprimable
argument et vérifier que la différence entre le carré du
résultat et l'argument original est inférieur à une petite fraction de
l'argument.

Armé de ce contrat, et en supposant que notre routine fait sa propre pré-


et la vérification des postconditions, nous pouvons écrire un script de test de base pour exercer le
of cn

sEn u
C'est un test assez simple; dans le monde réel, tout module non trivial est
susceptibles de dépendre d'un certain nombre d'autres modules, alors comment allons-nous
tester la combinaison?

Supposons que nous ayons un module A qui


LinkedList
utilise unet un Sort. En ordre,
on testerait :

1. 1. Contrat de LinkedList, dans son intégralité


2. 2. Contrat de Sort, dans son intégralité
3. 3. Le contrat de A, qui s'appuie sur les autres contrats mais ne
les exposer directement

Ce style de test nécessite que vous testiez d'abord les sous-composants d'un module.
Une fois les sous-composants vérifiés, le module lui-même peut être
testé.

Si les tests de LinkedList et Sort ont réussi, mais que le test de A a échoué, nous pouvons être assez
assurez-vous que le problème est dans A, ou dans l'utilisation par A d'un de ces sous-composants.
Cette technique est un excellent moyen de réduire l'effort de débogage : nous pouvons rapidement
se concentrer sur la source probable du problème dans le module A, et non
perdre du temps à réexaminer ses sous-composantes.

Pourquoi se donne-t-on tout ce mal ? Avant tout, nous voulons éviter de créer un
"bombe à retardement" - quelque chose qui reste inaperçu et explose à un
moment gênant plus tard dans le projet. En mettant l'accent sur les tests contre
contrat, nous pouvons essayer d'éviter autant de ces catastrophes en aval que possible
possible.

Astuce
Astuce 48
48

Concevoir pour tester

Lorsque vous concevez un module, ou même une seule routine, vous devez concevoir les deux
son contrat et le code pour tester ce contrat. En concevant du code pour passer un
tester et remplir son contrat, vous pouvez très bien envisager des conditions aux limites et
d'autres problèmes qui ne se poseraient pas autrement. Il n'y a pas de meilleur moyen de
corriger les erreurs qu'en les évitant en premier lieu. En effet, en construisant le
tests avant d'implémenter le code, vous pouvez essayer l'interface avant
vous vous y engagez.

Rédaction
Rédaction de
de tests
tests unitaires
unitaires

Les tests unitaires d'un module ne doivent pas être poussés dans un coin éloigné de
l'arborescence des sources. Ils doivent être idéalement situés. Pour les petits projets,
vous pouvez intégrer le test unitaire d'un module dans le module lui-même. Pour les plus grands
projets, nous suggérons de déplacer chaque test dans un sous-répertoire. Dans les deux cas,
rappelez-vous que s'il n'est pas facile à trouver, il ne sera pas utilisé.
En rendant le code de test facilement accessible, vous fournissez aux développeurs
qui peut utiliser votre code avec deux ressources inestimables :

1. 1. Exemples d'utilisation de toutes les fonctionnalités de votre module


2. 2. Un moyen de construire des tests de régression pour valider d'éventuelles évolutions futures
au code

C'est pratique, mais pas toujours pratique, que chaque classe ou module contienne
son propre test unitaire. En Java, par exemple, chaque classe peut avoir principal.
sa propre Dans
tout sauf le fichier de classe principal de l'application,
la routineleprincipale peut être utilisée pour exécuter
tests unitaires ; il sera ignoré lors de l'exécution de l'application elle-même. Cela a le
avantage que le code que vous expédiez contient toujours les tests, qui peuvent être utilisés pour
diagnostiquer les problèmes sur le terrain.

En C++, vous pouvez obtenir le même effet (au moment de la compilation) en utilisant #ifdef pour
compiler le code de test unitaire de manière sélective. Par exemple, voici une unité très simple
test en C++, intégré dans notre module, qui vérifie notre fonction racine carrée
en utilisant une routine testValue similaire à celle Java définie précédemment :

# dif e

un

Ce test unitaire exécutera un ensemble minimal de tests ou, si des arguments lui sont donnés,
vous permettent de transmettre des données depuis le monde extérieur. Un script shell pourrait utiliser
cette capacité à exécuter un ensemble de tests beaucoup plus complet.

Que faites-vous si la réponse correcte pour un test unitaire est de quitter ou d'abandonner le
programme? Dans ce cas, vous devez pouvoir sélectionner le test à exécuter, peut-être
en spécifiant un argument sur la ligne de commande. Vous devrez également passer
paramètres si vous devez spécifier différentes conditions de démarrage pour votre
essais.

Mais fournir des tests unitaires ne suffit pas. Vous devez les exécuter, et les exécuter
souvent. Cela aide également si la classe réussit ses tests de temps en temps.

Utilisation
Utilisation des
des harnais
harnais de
de test
test

Parce que nous écrivons généralement beaucoup de code de test et faisons beaucoup de tests, nous allons
se faciliter la vie et développer un harnais de test standard pour le
projet. Le principal montré dans la section précédente est un harnais de test très simple,
mais généralement nous aurons besoin de plus de fonctionnalités que cela.

Un harnais de test peut gérer des opérations courantes telles que l'état de la journalisation,
analyser la sortie pour les résultats attendus, et sélectionner et exécuter les tests.
Les faisceaux peuvent être pilotés par une interface graphique, peuvent être écrits dans le même langage cible
comme le reste du projet, ou peut être mis en œuvre comme une combinaison de
makefiles et scripts Perl. Un simple harnais de test est montré dans la réponse à
Exercice 41 à la page 305.

Dans les langages et environnements orientés objet, vous pouvez créer une base
classe qui fournit ces opérations courantes. Les tests individuels peuvent sous-classer
à partir de là et ajoutez un code de test spécifique. Vous pouvez utiliser une dénomination standard
convention et réflexion en Java pour construire dynamiquement une liste de tests. Ce
technique est une belle façon d'honorer le principe DRY - vous n'avez pas à

maintenir une liste des tests disponibles. Mais avant de partir et de commencer à écrire
votre propre harnais, vous voudrez peut-être enquêter sur Kent Beck et Erich
xUnit de Gamma à [ URL 22 ]. Ils ont déjà fait le gros du travail.

Quelle que soit la technologie que vous décidez d'utiliser, les harnais de test doivent
inclure les fonctionnalités suivantes :

• • Une manière standard de spécifier la configuration et le nettoyage


• • Une méthode de sélection des tests individuels ou de tous les tests disponibles
• • Un moyen d'analyser les résultats attendus (ou inattendus)
• • Un formulaire normalisé de rapport de panne

Les tests doivent être composables ; c'est-à-dire qu'un test peut être composé de sous-tests de
sous-composants à n'importe quelle profondeur. Nous pouvons utiliser cette fonctionnalité pour tester des pièces sélectionnées
du système ou de l'ensemble du système tout aussi facilement, avec les mêmes outils.

Tests ad hoc

Lors du débogage, nous pouvons finir par créer des tests particuliers
à la volée. Ceux-ci peuvent être aussi simples qu'une déclaration imprimée ou un morceau
de code entré de manière interactive dans un environnement de débogage ou IDE.

À la fin de la session de débogage, vous devez formaliser l'adhoc


test. Si le code s'est cassé une fois, il est susceptible de se casser à nouveau. Ne vous contentez pas
jeter le test que vous avez créé ; ajoutez-le au test unitaire existant.

Par exemple, en utilisant JUnit (le membre Java de la famille xUnit), nous pourrions
éc eriv
p u

JUnit est conçu pour être composable : nous pourrions ajouter autant de tests que nous
voulait cette suite, et chacun de ces tests pourrait à son tour être une suite. Dans
De plus, vous avez le choix entre une interface graphique ou batch pour piloter le
essais.

Construire
Construire une
une fenêtre
fenêtre de
de test
test

Même les meilleurs ensembles de tests ont peu de chances de trouver tous les bogues ; il y a
quelque chose sur les conditions humides et chaudes d'un environnement de production
qui semble les faire sortir du bois.

Cela signifie que vous devrez souvent tester un logiciel une fois qu'il a été
déployé, avec des données du monde réel circulant dans ses veines. Contrairement à un circuit
carte ou puce, nous n'avons pas de broches de test dans le logiciel, mais nous pouvons fournir
différentes vues de l'état interne d'un module, sans utiliser le
débogueur (ce qui peut être gênant ou impossible dans une production
application).

Les fichiers journaux contenant des messages de trace sont l'un de ces mécanismes. Messages du journal
doit être dans un format régulier et cohérent ; vous voudrez peut-être les analyser
automatiquement pour déduire le temps de traitement ou les chemins logiques que le programme
a pris. Les diagnostics mal formatés ou incohérents sont tellement
"vomir" - ils sont difficiles à lire et peu pratiques à analyser.

Un autre mécanisme pour entrer dans le code en cours d'exécution est la "touche de raccourci"
séquence. Lorsque cette combinaison particulière de touches est enfoncée, un diagnostic
fenêtre de contrôle apparaît avec des messages d'état et ainsi de suite. Ce n'est pas
quelque chose que vous révéleriez normalement aux utilisateurs finaux, mais cela peut être très pratique
pour le service d'assistance.

Pour un code serveur plus volumineux et plus complexe, une technique astucieuse pour fournir une vue
dans son fonctionnement est d'inclure un serveur Web intégré. N'importe qui peut pointer un
navigateur Web au port HTTP de l'application (qui se trouve généralement sur un
numéro non standard, tel que 8080) et voir l'état interne, les entrées de journal,
et peut-être même une sorte de panneau de contrôle de débogage. Cela peut sonner
difficile à mettre en œuvre, mais ce n'est pas le cas. HTTP librement disponible et intégrable
Les serveurs Web sont disponibles dans une variété de langues modernes. Un bon endroit pour
commencer à chercher est]. [ URL 58

Une
Une culture
culture de
de test
test
Tous les logiciels que vous écrivez seront testés, sinon par vous et votre équipe, du moins par
les utilisateurs éventuels, alors autant prévoir de le tester à fond. UN
peu de prévoyance peut grandement contribuer à minimiser les coûts de maintenance
et les appels au service d'assistance.

Malgré sa réputation de hacker, la communauté Perl a une très forte


engagement envers les tests unitaires et de régression. Le module standard Perl
al p

Il n'y a rien de magique dans Perl lui-même à cet égard. Perl facilite les choses
pour rassembler et analyser les résultats des tests pour assurer la conformité, mais le gros
l'avantage est simplement qu'il s'agit d'une norme : les tests ont lieu à un endroit particulier, et
avoir une certaine sortie attendue. Les tests sont plus culturels que techniques ; nous
peut insuffler cette culture de test dans un projet quelle que soit la langue utilisée
utilisé.

Astuce
Astuce 49
49

Testez votre logiciel, ou vos utilisateurs le feront

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Le chat a mangé mon code source


• • Orthogonalité
• • Conception par contrat
• • Refactorisation
• • Tests impitoyables

Des
Des exercices
exercices

41.
41. Concevez un gabarit de test pour l'interface du mélangeur décrit dans la réponse à
Exercice 17, page 289. Écrivez un script shell qui effectuera une
test de régression pour le mélangeur. Vous devez tester les fonctionnalités de base,
les conditions d'erreur et limites, ainsi que toutes les obligations contractuelles. Quoi
des restrictions sont placées sur le changement de vitesse ? Sont-ils
honoré?

Sorciers
Sorciers maléfiques
maléfiques

Il est indéniable que les applications deviennent de plus en plus difficiles à écrire.
Les interfaces utilisateur, en particulier, deviennent de plus en plus sophistiquées.
Il y a vingt ans, l'application moyenne aurait un télétype en verre
interface (si elle avait une interface du tout). Les terminaux asynchrones
fournissent généralement un affichage interactif de caractères, tandis que les dispositifs interrogeables
(comme l'omniprésent IBM 3270) vous permettrait de remplir un écran entier

avant de frapper . Désormais, les utilisateurs s'attendent à des interfaces utilisateur graphiques, avec
aide contextuelle, couper-coller, glisser-déposer, intégration OLE et
MDI ou SDI. Les utilisateurs recherchent une intégration de navigateur Web et un client léger
soutien.

Les applications elles-mêmes deviennent de plus en plus complexes. La plupart


les développements utilisent maintenant un modèle multiniveau, éventuellement avec un middleware
couche ou un moniteur de transaction. Ces programmes doivent être dynamiques
et flexible, et d'interopérer avec des applications écrites par des tiers.

Oh, et avons-nous mentionné que nous en avions besoin la semaine prochaine ?

Les développeurs ont du mal à suivre. Si nous utilisions le même type de


outils qui produisaient les applications de base des terminaux muets il y a 20 ans,
nous n'aurions jamais rien fait.

Ainsi, les fabricants d'outils et les fournisseurs d'infrastructures ont trouvé une solution magique
balle, l'assistant. Les sorciers sont super. Avez-vous besoin d'une application MDI avec
Prise en charge du conteneur OLE ? Cliquez simplement sur un seul bouton, répondez à quelques

des questions simples, et l'assistant générera automatiquement un squelette de code


pour toi. L'environnement Microsoft Visual C++ crée plus de 1 200 lignes de
code pour ce scénario, automatiquement. Les sorciers travaillent dur dans d'autres
contextes aussi. Vous pouvez utiliser des assistants pour créer des composants de serveur, implémenter
Java beans et gérer les interfaces réseau - tous les domaines complexes où il est
agréable d'avoir l'aide d'un expert.

Mais utiliser un assistant conçu par un gourou ne rend pas automatiquement Joe
développeur tout aussi expert. Joe peut se sentir plutôt bien—il vient de produire un
une masse de code et un programme plutôt stylé. Il ajoute simplement dans le
fonctionnalité d'application spécifique et il est prêt à être expédié. Mais à moins que Joe
comprend réellement le code qui a été produit en son nom, il est
se tromper. Il programme par hasard. Les sorciers sont à sens unique
rue - ils coupent le code pour vous, puis passent à autre chose. Si le code qu'ils
le produit n'est pas tout à fait correct, ou si les circonstances changent et que vous devez vous adapter
le code, vous êtes seul.

Nous ne sommes pas contre les sorciers. Au contraire, nous consacrons une section entière
) pour écrire le vôtre. Mais si vous utilisez un assistant et que vous
( Générateurs de codes
ne comprenez pas tout le code qu'il produit, vous ne contrôlerez pas
votre propre application. Vous ne pourrez pas l'entretenir, et vous serez
en difficulté quand vient le temps de déboguer.

Astuce
Astuce 50
50

N'utilisez pas de code d'assistant que vous ne comprenez pas

Certaines personnes pensent que c'est une position extrême. Ils disent que les développeurs
s'appuient régulièrement sur des choses qu'ils ne comprennent pas entièrement - le quantum
la mécanique des circuits intégrés, la structure d'interruption du processeur,
les algorithmes utilisés pour planifier les processus, le code dans les bibliothèques fournies,
et ainsi de suite. Nous sommes d'accord. Et nous ressentirions la même chose pour les sorciers s'ils l'étaient
simplement un ensemble d'appels de bibliothèque ou de services de système d'exploitation standard qui
les développeurs pourraient compter. Mais ils ne le sont pas. Les assistants génèrent du code qui
devient partie intégrante de la candidature de Joe. Le code de l'assistant n'est pas
pris en compte derrière une interface soignée - il est entrelacé ligne par ligne avec
fonctionnalité que Joe écrit. [4] Finalement, il cesse d'être le code de l'assistant
et commence à appartenir à Joe. Et personne ne devrait produire de code qu'il ne produit pas entièrement
comprendre.

[4] Cependant, il existe d'autres techniques qui aident à gérer la complexité. Nous en discutons deux, beans et AOP, dans Orthogoality .

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Orthogonalité
• • Générateurs de codes
Défis
Défis

• • Si vous disposez d'un assistant de création d'interface graphique, utilisez-le pour générer un
demande de squelette. Parcourez chaque ligne de code qu'il produit. Faire
tu as tout compris ? Auriez-vous pu le fabriquer vous-même ? Serait
vous l'avez produit vous-même, ou fait-il des choses dont vous n'avez pas besoin ?

Chapitre 7. Avant le projet

Avez-vous parfois le sentiment que votre projet est voué à l'échec, avant même qu'il ne démarre ?
Parfois, cela peut l'être, à moins que vous n'établissiez d'abord quelques règles de base de base.
Sinon, autant suggérer qu'il soit fermé maintenant et enregistrer
le parrain de l'argent.

Au tout début d'un projet, vous devrez déterminer les


exigences. Il ne suffit pas d'écouter les utilisateurs : lisez The
Exigences Pit pour en savoir plus.

La sagesse conventionnelle et la gestion des contraintes sont les sujets de Solving


Énigmes impossibles. Que vous exécutiez des exigences, des analyses,
codage ou test, des problèmes difficiles surgiront. La plupart du temps, ils
ne seront pas aussi difficiles qu'ils semblent l'être à première vue.

Lorsque vous pensez avoir résolu les problèmes, vous ne vous sentez peut-être toujours pas
à l'aise avec le saut et le démarrage. Est-ce une simple procrastination ou est-ce
c'est quelque chose de plus? Pas jusqu'à ce que vous soyez prêt offre des conseils sur le moment où cela peut être
prudent d'écouter cette voix d'avertissement à l'intérieur de votre tête.

Commencer trop tôt est un problème, mais attendre trop longtemps peut être encore pire. Dans
Le piège de la spécification, nous discuterons des avantages de la spécification en
exemple.
Enfin,
et nous examinerons
méthodologies certains
dans les cerclesdes pièges
et les des Peu
flèches. processus
importedeà développement
quel point c'est formels
bien pensé
c'est le cas, et quelles que soient les "meilleures pratiques" qu'elle inclut, aucune méthode ne peut
remplacer la pensée.

Une fois ces problèmes critiques réglés avant le début du projet, vous
peut être mieux placé pour éviter la "paralysie de l'analyse" et commencer réellement
votre projet réussi.

La
La fosse
fosse aux
aux exigences
exigences

La perfection est atteinte, non pas lorsqu'il n'y a plus rien à ajouter, mais lorsqu'il
il n'y a plus rien à enlever....

Antoine
Antoine de
de Saint-Exupéry,
Saint-Exupéry, Vent,
Vent, sable
sable et
et étoiles,
étoiles, 1939
1939

De nombreux livres et didacticiels font référence à la collecte des exigences au début


étape du projet. Le mot "rassemblement" semble impliquer une tribu de joyeux
analystes, à la recherche de pépites de sagesse gisant par terre

autour d'eux tandis que la Symphonie pastorale joue doucement en arrière-plan.


"Rassembler" implique que les exigences sont déjà là - vous avez besoin
trouvez-les simplement, placez-les dans votre panier et partez joyeusement.

Cela ne fonctionne pas tout à fait de cette façon. Les exigences se situent rarement à la surface.
Normalement, ils sont enterrés profondément sous des couches d'hypothèses,
les idées fausses et la politique.

Astuce
Astuce 51
51

Ne rassemblez pas les exigences - creusez pour elles

Creuser
Creuser pour
pour les
les besoins
besoins

Comment pouvez-vous reconnaître une véritable exigence alors que vous creusez à travers tous
la saleté environnante? La réponse est à la fois simple et complexe.

La réponse simple est qu'une exigence est une déclaration de quelque chose qui
doit être accompli. Les bonnes exigences peuvent inclure les éléments suivants :

• • Un dossier d'employé ne peut être consulté que par un groupe désigné de


personnes.
• • La température de la culasse ne doit pas dépasser la température critique
valeur, qui varie selon le moteur.
• • L'éditeur mettra en surbrillance les mots clés, qui seront sélectionnés
selon le type de fichier en cours d'édition.

Cependant, très peu d'exigences sont aussi claires, et c'est ce qui fait que
complexe d'analyse des besoins.

La première déclaration de la liste ci-dessus peut avoir été déclarée par les utilisateurs comme
"Seuls les superviseurs d'un employé et le service du personnel peuvent voir
les dossiers de cet employé. » Cette déclaration est-elle vraiment une exigence ? Peut-être
aujourd'hui, mais il inscrit la politique commerciale dans un énoncé absolu. Stratégies
changer régulièrement, donc nous ne voulons probablement pas les lier à notre
exigences. Notre recommandation est de documenter ces politiques
séparément de l'exigence, et créez un lien hypertexte entre les deux. Faire le
exigence la déclaration générale, et donner aux développeurs la politique
informations comme exemple du type de chose qu'ils devront prendre en charge dans le
mise en œuvre. Finalement, la politique peut se retrouver sous forme de métadonnées dans le
application.
Il s'agit d'une distinction relativement subtile, mais qui aura de profondes répercussions
conséquences pour les développeurs. Si l'exigence est indiquée comme "uniquement
le personnel peut voir un dossier d'employé", le développeur peut finir par coder
un test explicite à chaque fois que l'application accède à ces fichiers. Toutefois, si
la déclaration est "Seuls les utilisateurs autorisés peuvent accéder au dossier d'un employé",
le développeur concevra et implémentera probablement une sorte d'accès
Système de contrôle. Lorsque la politique change (et ce sera le cas), seules les métadonnées de
ce système devra être mis à jour. En fait, la collecte des exigences dans ce
chemin vous mène naturellement à un système bien conçu pour prendre en charge
métadonnées.

Les distinctions entre les exigences, la politique et la mise en œuvre peuvent


très flou lorsque les interfaces utilisateur sont discutées. "Le système doit vous permettre
choisir une durée de prêt" est une déclaration d'exigence. "Nous avons besoin d'une zone de liste pour
sélectionner la durée du prêt" peut l'être ou non. Si les utilisateurs doivent absolument disposer d'un
zone de liste, alors c'est une exigence. Si, au lieu de cela, ils décrivent la capacité de
choisissez, mais utilisez la liste déroulante comme exemple, alors ce n'est peut-être pas le cas. La boîte sur
La page 205 traite d'un projet qui a terriblement mal tourné parce que les utilisateurs
les besoins d'interface ont été ignorés.

Il est important de découvrir la raison sous-jacente pour laquelle les utilisateurs font une action particulière
chose, plutôt que simplement la façon dont ils le font actuellement. À la fin de la journée,
votre développement doit résoudre leur problème commercial, pas seulement répondre à leur
exigences énoncées. Documenter les raisons qui sous-tendent les exigences
donnez à votre équipe des informations précieuses lors de la mise en œuvre quotidienne
les décisions.

Il existe une technique simple pour entrer dans les exigences de vos utilisateurs qui
n'est pas assez utilisé : devenez utilisateur. Êtes-vous en train d'écrire un système pour
bureau d'aide? Passez quelques jours à surveiller les téléphones avec un
personne de soutien expérimentée. Automatisez-vous un contrôle manuel des stocks
système? Travail dans l'entrepôt pendant une [1] En plus de vous donner un aperçu
semaine.
comment le système sera réellement utilisé, vous seriez étonné de voir comment la demande
"Puis-je m'asseoir pendant une semaine pendant que vous faites votre travail?" contribue à instaurer la confiance et
établit une base de communication avec vos utilisateurs. Rappelez-vous juste que non
se mettre en travers !

[1] Est-ce qu'une semaine vous semble longue ? Ce n'est vraiment pas le cas, en particulier lorsqu'il s'agit de processus dans lesquels la direction

et les travailleurs occupent des mondes différents. La direction vous donnera une vue d'ensemble de la façon dont les choses fonctionnent, mais lorsque vous descendez
sur le sol, vous trouverez une réalité très différente, une réalité qui prendra du temps à assimiler.

Astuce
Astuce 52
52

Travailler avec un utilisateur pour penser comme un utilisateur

Le processus d'exploration des exigences est également le moment de commencer à établir un rapport
avec votre base d'utilisateurs, en apprenant leurs attentes et leurs espoirs pour le système
vous construisez. Voir de grandes attentes, pour plus.

Exigences
Exigences de
de documentation
documentation

Donc, vous vous asseyez avec les utilisateurs et vous vous interrogez sur les véritables exigences
d'eux. Vous rencontrez quelques scénarios probables qui décrivent ce que
l'application doit faire. Toujours le professionnel, vous voulez les écrire
et publier un document que chacun pourra utiliser comme base pour
discussions - les développeurs, les utilisateurs finaux et les sponsors du projet.
C'est un public assez large.

Ivar Jacobson [ Jac94] a proposé le concept de cas d'utilisation pour capturer


exigences. Ils vous permettent de décrire une utilisation particulière du système, pas dans
termes d'interface utilisateur, mais de manière plus abstraite. Malheureusement,
Le livre de Jacobson était un peu vague sur les détails, il y a donc maintenant beaucoup
différentes opinions sur ce que devrait être un cas d'utilisation. Est-ce formel ou informel,
texte simple ou document structuré (comme un formulaire) ? Quel est le niveau de détail
approprié (rappelez-vous que nous avons un large public) ?

Parfois, l'interface est le système

Dans un article du magazine Wired (janvier 1999, page 176), le producteur


et le musicien Brian Eno ont décrit un morceau incroyable de
technologie - la table de mixage ultime. Il fait n'importe quoi pour sonner
cela peut être fait. Et pourtant, au lieu de laisser les musiciens faire mieux
musique, ou produire un enregistrement plus rapidement ou à moindre coût, il entre dans
le chemin; cela perturbe le processus de création.

Pour comprendre pourquoi, il faut regarder comment travaillent les ingénieurs du son. Ils
équilibrer les sons intuitivement. Au fil des ans, ils développent un sens inné
boucle de rétroaction entre leurs doigts—faders coulissants, rotation
boutons, etc. Cependant, l'interface de la nouvelle table de mixage n'a pas
tirer parti de ces capacités. Au lieu de cela, il forçait ses utilisateurs à taper sur un
clavier ou cliquez sur une souris. Les fonctions qu'il offrait étaient
complets, mais ils ont été emballés dans des termes inconnus et exotiques
façons. Les fonctions dont les ingénieurs avaient besoin étaient parfois cachées
derrière des noms obscurs, ou ont été obtenus avec des

combinaisons d'installations de base.

Cet environnement doit tirer parti des ensembles de compétences existants.


Alors que dupliquer servilement ce qui existe déjà ne permet pas
progrès, nous devons être en mesure d'assurer une transition vers l'avenir.

Par exemple, les ingénieurs du son auraient peut-être été mieux servis
par une sorte d'interface à écran tactile - toujours tactile, toujours montée comme
une table de mixage traditionnelle pourrait être, tout en permettant au logiciel d'aller
au-delà du domaine des boutons et interrupteurs fixes. Fournir un
transition confortable à travers des métaphores familières est une façon de
aider à obtenir l'adhésion.

Cet exemple illustre également notre conviction que les outils performants s'adaptent
aux mains qui les utilisent. Dans ce cas, ce sont les outils que vous construisez
pour d'autres qui doivent être adaptables.

Une façon d'examiner les cas d'utilisation consiste à souligner leur nature axée sur les objectifs.
Alistair Cockburn a un article qui décrit cette approche, ainsi que
modèles pouvant être utilisés (strictement ou non) comme point de départ],([ Coc97a
également en ligne sur [ URL 46 ]). La figure 7.1 sur la page suivante montre un
exemple abrégé de son modèle, tandis que la figure 7.2 montre son exemple d'utilisation
cas.

Illustration
Illustration 7.1.
7.1. Modèle
Modèle de
de cas
cas d'utilisation
d'utilisation de
de Cockburn
Cockburn
Illustration
Illustration 7.2.
7.2. Un
Un exemple
exemple de
de cas
cas d'utilisation
d'utilisation
En utilisant un modèle formel comme aide-mémoire, vous pouvez être sûr que vous
inclure toutes les informations dont vous avez besoin dans un cas d'utilisation : performances
caractéristiques, autres parties impliquées, priorité, fréquence et divers
erreurs et exceptions qui peuvent survenir ("exigences non fonctionnelles"). Ce
est également un endroit idéal pour enregistrer les commentaires des utilisateurs tels que "oh, sauf si nous obtenons un
condition xxx, alors nous devons faire yyy à la place." Le modèle sert également de
un agenda prêt à l'emploi pour les réunions avec vos utilisateurs.

Ce type d'organisation soutient la structuration hiérarchique de l'utilisation


cas—imbriquer des cas d'utilisation plus détaillés dans des cas d'utilisation de niveau supérieur. Pour
Par exemple, le post-débit et le post-crédit élaborent tous deux sur la post-transaction.

Diagrammes
Diagrammes de
de cas
cas d'utilisation
d'utilisation

Le flux de travail peut être capturé avec des diagrammes d'activité UML, et
les diagrammes de classes au niveau conceptuel peuvent parfois être utiles pour modéliser
affaire à portée de main. Mais les vrais cas d'utilisation sont des descriptions textuelles, avec un
hiérarchie et liens croisés. Les cas d'utilisation peuvent contenir des hyperliens vers d'autres utilisations
cas, et ils peuvent être imbriqués les uns dans les autres.

Il nous semble incroyable que quelqu'un envisage sérieusement de documenter


des informations aussi denses en utilisant uniquement des personnes simplistes
. telles que la figure 7.3
Ne soyez esclave d'aucune notation ; utiliser la méthode qui communique le mieux
les exigences avec votre public.

Illustration
Illustration 7.3.
7.3. Cas
Cas d'utilisation
d'utilisation UML
UML -- si
si simple
simple qu'un
qu'un enfant
enfant pourrait
pourrait le
le faire
faire !!
Surspécification
Surspécification

Un grand danger dans la production d'un document d'exigences est d'être trop spécifique.
Les bons documents d'exigences restent abstraits. Où les exigences sont
concerné, la déclaration la plus simple qui reflète fidèlement l'entreprise
le besoin est le meilleur. Cela ne veut pas dire que vous pouvez être vague—vous devez capturer le
invariants sémantiques sous-jacents en tant qu'exigences, et documenter les
ou les pratiques de travail actuelles comme politique.

Les exigences ne sont pas l'architecture. Les exigences ne sont pas de conception, ni
ils l'interface utilisateur. Les exigences sont nécessaires.

Voir
Voir plus
plus loin
loin

Le problème de l'an 2000 est souvent imputé aux programmeurs à courte vue,
désespéré d'économiser quelques octets à l'époque où les mainframes avaient moins
mémoire qu'une télécommande de télévision moderne.

Mais ce n'était pas le fait des programmeurs, et ce n'était pas vraiment une utilisation de la mémoire
problème. Au contraire, c'était la faute des analystes et des concepteurs du système. L'an 2000

problème est survenu à partir de deux causes principales : une incapacité à voir au-delà du courant
pratique commerciale et une violation du principe DRY.

Les entreprises utilisaient le raccourci à deux chiffres bien avant l'arrivée des ordinateurs
sur la scène. C'était une pratique courante. Le premier traitement de données
applications n'ont fait qu'automatiser les processus métier existants, et simplement
répété l'erreur. Même si l'architecture nécessitait des années à deux chiffres pour
saisie de données, rapport et stockage, il aurait dû y avoir une abstraction de
unDATE qui "savait" que les deux chiffres étaient une forme abrégée de la date réelle.

Astuce
Astuce 53
53

Les abstractions vivent plus longtemps que les détails

Est-ce que « voir plus loin » vous oblige à prédire l'avenir ? Non. Cela signifie
générer des déclarations telles que

Le système utilise activement une abstraction de DATE. Le système va


mettre en œuvre les services DATE, tels que le formatage, le stockage et les mathématiques
opérations, de manière cohérente et universelle.

Les exigences préciseront seulement que les dates sont utilisées. Cela peut laisser entendre que
certains calculs peuvent être effectués sur les dates. Il peut vous dire que les dates seront stockées
sur diverses formes de stockage secondaire. Ce sont de véritables exigences pour
unModule ou classe DATE.

Juste
Juste une
une autre
autre menthe
menthe ultra-mince…
ultra-mince…

De nombreux échecs de projets sont imputés à une augmentation de la portée, également appelée
fonctionnalité gonflement, featurism rampant, ou fluage des exigences. C'est un aspect
du syndrome de la grenouille bouillie de Stone Soup et Boiled Frogs
. Ce qui peut
faisons-nous pour éviter que les exigences ne nous envahissent ?

Dans la littérature, vous trouverez des descriptions de nombreuses métriques, telles que les bugs
rapportés et corrigés, densité de défauts, cohésion, couplage, points de fonction, lignes
de code, etc. Ces métriques peuvent être suivies manuellement ou avec un logiciel.

Malheureusement, peu de projets semblent suivre activement les exigences. Ce


signifie qu'ils n'ont aucun moyen de rendre compte des changements de périmètre - qui a demandé
une fonctionnalité, qui l'a approuvée, le nombre total de demandes approuvées, etc.
La clé dede
l'impact la la
gestion de la croissance
fonctionnalité des besoins
sur le calendrier est de signaler
des sponsors chaque
du projet. nouvelle
Lorsque le projet est

un an de retard par rapport aux estimations initiales et les accusations commencent à voler, il peut être
utile d'avoir une image précise et complète de comment et quand,
la croissance des besoins s'est produite.

Il est facile de se laisser entraîner dans le maelström "juste une fonctionnalité de plus", mais en
exigences de suivi, vous pouvez obtenir une image plus claire que "juste un de plus
feature" est vraiment la quinzième nouvelle fonctionnalité ajoutée ce mois-ci.

Maintenir
Maintenir un
un glossaire
glossaire

Dès que vous commencez à discuter des exigences, les utilisateurs et les experts du domaine
utiliseront certains termes qui ont une signification particulière pour eux. Ils peuvent
faire la différence entre un « client » et un « client », par exemple. Ce serait
alors être inapproprié d'utiliser l'un ou l'autre mot avec désinvolture dans le système.

Créer et maintenir un glossaire de projet—un endroit qui définit tous les


termes et vocabulaire spécifiques utilisés dans un projet. Tous les participants à la
projet, des utilisateurs finaux au personnel de support, doivent utiliser le glossaire pour s'assurer
cohérence. Cela implique que le glossaire doit être largement accessible - un
bon argument pour la documentation basée sur le Web (plus à ce sujet dans un instant).

Astuce
Astuce 54
54

Utiliser un glossaire de projet

Il est très difficile de réussir un projet où les utilisateurs et les développeurs se réfèrent
à la même chose par des noms différents ou, pire encore, faire référence à différents
choses du même nom.

Faire
Faire passer
passer le
le mot
mot

Dans It's All Writing , nous discutons de la publication de documents de projet en interne
Sites Web pour un accès facile par tous les participants. Ce mode de distribution est
particulièrement utile pour les documents d'exigences.

En présentant les exigences sous forme de document hypertexte, nous pouvons mieux
répondre aux besoins d'un public diversifié - nous pouvons donner à chaque lecteur ce
Ils veulent. Les sponsors du projet peuvent naviguer à un niveau élevé d'abstraction pour
s'assurer que les objectifs commerciaux sont atteints. Les programmeurs peuvent utiliser des hyperliens
pour "explorer" à des niveaux de détail croissants (même en référençant
définitions ou spécifications techniques).

La distribution sur le Web évite également le classeur typique de deux pouces d'épaisseur
intitulé Analyse des besoins que personne ne lit jamais et qui devient
obsolète l'encre instantanée frappe le papier.

Si c'est sur le Web, les programmeurs peuvent même le lire.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Soupe aux cailloux et grenouilles bouillies


• • Logiciel suffisamment bon
• • Cercles et flèches
• • Tout est écrit
• • De grandes attentes

Défis
Défis

• • Pouvez-vous utiliser le logiciel que vous écrivez ? Est-il possible d'avoir un


bon ressenti des besoins sans pouvoir utiliser le logiciel
toi-même?
• • Choisissez un problème non lié à l'informatique que vous devez actuellement résoudre.
Générer des exigences pour une solution non informatique.

Des
Des exercices
exercices

42.
42. Parmi les exigences suivantes, lesquelles sont probablement de véritables exigences ? Reformuler
ceux qui ne le sont pas pour les rendre plus utiles (si possible) .

1. 1. Le temps de réponse doit être inférieur à 500 ms.


2. 2. Les boîtes de dialogue auront un fond gris.
3. 3. L'application sera organisée en plusieurs interfaces
processus et un serveur principal.
4. 4. Si un utilisateur saisit des caractères non numériques dans un champ numérique,
le système émettra un bip et ne les acceptera pas.
5. 5. Le code d'application et les données doivent tenir dans 256 Ko.

Résoudre
Résoudre des
des énigmes
énigmes impossibles
impossibles

Gordius, le roi de Phrygie, a un jour noué un nœud que personne ne pouvait dénouer. Il
On disait que celui qui résoudrait l'énigme du nœud gordien régnerait sur tout
Asie. Ainsi arrive Alexandre le Grand, qui coupe le nœud en morceaux avec

son épée. Juste une interprétation un peu différente des exigences, c'est
tout… et il a fini par diriger la majeure partie de l'Asie.

De temps à autre, vous vous retrouverez mêlé au milieu d'une


projet lorsqu'un casse-tête vraiment difficile surgit : une pièce d'ingénierie qui
vous ne pouvez tout simplement pas maîtriser, ou peut-être un morceau de code qui tourne
être beaucoup plus difficile à écrire que vous ne le pensiez. Peut-être que cela semble impossible.
Mais est-ce vraiment aussi difficile qu'il n'y paraît ?

Considérez les puzzles du monde réel - ces petits morceaux de bois sournois, le fer forgé,
ou du plastique qui semblent se présenter comme cadeaux de Noël ou dans les vide-greniers. Tous
il suffit de retirer l'anneau, ou de mettre les pièces en forme de T dans la boîte, ou
peu importe.

Alors vous tirez sur l'anneau, ou essayez de mettre les T dans la boîte, et découvrez rapidement
que les solutions évidentes ne fonctionnent tout simplement pas. Le puzzle ne peut être résolu que
chemin. Mais même si c'est évident, cela n'empêche pas les gens d'essayer le
la même chose - encore et encore - en pensant qu'il doit y avoir un moyen.

Bien sûr, il n'y en a pas. La solution est ailleurs. Le secret pour résoudre le
puzzle est d'identifier les contraintes réelles (non imaginées) et de trouver une solution
la bride. Certaines contraintes sont absolues ; d'autres sont simplement préconçus
notions. Les contraintes absolues doivent être honorées, même si elles sont désagréables ou
stupides qu'ils peuvent sembler être. D'autre part, certains apparents
les contraintes peuvent ne pas être du tout de vraies contraintes. Par exemple, il y a ce vieux
truc de bar où vous prenez une bouteille de champagne neuve et non ouverte et pariez
que vous pouvez en boire de la bière. L'astuce consiste à retourner la bouteille,
et versez une petite quantité de bière dans le creux au fond de la bouteille.
De nombreux problèmes logiciels peuvent être tout aussi sournois.

Degrés
Degrés de
de liberté
liberté
L'expression à la mode populaire "sortir des sentiers battus" nous encourage à
reconnaître les contraintes qui pourraient ne pas s'appliquer et les ignorer.

Mais cette phrase n'est pas tout à fait exacte. Si la "boîte" est la limite de
contraintes et conditions, alors l'astuce consiste à trouver la boîte, qui peut être
considérablement plus grand que vous ne le pensez.

La clé pour résoudre des énigmes est à la fois de reconnaître les contraintes qui vous sont imposées
et de reconnaître les degrés de liberté que vous avez, car dans ceux-ci vous trouverez
votre résolution. C'est pourquoi certains puzzles sont si efficaces ; vous pouvez renvoyer
solutions potentielles trop facilement.

Par exemple, pouvez-vous relier tous les points du puzzle suivant et


revenir au point de départ avec seulement trois lignes droites, sans soulever
votre stylo du papier ou revenir sur vos pas [ Hol78 ]?

Vous devez remettre en question toute idée préconçue et évaluer si oui ou non
ce sont de vraies contraintes dures et rapides.

Ce n'est pas si vous pensez à l'intérieur de la boîte ou à l'extérieur de la boîte. Le problème


consiste à trouver la boîte, à identifier les contraintes réelles.

Astuce
Astuce 55
55

Ne sortez pas des sentiers battus—Trouvez la boîte

Face à un problème insoluble, énumérer toutes les possibilités


avenues que vous avez devant vous. Ne rejetez rien, peu importe comment
inutilisable ou stupide, il semble. Parcourez maintenant la liste et expliquez pourquoi un
certain chemin ne peut pas être pris. Es-tu sûr? Tu peux le prouver?

Considérez le cheval de Troie, une nouvelle solution à un problème insoluble. Comment


envoyer des troupes dans une ville fortifiée sans être découvert ? Tu veux parier
que "par la porte d'entrée" a été initialement rejeté comme un suicide.

Catégorisez et hiérarchisez vos contraintes. Lorsque les menuisiers commencent une


projet, ils coupent d'abord les morceaux les plus longs, puis coupent les plus petits morceaux de
le bois restant. De la même manière, nous voulons identifier les plus
contraintes restrictives en premier, et y insérer les contraintes restantes.

Soit dit en passant, une solution au puzzle des quatre poteaux est présentée à la page 307.

IlIl doit
doit yy avoir
avoir un
un moyen
moyen plus
plus simple
simple !!

Parfois, vous vous retrouverez à travailler sur un problème qui semble beaucoup
plus difficile que vous ne le pensiez. Peut-être que tu as l'impression de tomber
le mauvais chemin - qu'il doit y avoir un chemin plus facile que celui-ci ! Peut-être toi
sont en retard sur le calendrier maintenant, ou même désespèrent d'obtenir un jour le
système fonctionne parce que ce problème particulier est "impossible".
C'est alors que vous reculez d'un pas et que vous vous posez ces questions :

• • Existe-t-il un moyen plus simple ?


• • Essayez-vous de résoudre le bon problème, ou avez-vous été
distrait par une technicité périphérique ?
• • Pourquoi cette chose est-elle un problème ?
• • Qu'est-ce qui le rend si difficile à résoudre ?
• • Doit-il être fait de cette façon ?
• • Doit-il être fait du tout ?

Plusieurs fois, une révélation surprenante viendra à vous alors que vous essayez de répondre
une de ces questions. Plusieurs fois une réinterprétation des exigences
peut faire disparaître toute une série de problèmes, tout comme le nœud gordien.

Tout ce dont vous avez besoin, ce sont les contraintes réelles, les contraintes trompeuses et les
la sagesse de connaître la différence.

Défis
Défis

• • Examinez attentivement le problème difficile que vous rencontrez


embrouillé aujourd'hui. Pouvez-vous couper le nœud gordien? Demandez-vous le
questions clés que nous avons décrites ci-dessus, en particulier "Faut-il le faire
Par ici?"
• • Avez-vous reçu un ensemble de contraintes lorsque vous vous êtes connecté à votre
Projet en cours? Sont-elles toujours applicables et l'interprétation est-elle
d'entre eux encore valides?

Pas
Pas tant
tant que
que vous
vous n'êtes
n'êtes pas
pas prêt
prêt

Celui qui hésite est parfois sauvé.

James
James Thurber,
Thurber, Le
Le verre
verre dans
dans le
le champ
champ

Les grands artistes partagent un trait : ils savent quand commencer et quand attendre.
Le plongeur se tient debout sur la planche haute, attendant le moment idéal pour sauter.
La chef d'orchestre se tient devant l'orchestre, les bras levés, jusqu'à ce qu'elle perçoive
que le moment est venu de commencer la pièce.

Vous êtes un grand interprète. Toi aussi tu dois écouter la voix qui chuchote
"attendez." Si vous vous asseyez pour commencer à taper et qu'il y a un doute persistant dans
votre esprit, tenez-en compte.

Astuce
Astuce 56
56

Écoutez Nagging Doubts—Commencez quand vous êtes prêt

Il y avait autrefois un style d'entraînement de tennis appelé "tennis intérieur". Vous feriez
passer des heures à frapper des balles par-dessus le filet, sans chercher particulièrement à être précis,
mais plutôt verbaliser juste où la balle a frappé par rapport à une cible (souvent
une chaise). L'idée était que la rétroaction formerait votre subconscient et
réflexes, de sorte que vous vous êtes amélioré sans savoir consciemment comment ni pourquoi.

En tant que développeur, vous avez fait le même genre de choses pendant toute votre
carrière. Vous avez essayé des choses et vu lesquelles fonctionnaient et lesquelles
n'a pas. Vous avez accumulé de l'expérience et de la sagesse. Quand tu ressens un
un doute lancinant ou une certaine réticence face à une tâche, tenez compte
il. Vous ne pourrez peut-être pas mettre le doigt sur exactement ce qui ne va pas, mais donnez
il est temps et vos doutes se cristalliseront probablement en quelque chose de plus solide,
quelque chose que vous pouvez aborder. Le développement logiciel n'est toujours pas une science. Laisser
votre instinct contribue à votre performance.

Bon
Bon jugement
jugement ou
ou procrastination
procrastination ??
Tout le monde a peur de la feuille blanche. Commencer un nouveau projet (ou même un
nouveau module dans un projet existant) peut être une expérience déconcertante. Un grand nombre de
nous préférerions remettre à plus tard l'engagement initial de commencer. Donc
comment pouvez-vous savoir quand vous procrastinez simplement, plutôt que
attendre de manière responsable que toutes les pièces se mettent en place ?

Une technique qui a fonctionné pour nous dans ces circonstances est de commencer
prototypage. Choisissez un domaine qui, selon vous, sera difficile et commencez
produisant une sorte de preuve de concept. L'une des deux choses sera généralement
arriver. Peu de temps après le démarrage, vous pouvez avoir l'impression de perdre votre temps.
Cet ennui est probablement une bonne indication que votre réticence initiale était
juste un désir de reporter l'engagement de commencer. Abandonner le prototype,
et pirater le développement réel.

D'un autre côté, au fur et à mesure que le prototype progresse, vous pouvez avoir l'un de ces
des moments de révélation où vous réalisez soudainement que certaines prémisses de base
avait tort. Non seulement cela, mais vous verrez clairement comment vous pouvez y remédier.
Vous vous sentirez à l'aise d'abandonner le prototype et de vous lancer dans la
projet proprement dit. Vos instincts étaient bons, et vous venez de vous sauver et
votre équipe une quantité considérable d'efforts inutiles.

Lorsque vous prenez la décision de prototyper comme moyen d'étudier votre


malaise, assurez-vous de vous rappeler pourquoi vous le faites. La dernière chose que tu veux c'est
se retrouver plusieurs semaines dans un développement sérieux avant
rappelant que vous avez commencé à écrire un prototype.

Un peu cyniquement, commencer à travailler sur un prototype pourrait aussi être plus
politiquement acceptable que d'annoncer simplement que "je ne me sens pas bien
démarrage" et allumage s

Défis
Défis

• • Discutez du syndrome de la peur de commencer avec vos collègues. Faire


d'autres vivent la même chose? En tiennent-ils compte ? Quelles astuces font
qu'ils utilisent pour le surmonter? Un groupe peut-il aider à surmonter les
réticence, ou est-ce simplement la pression des pairs?

Le
Le piège
piège des
des spécifications
spécifications

Le pilote d'atterrissage est le pilote non-pilote jusqu'à "l'altitude de décision"


appel, lorsque le pilote non atterrisseur manipulant remet la manipulation au
Non-Handling Landing Pilot, à moins que ce dernier n'annonce une remise des gaz, dans laquelle
cas où le pilote non atterrisseur en maniement continue de s'envoler et le
Le pilote d'atterrissage sans pilotage continue de ne pas piloter jusqu'au prochain appel de
« atterrir » ou « remettre les gaz », selon le cas. Compte tenu des confusions récentes sur ces
règles, il a été jugé nécessaire de les réaffirmer clairement.

Mémorandum
Mémorandum de
de British
British Airways,
Airways, cité
cité dans
dans Pilot
Pilot Magazine,
Magazine, décembre
décembre 1996
1996

La spécification du programme est le processus qui consiste à prendre une exigence et à réduire
jusqu'au point où les compétences d'un programmeur peuvent prendre le dessus. C'est un acte de
communication, expliquant et clarifiant le monde de manière à
lever les principales ambiguïtés. En plus de parler au développeur qui sera
effectuant la mise en œuvre initiale, la spécification est un record pour
les futures générations de programmeurs qui maintiendront et amélioreront
le code. La spécification est également un accord avec l'utilisateur—un
codification de leurs besoins et un contrat implicite que le système final
être conforme à cette exigence.

Rédiger un cahier des charges est une lourde responsabilité.

Le problème est que de nombreux designers ont du mal à s'arrêter. Ils sentent que
à moins que chaque petit détail ne soit épinglé dans des détails atroces, ils ne l'ont pas fait
gagné leur dollar quotidien.

C'est une erreur pour plusieurs raisons. Premièrement, il est naïf de supposer qu'un
spécification capturera jamais chaque détail et nuance d'un système ou de ses
exigence. Dans des domaines de problèmes restreints, il existe des méthodes formelles qui
peuvent décrire un système, mais ils nécessitent toujours que le concepteur explique le
signification de la notation pour les utilisateurs finaux - il y a toujours un humain

l'interprétation va gâcher les choses. Même sans les problèmes


inhérent à cette interprétation, il est très peu probable que l'utilisateur moyen
sait exactement ce dont il a besoin pour participer à un projet. Ils peuvent dire qu'ils ont
une compréhension de l'exigence, et ils peuvent signer le
document de 200 pages que vous produisez, mais vous pouvez garantir qu'une fois qu'ils verront
le système en cours d'exécution, vous serez inondé de demandes de modification.

Deuxièmement, il y a un problème avec le pouvoir expressif du langage lui-même. Tous


les techniques de schématisation et les méthodes formelles reposent encore sur des
expressions linguistiques des opérations à effectuer. [2] Et naturel
la langue n'est vraiment pas à la hauteur. Regardez le libellé de n'importe quel contrat : dans
pour tenter d'être précis, les avocats doivent plier le langage au maximum
manières non naturelles.

[2] Il existe des techniques formelles qui tentent d'exprimer les opérations de manière algébrique, mais ces techniques sont rarement

utilisé dans la pratique. Ils exigent toujours que les analystes expliquent le sens aux utilisateurs finaux.

Voici un défi pour vous. Rédigez une courte description qui indique à quelqu'un comment
faire des nœuds à leurs lacets. Allez-y, essayez-le!

Si vous êtes comme nous, vous avez probablement abandonné quelque part autour de "maintenant
rouler le pouce et l'index de manière à ce que l'extrémité libre passe sous et à l'intérieur
le lacet gauche..." C'est une chose incroyablement difficile à faire. Et pourtant la plupart d'entre nous
peut attacher nos chaussures sans pensée consciente.

Astuce
Astuce 57
57

Certaines choses sont mieux faites que décrites

Enfin, il y a l'effet camisole de force. Une conception qui ne laisse pas le codeur
place à l'interprétation prive l'effort de programmation de toute compétence et de tout art.
Certains diront que c'est pour le mieux, mais ils se trompent. Souvent, ce n'est que
lors du codage que certaines options deviennent apparentes. Pendant le codage, vous pouvez
pensez "Regardez ça. En raison de la façon particulière dont j'ai codé cette routine, je
pourrait ajouter cette fonctionnalité supplémentaire sans presque aucun effort" ou "Le
la spécification dit de le faire, mais je pourrais obtenir un résultat presque identique
en le faisant d'une manière différente, et je pourrais le faire en deux fois moins de temps." De toute évidence, vous
ne devrait pas simplement pirater et apporter les modifications, mais vous n'auriez même pas
repéré l'opportunité si vous étiez contraint par un trop prescriptif
conception.

En tant que programmeur pragmatique, vous devriez avoir tendance à afficher les exigences
la collecte, la conception et la mise en œuvre comme différentes facettes de la même

processus—la livraison d'un système de qualité. Méfiez-vous des environnements où


les exigences sont rassemblées, les spécifications sont écrites, puis codées
démarre, le tout isolément. Au lieu de cela, essayez d'adopter une approche transparente :
la spécification et la mise en œuvre sont simplement des aspects différents de la même
processus - une tentative de capturer et de codifier une exigence. Chacun devrait couler
directement dans le suivant, sans frontières artificielles. Vous constaterez qu'un
un processus
et les de le
tests dans développement
processus de sain encourage les commentaires de la mise en œuvre
spécification.

Juste pour être clair, nous ne sommes pas contre la génération de spécifications. En effet, nous
reconnaître qu'il y a des moments où des spécifications incroyablement détaillées sont
exigé - pour des raisons contractuelles, en raison de l'environnement dans lequel vous
travail, ou en raison de la nature du produit que vous développez. [3] Sois juste
conscient que vous atteignez un point de rendements décroissants, voire négatifs,
les spécifications deviennent de plus en plus détaillées. Faites également attention à
spécifications de construction superposées aux spécifications, sans aucune
soutenir la mise en œuvre ou le prototypage ; c'est trop facile à préciser
quelque chose qui ne peut pas être construit.

[3] Les spécifications détaillées sont clairement appropriées pour les systèmes vitaux. Nous estimons qu'ils devraient également être produits pour

interfaces et bibliothèques utilisées par d'autres. Lorsque toute votre sortie est considérée comme un ensemble d'appels de routine, vous feriez mieux de vous assurer

ces appels sont bien spécifiés.

Plus longtemps vous permettez aux spécifications d'être des couvertures de sécurité, protégeant
développeurs du monde effrayant de l'écriture de code, plus il sera difficile de
passer au piratage de code. Ne tombez pas dans cette spirale de spécifications : à certains
point, vous devez commencer à coder ! Si vous trouvez votre équipe complètement enveloppée dans
spécifications chaleureuses et confortables, sortez-les. Regardez le prototypage, ou
envisager le développement d'une balle traçante.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Balles traçantes

Défis
Défis

• • L'exemple de lacet mentionné dans le texte est un exemple intéressant


illustration des problèmes des descriptions écrites. Avez-vous considéré
décrivant le processus à l'aide de diagrammes plutôt que de mots ?
Photographies? Une notation formelle de la topologie ? Modèles avec fil
lacets? Comment enseigneriez-vous à un tout-petit?

Parfois, une image vaut plus que n'importe quel nombre de mots.
Parfois ça ne vaut rien. Si vous vous surprenez à trop spécifier, est-ce que
des images ou des notations spéciales aident? À quel point doivent-ils être détaillés ?
Quand un outil de dessin est-il meilleur qu'un tableau blanc ?

Cercles
Cercles et
et flèches
flèches

[photographies] avec des cercles et des flèches et un paragraphe au dos de chacune


un expliquant ce que chacun était, pour être utilisé comme preuve contre nous…

Arlo
Arlo Guthrie,
Guthrie, "Le
"Le restaurant
restaurant d'Alice"
d'Alice"

De la programmation structurée aux équipes de programmeurs en chef, CASE


outils, développement en cascade, modèle en spirale, Jackson, diagrammes ER,
Booch clouds, OMT, Objectory et Coad/Yourdon, jusqu'à l'UML d'aujourd'hui,
l'informatique n'a jamais été à court de méthodes destinées à rendre la programmation
plutôt de l'ingénierie. Chaque méthode rassemble ses disciples, et chacune jouit d'un
période de popularité. Puis chacun est remplacé par le suivant. De tous,
peut-être que seul le premier – la programmation structurée – a connu une longue vie.

Pourtant, certains développeurs, à la dérive dans une mer de projets en perdition, continuent de s'accrocher au
dernière mode au moment où les naufragés s'accrochent au bois flotté qui passe. Comme chacun
une nouvelle pièce flotte, ils nagent péniblement, espérant que ce sera mieux. Au
fin de la journée, cependant, peu importe la qualité de l'épave, le
les développeurs sont toujours à la dérive sans but.

Ne vous méprenez pas. Nous aimons (certaines) techniques et méthodes formelles. Mais nous
croire qu'adopter aveuglément n'importe quelle technique sans la mettre dans le
contexte de vos pratiques et capacités de développement est une recette pour
déception.

Astuce
Astuce 58
58

Ne soyez pas esclave des méthodes formelles

Les méthodes formelles présentent de sérieuses lacunes.

• • La plupart des méthodes formelles capturent les exigences en utilisant une combinaison
de schémas et quelques mots d'appui. Ces images représentent
la compréhension des exigences par les concepteurs. Cependant dans de nombreux
cas, ces diagrammes n'ont aucun sens pour les utilisateurs finaux, de sorte que le
les concepteurs doivent les interpréter. Il n'y a donc pas vraiment de formalité
vérification des exigences par l'utilisateur effectif du

système - tout est basé sur les explications des concepteurs, tout comme
dans les exigences écrites démodées. Nous voyons un certain avantage dans
capturer les besoins de cette façon, mais nous préférons, dans la mesure du possible,
montrez à l'utilisateur un prototype et laissez-le jouer avec.
• • Les méthodes formelles semblent encourager la spécialisation. Un groupe de
une personne travaille sur un modèle de données, une autre regarde l'architecture,
tandis que les collecteurs d'exigences collectent les cas d'utilisation (ou leur équivalent).
Nous avons vu cela conduire à une mauvaise communication et à des efforts inutiles. Là
est aussi une tendance à retomber dans la mentalité nous contre eux de
concepteurs contre codeurs. Nous préférons comprendre l'ensemble de la
système sur lequel nous travaillons. Il n'est peut-être pas possible d'avoir une analyse approfondie
comprendre tous les aspects d'un système, mais vous devez savoir comment le
les composants interagissent, où les données vivent, et ce que le
les exigences sont.
• • Nous aimons écrire des systèmes adaptables et dynamiques, en utilisant des métadonnées pour
nous permettent de changer le caractère des applications lors de l'exécution. La plupart
les méthodes formelles actuelles combinent un objet statique ou un modèle de données avec
une sorte de mécanisme de cartographie des événements ou des activités. Nous n'avons pas encore
tomber sur celui qui nous permet d'illustrer le genre de dynamisme que nous
sentir que les systèmes devraient présenter. En fait, la plupart des méthodes formelles conduiront
vous égarer, vous incitant à établir des relations statiques entre
objets qui devraient vraiment être tricotés ensemble dynamiquement.

Les
Les méthodes
méthodes sont-elles
sont-elles payantes
payantes ??

Dans un article du CACM de 1999 [ Gla99b ], Robert Glass passe en revue les recherches sur
les gains de productivité et de qualité obtenus grâce à sept
technologies de développement logiciel (4GLs, techniques structurées, CASE
outils, méthodes formelles, méthodologie de salle blanche, modèles de processus et objet
orientation). Il rapporte que le battage médiatique initial entourant tous ces
les méthodes étaient exagérées. Bien qu'il y ait une indication que certaines méthodes
avoir des avantages, ces avantages ne commencent à se manifester qu'après une
baisse significative de la productivité et de la qualité lors de l'adoption de la technique
et ses utilisateurs se forment. Ne sous-estimez jamais le coût de l'adoption
de nouveaux outils et méthodes. Soyez prêt à traiter les premiers projets en utilisant ces
techniques comme une expérience d'apprentissage.

Doit-on
Doit-on utiliser
utiliser des
des méthodes
méthodes formelles
formelles ??

Absolument. Mais souvenez-vous toujours que les méthodes de développement formelles sont
juste un outil de plus dans la boîte à outils. Si, après une analyse minutieuse, vous sentez que vous avez besoin
utiliser une méthode formelle, puis l'adopter, mais rappelez-vous qui est responsable.
Ne devenez jamais esclave d'une méthodologie : les cercles et les flèches rendent pauvres
maîtrise. Les programmeurs pragmatiques examinent les méthodologies de manière critique, puis
extraire le meilleur de chacun et les fondre dans un ensemble de pratiques de travail
qui s'améliore chaque mois. C'est crucial. Vous devez travailler constamment pour
affiner et améliorer vos processus. N'acceptez jamais les limites rigides d'un
méthodologie comme les limites de votre monde.

Ne cédez pas à la fausse autorité d'une méthode. Les gens peuvent entrer dans
réunions avec un acre de diagrammes de classes et 150 cas d'utilisation, mais tout ça
le papier n'est encore que leur interprétation faillible des exigences et de la conception.
Essayez de ne pas penser au coût d'un outil lorsque vous regardez sa sortie.

Astuce
Astuce 59
59

Trop cher ne produit pas de meilleurs designs

Les méthodes formelles ont certainement leur place dans le développement. Cependant, si vous
tomber sur un projet dont la philosophie est "le diagramme de classes est le
application, le reste est du codage mécanique", vous savez que vous avez affaire à un
équipe de projet gorgée d'eau et une longue maison de pagaie.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • La fosse aux exigences

Défis
Défis

• • Les diagrammes de cas d'utilisation font partie du processus UML de collecte


exigences (voir Le puits des exigences ). Sont-ils un moyen efficace
de communiquer avec vos utilisateurs ? Si non, pourquoi les utilisez-vous ?
• • Comment savoir si une méthode formelle amène votre équipe
avantages? Que pouvez-vous mesurer ? Qu'est-ce qui constitue une amélioration ?
Pouvez-vous faire la distinction entre les avantages de l'outil et l'augmentation
expérience de la part des membres de l'équipe?
• • Où est le seuil de rentabilité pour introduire de nouvelles méthodes
ton équipe? Comment évaluez-vous le compromis entre l'avenir
avantages et les pertes de productivité actuelles au fur et à mesure de l'introduction de l'outil ?
• • Les outils qui fonctionnent pour les grands projets sont-ils bons pour les petits ? Comment
à propos de l'inverse ?

Chapitre 8. Projets pragmatiques

Au fur et à mesure que votre projet démarre, nous devons nous éloigner des questions de
philosophie et codage individuels pour parler de problèmes plus vastes et de la taille d'un projet.
Nous n'entrerons pas dans les détails de la gestion de projet, mais nous parlerons
sur une poignée de domaines critiques qui peuvent faire ou défaire n'importe quel projet.

Dès que vous avez plus d'une personne travaillant sur un projet, vous devez
établir des règles de base et déléguer des parties du projet en conséquence.
Dans Pragmatic Teams, nous montrerons comment faire cela tout en respectant les
philosophie pragmatique.

Le facteur le plus important pour faire fonctionner les activités au niveau du projet
de manière cohérente et fiable consiste à automatiser vos procédures. Nous allons vous expliquer pourquoi,
et montrer quelques exemples concrets dans Ubiquitous Automation.
Plus tôt, nous avons parlé de tester pendant que vous codez. Dans Ruthless Testing, nous allons à
la prochaine étape de la philosophie et des outils de test à l'échelle du projet, surtout si vous
n'ayez pas un grand personnel d'assurance qualité à votre entière disposition.

La seule chose que les développeurs n'aiment pas plus que les tests, c'est la documentation.
Que vous ayez des rédacteurs techniques qui vous aident ou que vous le fassiez vous-même,
nous vous montrerons comment rendre la corvée moins pénible et plus productive dans
Tout est écrit.

Le succès est dans l'œil du spectateur, le parrain du projet. Le


la perception du succès est ce qui compte, et dans Great Expectations, nous montrerons
quelques astuces pour ravir chaque sponsor de projet.

Le dernier conseil du livre est une conséquence directe de tout le reste. Dans la fierté et
Préjugé, nous vous encourageons à signer votre travail, et à être fier de ce que
tu fais.

Des
Des équipes
équipes pragmatiques
pragmatiques

Chez Group L, Stoffel supervise six programmeurs de premier ordre, un gestionnaire


défi à peu près comparable à l'élevage de chats.

The
The Washington
Washington Post
Post Magazine,
Magazine, 99 juin
juin 1985
1985

Jusqu'à présent, dans ce livre, nous avons examiné des techniques pragmatiques qui aident un
individu être un meilleur programmeur. Ces méthodes peuvent-elles fonctionner pour les équipes
Bien?

La réponse est un oui retentissant!" Il y a des avantages à être un


pragmatique, mais ces avantages sont multipliés si le
personne travaille au sein d'une équipe pragmatique.

Dans cette section, nous verrons brièvement comment les techniques pragmatiques peuvent être appliquées
aux équipes dans leur ensemble. Ces notes ne sont qu'un début. Une fois que vous avez un groupe de
développeurs pragmatiques travaillant dans un environnement favorable, ils vont rapidement
développer et affiner leur propre dynamique d'équipe qui fonctionne pour eux.

Reprenons certaines des sections précédentes en termes d'équipes.

Pas
Pas de
de fenêtres
fenêtres cassées
cassées

La qualité est une question d'équipe. Le développeur le plus diligent placé dans une équipe qui
s'en fiche aura du mal à maintenir l'enthousiasme nécessaire pour
régler les problèmes agaçants. Le problème est encore aggravé si l'équipe
décourage activement le développeur de passer du temps sur ces correctifs.

Les équipes dans leur ensemble ne devraient pas tolérer les fenêtres brisées, ces petites
imperfections que personne ne corrige. L'équipe doit assumer la responsabilité de
qualité du produit, en soutenant les développeurs qui comprennent le non
la philosophie des fenêtres brisées que nous décrivons dans Software Entropy , et
encourageant ceux qui ne l'ont pas encore découvert.

Certaines méthodologies d'équipe ont un responsable de la qualité - quelqu'un à qui


l'équipe délègue la responsabilité de la qualité du livrable. C'est
clairement ridicule : la qualité ne peut venir que des contributions individuelles
de tous les membres de l'équipe.

Grenouilles
Grenouilles bouillies
bouillies

Rappelez-vous la pauvre grenouille dans la casserole d'eau, de retour dans Stone Soup and Boiled
Grenouilles? Il ne remarque pas le changement progressif de son environnement et finit par
cuit. La même chose peut arriver aux personnes qui ne sont pas vigilantes. Ça peut être
difficile de garder un oeil sur son environnement global dans le feu du projet
développement.

C'est encore plus facile pour les équipes dans leur ensemble de se faire bouillir. Les gens supposent que
quelqu'un d'autre s'occupe d'un problème, ou que le chef d'équipe doit avoir l'accord
une modification demandée par votre utilisateur. Même les équipes les mieux intentionnées peuvent
être inconscients des changements importants dans leurs projets.

Combattez ça. Assurez-vous que tout le monde surveille activement l'environnement pour
changements. Peut-être nommer un testeur d'eau en chef. Faites vérifier par cette personne
constamment pour une portée accrue, des échelles de temps réduites, des fonctionnalités supplémentaires,
de nouveaux environnements—tout ce qui ne figurait pas dans l'accord d'origine. Donjon
métriques sur les nouvelles exigences (voir page 209). L'équipe n'a pas à rejeter
changements incontrôlables - vous devez simplement être conscient qu'ils se produisent.
Sinon, ce sera toi dans l'eau chaude.

Communiquer
Communiquer

Il est évident que les développeurs d'une équipe doivent se parler. Nous avons donné
quelques suggestions pour faciliter cela dans Communicate! . Cependant, il est facile de
oublier que l'équipe elle-même est présente au sein de l'organisation. L'équipe
en tant qu'entité doit communiquer clairement avec le reste du monde.

Pour les étrangers, les pires équipes de projet sont celles qui semblent maussades et
réticent. Ils tiennent des réunions sans structure, où personne ne veut parler.
Leurs documents sont en désordre : il n'y en a pas deux qui se ressemblent et chacun utilise des
terminologie.

Les grandes équipes de projet ont une personnalité distincte. Les gens attendent avec impatience
rencontres avec eux, parce qu'ils savent qu'ils verront une rencontre bien préparée
des performances qui font que tout le monde se sent bien. La documentation qu'ils
les produits sont nets, précis et cohérents. L'équipe parle d'une seule voix. [1]

Ils peuvent même avoir le sens de l'humour.

[1] L'équipe parle d'une seule voix à l'extérieur. En interne, nous encourageons fortement un débat animé et vigoureux. Bons développeurs

ont tendance à être passionnés par leur travail.

Il existe une astuce marketing simple qui aide les équipes à communiquer comme une seule :
générer une marque. Lorsque vous démarrez un projet, donnez-lui un nom,
idéalement quelque chose de décalé. (Par le passé, nous nommions les projets d'après
des choses telles que des perroquets tueurs qui se nourrissent de moutons, des illusions d'optique et
villes mythiques.) Passez 30 minutes à créer un logo loufoque et utilisez-le
sur vos mémos et rapports. Utilisez généreusement le nom de votre équipe lorsque vous parlez
avec des gens. Cela semble idiot, mais cela donne à votre équipe une identité sur laquelle s'appuyer,
et le monde quelque chose de mémorable à associer à votre travail.

Ne
Ne vous
vous répétez
répétez pas
pas

Dans Les maux de la duplication, nous avons parlé des difficultés d'éliminer
travail en double entre les membres d'une équipe. Ce dédoublement conduit à

effort inutile et peut entraîner un cauchemar de maintenance. Clairement bon


la communication peut aider ici, mais parfois quelque chose de plus est nécessaire.
Certaines équipes désignent un membre comme bibliothécaire du projet, responsable de
coordonner la documentation et les référentiels de code. Autres membres de l'équipe
peut utiliser cette personne comme première escale lorsqu'elle recherche
quelque chose. Un bon bibliothécaire sera également en mesure de repérer les doublons imminents
en lisant le matériel qu'ils manipulent.

Lorsque le projet est trop important pour un seul bibliothécaire (ou lorsque personne ne veut jouer
le rôle), nommer des personnes comme points focaux pour divers aspects fonctionnels du
travail. Si les gens veulent parler de la gestion des rendez-vous, ils doivent savoir parler
avec Marie. S'il y a un problème de schéma de base de données, consultez Fred.

Et n'oubliez pas la valeur des systèmes collaboratifs et Usenet local


groupes de discussion pour communiquer et archiver les questions et les réponses.

Orthogonalité
Orthogonalité

L'organisation traditionnelle de l'équipe est basée sur la cascade à l'ancienne


méthode de construction du logiciel. Les individus se voient attribuer des rôles en fonction de
leur fonction professionnelle. Vous trouverez des analystes d'affaires, des architectes, des designers,
programmeurs, testeurs, documentalistes, etc. [2] Il y a un implicite
hiérarchie ici : plus vous êtes proche de l'utilisateur autorisé, plus vous avez d'ancienneté
sont.

[2] Dans The Rational Unified Process : An Introduction, l'auteur identifie 27 rôles distincts au sein d'une équipe de projet !

[ Kru98 ]

Poussant les choses à l'extrême, certaines cultures de développement dictent


répartition des responsabilités; les codeurs ne sont pas autorisés à parler aux testeurs, qui
tour ne sont pas autorisés à parler à l'architecte en chef, et ainsi de suite. Quelques
les organisations aggravent alors le problème en ayant différentes sous-équipes
rendre compte par le biais de chaînes de gestion distinctes.

C'est une erreur de penser que les activités d'un projet - analyse, conception,
le codage et les tests peuvent se produire isolément. Ils ne peuvent pas. Ceux-ci sont
différentes vues d'un même problème, et les séparer artificiellement peut
causer un tas de problèmes. Programmeurs à deux ou trois niveaux
retirés des utilisateurs réels de leur code sont peu susceptibles d'être conscients de la
contexte dans lequel leur travail est utilisé. Ils ne pourront pas informer
les décisions.

Astuce
Astuce 60
60

Organiser autour de la fonctionnalité, pas des fonctions de travail

Nous privilégions le fractionnement fonctionnel des équipes. Divisez votre personnel en petites équipes,
chacun étant responsable d'un aspect fonctionnel particulier du système final. Laisser
les équipes s'organisent en interne en s'appuyant sur les forces de chacun
comme ils peuvent. Chaque équipe a des responsabilités envers les autres dans le projet, comme
définis par leurs engagements convenus. L'ensemble exact des engagements
change à chaque projet, tout comme la répartition des personnes en équipes.

La fonctionnalité ici ne signifie pas nécessairement des cas d'utilisation d'utilisateurs finaux. Le
la couche d'accès à la base de données compte, tout comme le sous-système d'aide. Nous recherchons
des équipes de personnes cohésives et largement autonomes - exactement les mêmes critères
nous devrions utiliser lorsque nous modularisons le code. Il y a des signes avant-coureurs qui
l'organisation de l'équipe est mauvaise - un exemple classique est d'avoir deux sous-équipes
travailler sur le même module ou la même classe de programme.

Comment ce style fonctionnel d'organisation aide-t-il ? Organiser nos ressources


en utilisant les mêmes techniques que nous utilisons pour organiser le code, en utilisant des techniques telles que
sous forme de contrats ( Design by), Contract
le découplage ( Le découplage et la loi de
Demeter ), et orthogonalité ( Orthogonalité ), et nous aidons à isoler l'équipe
dans son ensemble des effets du changement. Si l'utilisateur décide soudainement de changer
fournisseurs de bases de données, seule l'équipe de la base de données devrait être affectée. Devrait
le marketing décide soudainement d'utiliser un outil prêt à l'emploi pour le calendrier
fonction, le groupe de calendrier en prend un coup. Correctement exécuté, ce genre de
l'approche de groupe peut réduire considérablement le nombre d'interactions
entre le travail des individus, en réduisant les échelles de temps, en augmentant la qualité et
réduire le nombre de défauts. Cette approche peut également conduire à une
ensemble de développeurs plus engagés. Chaque équipe sait qu'elle est la seule
responsable d'une fonction particulière, de sorte qu'ils se sentent plus propriétaires de leur
sortir.

Cependant, cette approche ne fonctionne qu'avec des développeurs responsables et de solides


gestion de projet. Créer un pool d'équipes autonomes et laisser
les perdre sans leadership est une recette pour le désastre. Le projet a besoin de
au moins deux "chefs", l'un technique, l'autre administratif. La technique
le chef définit la philosophie et le style de développement, attribue des responsabilités à
équipes, et arbitre les inévitables "discussions" entre les personnes. Le
le chef technique regarde également constamment la situation dans son ensemble, essayant de trouver
points communs inutiles entre les équipes qui pourraient réduire le
orthogonalité de l'effort global. Le responsable administratif, ou projet
manager, planifie les ressources dont les équipes ont besoin, suit et
rend compte des progrès et aide à décider des priorités en termes de besoins commerciaux.

Le responsable administratif peut également agir à titre d'ambassadeur de l'équipe lorsque


communiquant avec le monde extérieur.

Les équipes sur des projets plus importants ont besoin de ressources supplémentaires : un bibliothécaire qui indexe
et stocke le code et la documentation, un constructeur d'outils qui fournit des
outils et environnements, support opérationnel, etc.

Ce type d'organisation d'équipe est similaire dans l'esprit à l'ancien chef


concept d'équipe de programmeurs, documenté pour la première ]. fois en 1972 [ Bak72

Automatisation
Automatisation

Un excellent moyen d'assurer à la fois la cohérence et la précision consiste à automatiser


tout ce que fait l'équipe. Pourquoi disposer le code manuellement quand votre éditeur peut
le faire automatiquement au fur et à mesure que vous tapez ? Pourquoi remplir des formulaires de test alors que le
la construction de nuit peut exécuter des tests automatiquement ?

L'automatisation est un élément essentiel de chaque équipe de projet.


assez pour que nous y consacrions une section entière, en commençant par la suivante
page. Pour vous assurer que les choses deviennent automatisées, nommez une ou plusieurs équipes
membres en tant que constructeurs d'outils pour construire et déployer les outils qui automatisent
la corvée du projet. Demandez-leur de produire des makefiles, des scripts shell, un éditeur
modèles, programmes utilitaires, etc.

Savoir
Savoir quand
quand arrêter
arrêter d'ajouter
d'ajouter de
de la
la peinture
peinture

Rappelez-vous que les équipes sont composées d'individus. Donnez à chaque membre le
capacité à briller à sa manière. Donnez-leur juste assez de structure pour
les soutenir et s'assurer que le projet respecte ses
exigences. Alors, comme le peintre de Good-Enough Software, résistez aux
tentation d'ajouter plus de peinture.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Entropie logicielle
• • Soupe aux cailloux et grenouilles bouillies
• • Logiciel suffisamment bon
• • Communiquer!
• • Les maux de la duplication
• • Orthogonalité
• • Conception par contrat
• • Le découplage et la loi de Déméter
• • Automatisation omniprésente

Défis
Défis

• • Recherchez des équipes performantes en dehors du domaine des logiciels


développement. Qu'est-ce qui fait leur succès ? Utilisent-ils l'un des
processus abordés dans cette section ?
• • La prochaine fois que vous démarrez un projet, essayez de convaincre les gens de le marquer.
Donnez à votre organisation le temps de s'habituer à l'idée, puis faites
un audit rapide pour voir quelle différence cela a fait, tant au sein de l'équipe
et à l'extérieur.
• • Équipe d'algèbre : À l'école, on nous pose des problèmes tels que « Si c'est
prend 4 ouvriers 6 heures pour creuser un fossé, combien de temps faudrait-il 8
travailleurs?" Dans la vraie vie, cependant, quels facteurs affectent la réponse à : "Si
il faut 4 programmeurs 6 mois pour développer une application, combien de temps
faudrait-il 8 programmeurs ?" Dans combien de scénarios le temps est-il
vraiment réduit ?

Automatisation
Automatisation omniprésente
omniprésente

La civilisation progresse en augmentant le nombre d'opérations importantes que nous


peut jouer sans réfléchir.

Alfred
Alfred North
North Whitehead
Whitehead

A l'aube de l'ère automobile, les instructions de démarrage d'un


La Model-T Ford faisait plus de deux pages. Avec les voitures modernes, il vous suffit
tournez la clé, la procédure de démarrage est automatique et infaillible. Une personne
suivre une liste d'instructions peut inonder le moteur, mais le
le démarreur ne le fera pas.

Bien que l'informatique soit encore une industrie au stade du Modèle-T, nous ne pouvons pas
se permettre de parcourir deux pages d'instructions encore et encore pour certains
opération commune. Qu'il s'agisse de la procédure de construction et de publication, du code
revoir la paperasserie, ou toute autre tâche récurrente sur le projet, il doit être
automatique. Nous devrons peut-être construire le démarreur et l'injecteur de carburant à partir de zéro,
mais une fois que c'est fait, on peut juste tourner la clé à partir de là.

De plus, nous voulons assurer la cohérence et la répétabilité sur le projet.


Les procédures manuelles laissent la cohérence au hasard ; la répétabilité n'est pas
garanti, surtout si certains aspects de la procédure prêtent à interprétation
par différentes personnes.

Tout
Tout en
en automatique
automatique

Nous étions une fois sur un site client où tous les développeurs utilisaient le même
IDE. Leur administrateur système a donné à chaque développeur un ensemble d'instructions
sur l'installation de packages complémentaires dans l'IDE. Ces instructions ont rempli de nombreuses
pages - pages pleines de cliquez ici, faites défiler là-bas, faites glisser ceci, double-cliquez sur cela et
refais-le.

Sans surprise, la machine de chaque développeur était chargée légèrement différemment.


Des différences subtiles dans le comportement de l'application se produisaient lorsque différents
les développeurs ont exécuté le même code. Des bogues apparaissaient sur une machine mais pas
sur les autres. Traquer les différences de version d'un composant en général
révélé une surprise.

Astuce
Astuce 61
61

N'utilisez pas de procédures manuelles

Les gens ne sont tout simplement pas aussi reproductibles que les ordinateurs. Il ne faut pas non plus s'attendre
qu'ils soient. Un script shell ou un fichier batch exécutera les mêmes instructions, dans
le même ordre, à chaque fois. Il peut être placé sous contrôle de source, de sorte que vous
peut également examiner les modifications apportées à la procédure au fil du temps ("mais
travailler…").

Un autre outil d'automatisation favori est cron (ou "at" sous Windows NT). Il
nous permet de programmer des tâches sans surveillance pour qu'elles s'exécutent périodiquement, généralement dans le
au milieu de la nuit. Par exemple, ce qui suit crontab spécifie qu'un
projets la commande nocturne doit être exécutée à minuit cinq minutes tous les jours,
q u
êt er

En utilisant cron, nous pouvons planifier des sauvegardes, la construction nocturne, le site Web
l'entretien et tout ce qui doit être fait - sans surveillance,
automatiquement.

Compilation
Compilation du
du projet
projet

Compiler le projet est une corvée qui doit être fiable et reproductible. Nous
compilent généralement des projets avec des makefiles, même lors de l'utilisation d'un IDE
environnement. Il y a plusieurs avantages à utiliser les makefiles. C'est un
procédure scriptée et automatique. Nous pouvons ajouter des crochets pour générer du code pour nous,
et exécutez des tests de régression automatiquement. Les IDE ont leurs avantages, mais
avec les IDE seuls, il peut être difficile d'atteindre le niveau d'automatisation que nous sommes
à la recherche de. Nous voulons vérifier, construire, tester et expédier avec un seul
commande.

Génération
Génération de
de code
code

Dans The Evils of Duplication , nous avons préconisé de générer du code pour dériver
connaissances provenant de sources communes. Nous pouvons exploiter la dépendance de make
mécanisme d'analyse pour faciliter ce processus. C'est une question assez simple
pour ajouter des règles à un makefile pour générer un fichier à partir d'une autre source
automatiquement. Par exemple, supposons que nous voulions prendre un fichier XML,
g énéer

Tapez make test.class, et make recherchera automatiquement un fichier nommé


test.xml, créez un fichier .java en exécutant un script Perl, puis compilez-le
fichier à produire
t
Nous pouvons utiliser le même type de règles pour générer du code source, des fichiers d'en-tête ou
documentation automatiquement à partir d'un autre formulaire également (voir Code
Générateurs ).

Tests
Tests de
de régression
régression

Vous pouvez également utiliser le makefile pour exécuter des tests de régression pour vous, soit pour un
module individuel ou pour un sous-système entier. Vous pouvez facilement tester l'ensemble
projet avec une seule commande en haut de l'arborescence source, ou vous pouvez tester
un module individuel en utilisant la même commande dans un seul répertoire. Voir
Ruthless Testing , pour en savoir plus sur les tests de régression.

Make récursif

De nombreux projets mettent en place des builds de projet récursifs et hiérarchiques et


essai. Mais soyez conscient de certains problèmes potentiels.

make calcule les dépendances entre les différentes cibles qu'il doit
construire. Mais il ne peut analyser que les dépendances qui existent au sein
un seul faire l'invocation. En particulier, un make récursif n'a pas
connaissance des dépendances que d'autres invocations de make peuvent avoir.
Si vous êtes prudent et précis, vous pouvez obtenir les bons résultats, mais c'est
facile de causer du travail supplémentaire inutilement - ou de manquer une dépendance et
pas recompiler quand c'est nécessaire.

De plus, les dépendances de construction peuvent ne pas être les mêmes que celles de test
dépendances, et vous aurez peut-être besoin de hiérarchies distinctes.

Construire
Construire l'automatisation
l'automatisation

Un build est une procédure qui prend un répertoire vide (et un


environnement de compilation) et construit le projet à partir de zéro, produisant
tout ce que vous espérez produire comme livrable final - un master CD-ROM
image ou une archive auto-extractible, par exemple. Typiquement une construction de projet
englobera les étapes suivantes.

1. 1. Extrayez le code source du référentiel.

2. 2. Construisez le projet à partir de zéro, généralement à partir d'un niveau supérieur


makefile. Chaque version est marquée d'une forme de version ou de version
numéro, ou peut-être un tampon dateur.

3. 3. Créez une image distribuable. Cette procédure peut impliquer la fixation


la propriété et les autorisations des fichiers, et la production de tous les exemples,
documentation, fichiers README et tout ce qui sera livré avec
le produit, dans le format exact qui vous sera demandé lorsque vous
bateau.
[3]

[3] Si vous produisez un CD-ROM au format ISO9660, par exemple, vous exécuterez le programme qui produit un

image bit à bit du système de fichiers 9660. Pourquoi attendre la nuit avant d'expédier pour vous assurer que cela fonctionne ?

4. 4. Exécutez les tests spécifiés ( make test ).

Pour la plupart des projets, ce niveau de build est exécuté automatiquement chaque nuit. Dans
cette version nocturne, vous exécuterez généralement des tests plus complets qu'un
l'individu peut s'exécuter lors de la construction d'une partie spécifique du projet.
Le point important est que la version complète exécute tous les tests disponibles. Toi
vous voulez savoir si un test de régression a échoué à cause de l'un des codes d'aujourd'hui
changements. En identifiant le problème près de la source, vous vous portez mieux
chance de le trouver et de le réparer.

Lorsque vous n'exécutez pas de tests régulièrement, vous pouvez découvrir que l'application
cassé en raison d'un changement de code effectué il y a trois mois. Bonne chance pour trouver ça
un.

Versions
Versions finales
finales

Les versions finales, que vous avez l'intention d'expédier en tant que produits, peuvent avoir des
exigences de la construction nocturne régulière. Une version finale peut nécessiter que
le référentiel soit verrouillé, ou étiqueté avec le numéro de version, qui
les indicateurs d'optimisation et de débogage doivent être définis différemment, et ainsi de suite. Nous aimons utiliser un
séparé make target (comme make final ) qui définit tous ces paramètres
immediatement.

N'oubliez pas que si le produit est compilé différemment des versions antérieures,
alors vous devez tester à nouveau cette version.

Administration
Administration automatique
automatique

Ne serait-il pas agréable que les programmeurs puissent réellement consacrer tout leur temps à
la programmation? Malheureusement, c'est rarement le cas. Il y a un e-mail à être
réponses, des papiers à remplir, des documents à publier sur le Web,
et ainsi de suite. Vous pouvez décider de créer un script shell pour faire une partie du sale
fonctionnent, mais vous devez toujours vous rappeler d'exécuter le script si nécessaire.

Parce que la mémoire est la deuxième chose que vous perdez [4] nous ne voulons pas
en vieillissant,
compter trop dessus. Nous pouvons exécuter des scripts pour effectuer des procédures pour nous
automatiquement, en fonction du contenu du code source et des documents. Notre objectif
est de maintenir un flux de travail automatique, sans surveillance et axé sur le contenu.

[4] Quel est le premier ? J'oublie.

Génération
Génération de
de site
site Web
Web

De nombreuses équipes de développement utilisent un site Web interne pour le projet


communication, et nous pensons que c'est une excellente idée. Mais nous ne voulons pas
passer trop de temps à maintenir le site Web, et nous ne voulons pas le laisser

deviennent obsolètes ou obsolètes. Une information trompeuse est pire que non
informations du tout.

Documentation extraite du code, analyses des exigences, conception


documents, et tous les dessins, tableaux ou graphiques doivent tous être publiés sur
régulièrement sur le Web. Nous aimons publier ces documents
automatiquement dans le cadre de la construction nocturne ou en tant que crochet dans le code source
procédure d'enregistrement.

Quoi qu'il en soit, le contenu Web doit être généré automatiquement à partir de
informations dans le référentiel et publiées sans intervention humaine.
C'est vraiment une autre application du principe DRY : l'information existe
sous une seule forme sous forme de code d'enregistrement et de documents. La vue depuis le Web
navigateur est simplement cela, juste une vue. Tu ne devrais pas avoir à maintenir ça
voir à la main.

Toutes les informations générées par la construction nocturne doivent être accessibles sur le
site Web de développement : résultats de la construction elle-même (par exemple, la construction
les résultats peuvent être présentés sous la forme d'un résumé d'une page qui inclut le compilateur
avertissements, erreurs et état actuel), tests de régression, performances
statistiques, métriques de codage et toute autre analyse statique, etc.
Procédures
Procédures d'approbation
d'approbation

Certains projets ont divers workflows administratifs qui doivent être suivis.
Par exemple, les revues de code ou de conception doivent être programmées et suivies
à travers, des approbations peuvent devoir être accordées, et ainsi de suite. On peut utiliser
l'automatisation, et en particulier le site Web, pour faciliter la paperasserie
fardeau.

Supposons que vous vouliez automatiser la planification et l'approbation de la révision du code. Toi
p o

Un simple script pourrait parcourir tout le code source et rechercher tous les fichiers
qui avaient le statut d'examen_des_besoins, indiquant qu'ils étaient prêts à être
revu. Vous pouvez ensuite publier une liste de ces fichiers sous forme de page Web,
envoyer automatiquement un e-mail aux personnes appropriées, ou même programmer un
réunion automatiquement à l'aide d'un logiciel de calendrier.

Vous pouvez configurer un formulaire sur une page Web pour que les réviseurs enregistrent l'approbation
ou désapprobation. Après l'examen, le statut peut être automatiquement changé en

revu. Que vous ayez une revue de code avec tous les participants
C'est à toi de voir; vous pouvez toujours faire la paperasse automatiquement. (Dans un article de
CACM d'avril 1999, Robert Glass résume des recherches qui semblent
indiquent que, bien que l'inspection du code soit efficace, la réalisation d'examens dans
réunions n'est pas [ Gla99a].)

Les
Les enfants
enfants du
du cordonnier
cordonnier

Les enfants du cordonnier n'ont pas de chaussures. Souvent, les personnes qui développent des logiciels
utiliser les outils les plus pauvres pour faire le travail.

Mais nous avons toutes les matières premières dont nous avons besoin pour fabriquer de meilleurs outils. Nous avons
cron. Nous avons make, sur les plateformes Windows et Unix. Et nous avons
Perl et d'autres langages de script de haut niveau pour développer rapidement des
outils, générateurs de pages Web, générateurs de code, harnais de test, etc.

Laissez l'ordinateur faire le répétitif, le banal - il fera un meilleur travail de


que nous le ferions. Nous avons des choses plus importantes et plus difficiles à faire.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Le chat a mangé mon code source


• • Les maux de la duplication
• • La puissance du texte brut
• • Jeux de coquillages
• • Débogage
• • Générateurs de codes
• • Des équipes pragmatiques
• • Tests impitoyables
• • Tout est écrit

Défis
Défis

• • Examinez vos habitudes tout au long de la journée de travail. En voyez-vous


tâches répétitives? Tapez-vous la même séquence de commandes sur
et encore?

Essayez d'écrire quelques scripts shell pour automatiser le processus. Est-ce que tu
cliquez toujours sur la même séquence d'icônes à plusieurs reprises ? Peux-tu
créer une macro pour faire tout cela pour vous ?

• • Quelle part de la paperasserie de votre projet peut être automatisée ? Donné


[5] déterminer combien de
le coût élevé du personnel de programmation,
le budget du projet est gaspillé en procédures administratives. Peut
vous justifiez le temps qu'il faudrait pour créer un système automatisé
solution en fonction des économies de coûts globales qu'elle permettrait de réaliser ?

[5] À des fins d'estimation, vous pouvez calculer une moyenne de l'industrie d'environ 100 000 USD par tête - c'est le salaire

ainsi que les avantages sociaux, la formation, l'espace de bureau et les frais généraux, etc.

Tests
Tests impitoyables
impitoyables

La plupart des développeurs détestent les tests. Ils ont tendance à tester doucement, inconsciemment
savoir où le code va casser et éviter les points faibles. Pragmatique
Les programmeurs sont différents. Nous sommes poussés à trouver nos bogues maintenant, donc nous ne
avoir à endurer la honte que d'autres découvrent nos bogues plus tard.

Trouver des insectes, c'est un peu comme pêcher avec un filet. Nous utilisons de petits filets fins
(tests unitaires) pour attraper les vairons, et de grands filets grossiers (tests d'intégration) pour
attraper les requins tueurs. Parfois les poissons réussissent à s'échapper, alors on rafistole
tous les trous que nous trouvons, dans l'espoir d'attraper de plus en plus de défauts glissants
qui nagent dans notre pool de projets.

Astuce
Astuce 62
62

Testez tôt. Testez souvent. Tester automatiquement.

Nous voulons commencer les tests dès que nous aurons du code. Ces petits vairons ont
une mauvaise habitude de devenir assez rapidement des requins géants mangeurs d'hommes, et
attraper un requin est un peu plus difficile. Mais nous ne voulons pas avoir à tout faire
ce test à la main.

De nombreuses équipes développent des plans de test élaborés pour leurs projets. Parfois ils
les utilisera même. Mais nous avons constaté que les équipes qui utilisent des tests automatisés
ont de bien meilleures chances de succès. Les tests qui s'exécutent avec chaque build sont
beaucoup plus efficace que les plans de test qui reposent sur une étagère.

Plus un bogue est détecté tôt, moins il est coûteux d'y remédier. "Codez un peu, testez un
[6] et nous pouvons adopter que
peu" est un dicton populaire dans le monde Smalltalk,
mantra comme le nôtre en écrivant du code de test en même temps (ou même avant) que nous
écrire le code de fabrication.

[6] eXtreme Programming [ URL 45 ] appelle ce concept "Intégration continue, tests implacables".

En fait, un bon projet peut très bien avoir plus de code de test que de code de production.
Le temps qu'il faut pour produire ce code de test en vaut la chandelle. Ça finit
étant beaucoup moins cher à long terme, et vous avez en fait une chance de
produire un produit avec presque zéro défaut.

De plus, savoir que vous avez réussi le test vous donne un degré élevé de
confiance qu'un morceau de code est "fait".
Astuce
Astuce 63
63
Le codage n'est pas terminé jusqu'à ce que tous les tests soient exécutés

Ce n'est pas parce que vous avez fini de pirater un morceau de code que vous
pouvez aller dire à votre patron ou à votre client que c'est fait. Ce n'est pas. Tout d'abord, le code est
jamais vraiment fait. Plus important encore, vous ne pouvez pas prétendre qu'il est utilisable par
n'importe qui jusqu'à ce qu'il réussisse tous les tests disponibles.

Nous devons examiner trois aspects principaux des tests à l'échelle du projet : que tester,
comment tester et quand tester.

Quoi
Quoi tester
tester

Il existe plusieurs types majeurs de tests logiciels que vous devez effectuer :

• • Tests unitaires
• • Tests d'intégration
• • Validation et vérification
• • Épuisement des ressources, erreurs et récupération
• • Test de performance
• • Tests d'utilisation

Cette liste n'est en aucun cas exhaustive et certains projets spécialisés nécessiteront
divers autres types de tests également. Mais cela nous donne un bon point de départ.

Tests
Tests unitaires
unitaires

Un test unitaire est un code qui teste un module. Nous avons traité ce sujet seul dans
Code facile à tester. Les tests unitaires sont la base de tous les autres
formes de test dont nous parlerons dans cette section. Si les pièces ne fonctionnent pas par
eux-mêmes, ils ne fonctionneront probablement pas bien ensemble. Tous les modules que vous
que vous utilisez doivent passer leurs propres tests unitaires avant de pouvoir continuer.

Une fois que tous les modules pertinents ont réussi leurs tests individuels, vous êtes
prêt pour la prochaine étape. Vous devez tester comment tous les modules utilisent et
interagissent les uns avec les autres dans tout le système.

Tests
Tests d'intégration
d'intégration

Les tests d'intégration montrent que les principaux sous-systèmes qui composent le
travail de projet et bien jouer les uns avec les autres. Avec de bons contrats en place
et bien testé, tout problème d'intégration peut être détecté facilement. Sinon,
l'intégration devient un terreau fertile pour les bogues. En fait, c'est souvent
la plus grande source de bogues du système.

Les tests d'intégration ne sont en fait qu'une extension des tests unitaires que nous avons
décrit - seulement maintenant vous testez comment des sous-systèmes entiers honorent leur
contrats.

Validation
Validation et
et vérification
vérification

Dès que vous disposez d'une interface utilisateur exécutable ou d'un prototype, vous devez
répondre à une question primordiale : les utilisateurs vous ont dit ce qu'ils voulaient, mais
est-ce ce dont ils ont besoin ?

Répond-il aux exigences fonctionnelles du système ? Cela aussi doit


être testé. Un système sans bug qui répond à la mauvaise question n'est pas très
utile. Soyez conscient des modèles d'accès des utilisateurs finaux et de la façon dont ils diffèrent des
données de test de développeur (pour un exemple, voir l'histoire sur les coups de pinceau sur
pages 92).
Épuisement
Épuisement des
des ressources,
ressources, erreurs
erreurs et
et récupération
récupération

Maintenant que vous avez une assez bonne idée que le système se comportera correctement
dans des conditions idéales, vous devez découvrir comment il se comportera sous
conditions du monde réel. Dans le monde réel, vos programmes n'ont pas de limites
ressources; ils manquent de choses. Quelques limites que votre code peut rencontrer
inclure:

• • Mémoire
• • Espace disque
• • Bande passante du processeur
• • Heure de l'horloge murale
• • Bande passante disque
• • Bande passante réseau

• • Palette de couleurs
• • Résolution vidéo

Vous pouvez en fait vérifier les échecs d'espace disque ou d'allocation de mémoire, mais
à quelle fréquence testez-vous les autres? Votre application tiendra-t-elle sur un 640 × 480
écran avec 256 couleurs? Fonctionnera-t-il sur un écran 1600 × 1280 avec des couleurs 24 bits
sans ressembler à un timbre-poste ? Le traitement par lots se terminera-t-il avant le
l'archive commence ?

Vous pouvez détecter les limitations environnementales, telles que les spécifications vidéo,
et adapter le cas échéant. Cependant, toutes les pannes ne sont pas récupérables. Si ton
code détecte que la mémoire est épuisée, vos options sont limitées : vous
peut ne pas avoir assez de ressources pour faire autre chose qu'échouer.

Lorsque le système tombe en [7]panne,


échouera-t-il gracieusement ? Va-t-il essayer, du mieux qu'il peut,
pour sauver son état et éviter la perte de travail ? Ou sera-ce "GPF" ou "core-dump" dans
le visage de l'utilisateur ?
[7] Notre rédacteur en chef voulait que nous remplacions cette phrase par « Si le système échoue… ». Nous avons résisté.

Test
Test de
de performance
performance

Les tests de performance, les tests de résistance ou les tests sous charge peuvent être un
également un aspect important du projet.

Demandez-vous si le logiciel répond aux exigences de performance sous


conditions du monde réel, avec le nombre attendu d'utilisateurs ou de connexions,
ou transactions par seconde. Est-ce évolutif ?

Pour certaines applications, vous aurez peut-être besoin de matériel de test spécialisé ou
logiciel pour simuler la charge de manière réaliste.

Tests
Tests d'utilisation
d'utilisation

Les tests d'utilisabilité sont différents des types de tests discutés jusqu'à présent. C'est
réalisés avec de vrais utilisateurs, dans des conditions environnementales réelles.

Regardez
Regardez la
la convivialité
convivialité en
en termes
termes de
de facteurs
facteurs humains.
humains. YY avait-il
avait-il des
des miC'est
miC'est tout
tout
En
En écrivant
écrivant

L'encre la plus pâle vaut mieux que le meilleur souvenir.

Proverbe
Proverbe chinois
chinois
En règle générale, les développeurs ne prêtent pas beaucoup d'attention à la documentation. Au mieux ça
est une nécessité malheureuse; au pire, elle est traitée comme une tâche peu prioritaire dans
l'espoir que la direction l'oubliera à la fin du projet.

Les programmeurs pragmatiques considèrent la documentation comme faisant partie intégrante du


processus de développement global. La rédaction de la documentation peut être facilitée par
ne pas dupliquer les efforts ou perdre du temps, et en gardant la documentation à portée de main
à portée de main - dans le code lui-même, si possible.

Ce ne sont pas exactement des pensées originales ou nouvelles ; l'idée du code du mariage
et la documentation apparaît dans le travail de Donald Knuth sur l'alphabétisation
programmation et dans l'utilitaire JavaDoc de Sun, entre autres. Nous voulons
minimiser la dichotomie entre le code et la documentation, et à la place
traitez-les comme deux vues du même modèle (voir Ce n'est qu'une ). En
vuefait, nous
voulons aller un peu plus loin et appliquer tous nos principes pragmatiques pour
documentation ainsi qu'au code.

Astuce
Astuce 67
67

Traitez l'anglais comme un autre langage de programmation

Il existe essentiellement deux types de documentation produite pour un projet :


interne et externe. La documentation interne comprend le code source
commentaires, documents de conception et de test, etc. Documents externes
est tout ce qui est expédié ou publié vers le monde extérieur, comme les manuels d'utilisation.
Mais quel que soit le public visé, ou le rôle de l'auteur (développeur
ou rédacteur technique), toute la documentation est un miroir du code. S'il y a un
divergence, le code est ce qui compte, pour le meilleur ou pour le pire.

Astuce
Astuce 68
68

Intégrez la documentation, ne la boulonnez pas

Nous allons commencer par la documentation interne.

Commentaires
Commentaires dans
dans le
le code
code

Produire des documents formatés à partir des commentaires et des déclarations dans
code source est assez simple, mais nous devons d'abord nous assurer que nous
ont en fait des commentaires dans le code. Le code devrait avoir des commentaires, mais aussi
de nombreux commentaires peuvent être tout aussi mauvais que trop peu.

En général, les commentaires doivent expliquer pourquoi quelque chose est fait, son but
et son objectif. Le code montre déjà comment cela se fait, donc commenter ceci
est redondant et constitue une violation du principe DRY.

Commenter le code source vous donne l'occasion idéale de documenter


ces éléments insaisissables d'un projet qui ne peuvent être documentés nulle part ailleurs :
compromis d'ingénierie, pourquoi les décisions ont été prises, quelles autres alternatives
ont été jetés, et ainsi de suite.

Nous aimons voir un simple commentaire d'en-tête au niveau du module, des commentaires pour
données significatives et déclarations de type, et un bref par classe et par méthode
en-tête, décrivant comment la fonction est utilisée et tout ce qu'elle fait
n'est pas évident.

Les noms de variables, bien sûr, doivent être bien choisis et significatifs.
fou, pour
instance, n'a pas de sens, tout comme doit ou manager ou stuff. hongrois
notation (où vous encodez les informations de type de la variable dans le nom
lui-même) est tout à fait inapproprié dans les systèmes orientés objet. Rappelez-vous que
vous (et d'autres après vous) lirez le code plusieurs centaines de fois,
am si
a u

Pire encore que les noms dénués de sens sont les noms trompeurs. As-tu déjà
quelqu'un a expliqué les incohérences dans le code hérité telles que "La routine
appelégetData écrit vraiment des données sur le disque" ? Le cerveau humain
cela s'encrasse - c'est ce qu'on appelle l'effet Stroop [ Str35 ]. Vous pouvez essayer ce qui suit
expérimentez vous-même pour voir les effets de telles interférences. Obtenez de la couleur
stylos et utilisez-les pour écrire les noms des couleurs. Cependant, jamais
écrivez un nom de couleur à l'aide de ce stylo de couleur. Vous pourriez écrire le mot "bleu" dans
vert, le mot "marron" en rouge, etc. (Alternativement, nous avons un échantillon
ensemble de couleurs déjà dessiné sur notre site Web à
http://www.pragmaticprogrammer.com .) Une fois que vous avez les noms de couleurs
dessiné, essayez de dire à haute voix la couleur avec laquelle chaque mot est dessiné, aussi vite que
tu peux. À un moment donné, vous trébucherez et commencerez à lire les noms des
couleurs, et non les couleurs elles-mêmes. Les noms sont profondément significatifs pour votre
cerveau, et les noms trompeurs ajoutent du chaos à votre code.

Vous pouvez documenter des paramètres, mais demandez-vous si c'est vraiment nécessaire dans
tous les cas. Le niveau de commentaire suggéré par l'outil JavaDoc semble
a p

* * @

Voici une liste de choses qui ne devraient pas apparaître dans les commentaires source.

• • Une liste des fonctions exportées par code dans le fichier. Il y a


programmes qui analysent la source pour vous. Utilisez-les, et la liste est
garantie d'être à jour.
• • Historique des révisions. Voici ce que sont les systèmes de contrôle de code source
pour (voir Contrôle du code source
). Cependant, il peut être utile d'inclure
des informations sur la date du dernier changement et la personne qui[9]l'a effectué.

[9] Ce type d'information, ainsi que le nom du fichier, est fourni par la balise RCS $Id$.

• • Une liste des autres fichiers utilisés par ce fichier. Cela peut être déterminé plus
avec précision à l'aide d'outils automatiques.
• • Le nom du fichier. S'il doit apparaître dans le fichier, ne
l'entretenir à la main. Le RCS et les systèmes similaires peuvent conserver cette
informations mises à jour automatiquement. Si vous déplacez ou renommez le fichier,
vous ne voulez pas avoir à vous rappeler de modifier l'en-tête.

L'un des éléments d'information les plus importants qui devraient apparaître dans le
le fichier source est le nom de l'auteur, pas nécessairement celui qui a modifié le fichier en dernier,
mais le propriétaire. Attacher la responsabilité et l'imputabilité au code source
fait des merveilles pour garder les gens honnêtes (voir Pride and Prejudice ).

Le projet peut également exiger certains avis de droit d'auteur ou d'autres mentions légales.
passe-partout à apparaître dans chaque fichier source. Demandez à votre éditeur de les insérer pour
vous automatiquement.

Avec des commentaires significatifs en place, des outils tels que JavaDoc [ URL 7 ] et
DOC++ [ URL 21 ] peut les extraire et les formater pour produire automatiquement
Documentation au niveau de l'API. Ceci est un exemple spécifique d'un plus général
technique que nous utilisons : les documents exécutables.

Documents
Documents exécutables
exécutables

Supposons que nous ayons une spécification qui répertorie les colonnes d'une table de base de données.
Nous aurons alors un ensemble séparé de commandes SQL pour créer la table réelle

dans la base de données, et probablement une sorte d'enregistrement de langage de programmation


structure pour contenir le contenu d'une ligne dans la table. Les mêmes informations sont
répété trois fois. Changez l'une de ces trois sources, et l'autre
deux sont immédiatement obsolètes. Ceci est une violation claire du DRY
principe.

Pour corriger ce problème, nous devons choisir la source faisant autorité de


information. Cela peut être la spécification, cela peut être un schéma de base de données
outil, ou il peut s'agir d'une troisième source. Choisissons le
document de spécification comme source. C'est maintenant notre modèle pour ce processus.
Nous devons ensuite trouver un moyen d'exporter les informations qu'il contient comme différentes
vues—un schéma de base de données et un enregistrement de langue de haut [dix]niveau, par exemple.

[10] Voir It's Just a View , pour en savoir plus sur les modèles et les vues.

Si votre document est stocké en texte brut avec des commandes de balisage (à l'aide
HTML, LaTeX ou troff, par exemple), vous pouvez utiliser des outils tels que Perl pour
extraire le schéma et le reformater automatiquement. Si votre document est dans un
format binaire du traitement de texte, puis consultez l'encadré de la page suivante pour
certaines options.

Votre document fait désormais partie intégrante du développement du projet. Le seul


changer le schéma est de changer le document. Vous garantissez
que la spécification, le schéma et le code concordent tous. Vous minimisez le
quantité de travail que vous devez effectuer pour chaque modification, et vous pouvez mettre à jour
vues du changement automatiquement.

Que faire si mon document n'est pas en texte brut ?

Malheureusement, de plus en plus de documents de projet sont maintenant


écrit à l'aide de processeurs mondiaux qui stockent le fichier sur disque dans certains
format propriétaire. Nous disons "malheureusement" parce que cela sévèrement
limite vos options pour traiter le document automatiquement.
Cependant, vous avez encore quelques options :

• • Ecrire des macros. Les traitements de texte les plus sophistiqués actuellement
avoir un macro-langage. Avec un peu d'effort, vous pouvez programmer
leur permet d'exporter les sections balisées de vos documents vers le
formes alternatives dont vous avez besoin. Si la programmation à ce niveau est
trop pénible, vous pouvez toujours exporter la section appropriée
dans un fichier texte brut au format standard, puis utilisez un outil
comme Perl pour convertir cela dans les formes finales.
• • Rendre le document subordonné. Plutôt que d'avoir le
document comme source définitive, utilisez un autre

représentation. (Dans l'exemple de la base de données, vous voudrez peut-être


utiliser le schéma comme information faisant autorité.) Ensuite, écrivez
un outil qui exporte ces informations sous une forme que
document peut importer. Soyez prudent, cependant. Vous devez
s'assurer que ces informations sont importées chaque fois que le
document est imprimé, plutôt qu'une seule fois lorsque le
document est créé.

Nous pouvons générer une documentation au niveau de l'API à partir du code source à l'aide d'outils
tels que JavaDoc et DOC++ de la même manière. Le modèle est la source
code : une vue du modèle peut être compilée ; d'autres vues sont censées être
imprimés ou consultés sur le Web. Notre objectif est toujours de travailler sur
modèle - que le modèle soit le code lui-même ou un autre document - et
avoir toutes les vues mises à jour automatiquement (voir Ubiquitous ,Automation
pour plus
sur les processus automatiques).

Du coup, la documentation n'est pas si mal.

Rédacteurs
Rédacteurs techniques
techniques

Jusqu'à présent, nous n'avons parlé que de documentation interne, rédigée par
les programmeurs eux-mêmes. Mais que se passe-t-il lorsque vous avez
des rédacteurs techniques professionnels impliqués dans le projet ? Trop souvent,
les programmeurs jettent simplement du matériel "par-dessus le mur" aux rédacteurs techniques et
laissez-les se débrouiller seuls pour produire des manuels d'utilisation, des pièces promotionnelles,
et ainsi de suite.

C'est une erreur. Ce n'est pas parce que les programmeurs n'écrivent pas ces
documents ne signifie pas que nous pouvons renoncer aux principes pragmatiques. Nous
veulent que les écrivains adoptent les mêmes principes de base qu'un pragmatique
Le programmeur le fait, en particulier en respectant le principe DRY, l'orthogonalité,
le concept de vue modèle et l'utilisation de l'automatisation et des scripts.

Imprimez-le
Imprimez-le ou
ou tissez-le
tissez-le

Un problème inhérent à la documentation papier publiée est qu'elle peut


devient obsolète dès qu'il est imprimé. La documentation de n'importe quel formulaire est juste
un instantané.

Nous essayons donc de produire toute la documentation sous une forme qui peut être publiée
en ligne, sur le Web, complété par des hyperliens. Il est plus facile de garder cette vue de
la documentation à jour que de retrouver tous les exemplaires papier existants,

brûlez-le, et réimprimez et redistribuez de nouvelles copies. C'est aussi une meilleure façon de
répondre aux besoins d'un large public. N'oubliez pas cependant de mettre une date
cachet ou numéro de version sur chaque page Web. De cette façon, le lecteur peut obtenir un
bonne idée de ce qui est à jour, de ce qui a changé récemment et de ce qui ne l'a pas été.

Souvent, vous devez présenter la même documentation dans différents


formats : un document imprimé, des pages Web, une aide en ligne ou peut-être une diapositive
montrer. La solution typique s'appuie fortement sur le copier-coller, créant un
nombre de nouveaux documents indépendants de l'original. C'est une mauvaise idée:
la présentation d'un document doit être indépendante de son contenu.

Si vous utilisez un système de balisage, vous avez la possibilité d'implémenter au fur et à mesure
d e

générer un nouveau chapitre dans la version rapport du document et intituler un


nouvelle diapositive dans le diaporama. Technologies telles que XSL [11]etpeut
CSSêtre
utilisé pour générer plusieurs formats de sortie à partir de ce balisage unique.

[11] eXtensible Style Language et Cascading Style Sheets, deux technologies conçues pour aider à séparer la présentation de

contenu.

Si vous utilisez un traitement de texte, vous aurez probablement des capacités similaires.
Si vous avez pensé à utiliser des styles pour identifier les différents éléments du document,
puis en appliquant différentes feuilles de style, vous pouvez modifier radicalement l'apparence de
la sortie finale. La plupart des traitements de texte vous permettent maintenant de convertir vos
document vers des formats tels que HTML pour la publication Web.

Langages
Langages de
de balisage
balisage

Enfin, pour les projets de documentation à grande échelle, nous recommandons de consulter
certains des schémas les plus modernes de balisage de la documentation.

De nombreux auteurs techniques utilisent désormais DocBook pour définir leurs documents.
DocBook est une norme de balisage basée sur SGML qui identifie soigneusement
chaque composant d'un document. Le document peut passer par un
Processeur DSSSL pour le restituer dans n'importe quel nombre de formats différents. Le
Le projet de documentation Linux utilise DocBook pour publier des informations en RTF,

, info, PostScript et HTML.

Tant que votre balisage d'origine est suffisamment riche pour exprimer tous les concepts
dont vous avez besoin (y compris les hyperliens), traduction vers toute autre forme pouvant être publiée
peut être à la fois facile et automatique. Vous pouvez produire une aide en ligne, publiée
des manuels, des produits phares pour le site Web et même un calendrier de conseils par jour,
tous de la même source, qui est bien sûr sous contrôle de source et est
construit avec la construction nocturne (voir Ubiquitous Automation
).

La documentation et le code sont des vues différentes du même modèle sous-jacent,


mais la vue est tout ce qui devrait être différent. Ne laissez pas la documentation devenir
un citoyen de seconde classe, banni du flux de travail principal du projet. Traiter
documentation avec le même soin que vous traitez le code, et les utilisateurs (et
mainteneurs qui suivent) chanteront vos louanges.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Les maux de la duplication


• • Orthogonalité
• • La puissance du texte brut
• • Contrôle du code source
• • C'est juste une vue
• • Programmation par coïncidence
• • La fosse aux exigences
• • Automatisation omniprésente

Défis
Défis

• • Avez-vous écrit un commentaire explicatif pour le code source que vous


vient d'écrire ? Pourquoi pas? Pressé par le temps ? Je ne sais pas si le code sera vraiment
travail - essayez-vous simplement une idée en tant que prototype ? tu vas jeter
le code après, n'est-ce pas ? Cela ne fera pas partie du projet
non commenté et expérimental, n'est-ce pas ?
• • Parfois, il est inconfortable de documenter la conception de la source
coder parce que la conception n'est pas claire dans votre esprit ; ça évolue encore.
Vous ne pensez pas que vous devriez gaspiller vos efforts à décrire ce que
quelque chose fait jusqu'à ce qu'il le fasse réellement. Cela ressemble-t-il à
programmation par coïncidence (page 172) ?

des malentendus lors de l'analyse des exigences qui doivent être résolus ?
Le logiciel s'adapte-t-il à l'utilisateur comme une extension de la main ? (Non seulement nous
voulons que nos propres outils tiennent dans nos mains, mais nous voulons les outils que nous créons pour
utilisateurs de s'adapter également à leurs mains.)
Comme pour la validation et la vérification, vous devez effectuer des tests d'utilisabilité comme
le plus tôt possible, tant qu'il est encore temps d'apporter des corrections. Pour les plus grands
projets, vous voudrez peut-être faire appel à des spécialistes des facteurs humains. (Si rien
sinon, c'est amusant de jouer avec les rétroviseurs sans tain).

Le non-respect des critères d'utilisabilité est un bogue aussi important que la division par zéro.

Comment
Comment tester
tester

Nous avons regardé quoi tester. Maintenant, nous allons porter notre attention sur la façon de tester,
y compris:

• • Les tests de régression


• • Données de test
• • Exercer des systèmes GUI
• • Tester les tests
• • Tester minutieusement

Test de conception/méthodologie
Pouvez-vous tester la conception du code lui-même et la méthodologie que vous
utilisé pour créer le logiciel ? Après une mode, oui vous pouvez. Tu fais cela
en analysant les métriques - mesures de divers aspects du code.
La métrique la plus simple (et souvent la moins intéressante) est celle des lignes de
code—quelle est la taille du code lui-même ?

Il existe une grande variété d'autres mesures que vous pouvez utiliser pour examiner
codes, y compris :

• • Métrique de complexité cyclomatique de McCabe (mesure


complexité des structures de décision)
• • Fan-in d'héritage (nombre de classes de base) et fan-out
(nombre de modules dérivés utilisant celui-ci comme parent)
• • Ensemble de réponses (voir Découplage et loi de Déméter)
• • Rapports de couplage de classe (voir [ URL 48 ])

Certaines mesures sont conçues pour vous donner une « note de passage », tandis que
d'autres ne sont utiles que par comparaison. Autrement dit, vous calculez ces
métriques pour chaque module du système et voir comment un particulier
module se rapporte à ses frères. Techniques statistiques standard
(comme la moyenne et l'écart type) sont généralement utilisés ici.

Si vous trouvez un module dont les métriques sont sensiblement différentes de toutes

le reste, vous devez vous demander si cela est approprié. Pour certains
modules, il peut être acceptable de "faire exploser la courbe". Mais pour ceux qui ne le font pas
avoir une bonne excuse, cela peut indiquer des problèmes.

Les
Les tests
tests de
de régression
régression

Un test de régression compare la sortie du test actuel avec le test précédent (ou
valeurs connues). Nous pouvons nous assurer que les bogues que nous avons corrigés aujourd'hui n'ont rien cassé
qui fonctionnaient hier. Il s'agit d'un filet de sécurité important, et il coupe
à l'abri des mauvaises surprises.

Tous les tests que nous avons mentionnés jusqu'à présent peuvent être exécutés comme des tests de régression,
s'assurer que nous n'avons pas perdu de terrain à mesure que nous développons un nouveau code. Nous pouvons
exécuter des régressions pour vérifier les performances, les contrats, la validité, etc.

Données
Données de
de test
test

Où obtenons-nous les données pour exécuter tous ces tests ? Il n'y a que deux sortes de
données : données du monde réel et données synthétiques. En fait, nous devons utiliser les deux,
parce que les différentes natures de ces types de données exposeront différents
bogues dans notre logiciel.

Les données du monde réel proviennent d'une source réelle. Peut-être a-t-il été
collectées à partir d'un système existant, d'un système concurrent ou d'un prototype de
une sorte. Il représente les données utilisateur typiques. Les grandes surprises arrivent lorsque vous
découvrez ce que signifie typique. Ceci est le plus susceptible de révéler des défauts et
malentendus dans l'analyse des besoins.

Les données synthétiques sont générées artificiellement, peut-être sous certaines conditions statistiques.
contraintes. Vous devrez peut-être utiliser des données synthétiques pour l'un des éléments suivants
les raisons.

• • Vous avez besoin de beaucoup de données, peut-être plus que n'importe quel échantillon du monde réel
pourrait fournir. Vous pourrez peut-être utiliser les données du monde réel comme graine
pour générer un ensemble d'échantillons plus large et modifier certains champs qui doivent
être unique.
• • Vous avez besoin de données pour souligner les conditions aux limites. Ces données peuvent
être complètement synthétique : champs de date contenant le 29 février 1999,
des tailles d'enregistrement énormes ou des adresses avec des codes postaux étrangers.
• • Vous avez besoin de données présentant certaines propriétés statistiques. Vouloir
pour voir ce qui se passe si une transaction sur trois échoue ? Se souvenir du
algorithme de tri qui ralentit en rampant lorsqu'il reçoit des données pré-triées ?

Vous pouvez présenter les données dans un ordre aléatoire ou trié pour exposer ce type de
faiblesse.

Exercer
Exercer des
des systèmes
systèmes GUI
GUI

Tester des systèmes gourmands en interfaces graphiques nécessite souvent des outils de test spécialisés.
Ces outils peuvent être basés sur un simple modèle de capture/lecture d'événements, ou ils
peut nécessiter des scripts spécialement écrits pour piloter l'interface graphique. Certains systèmes
combiner des éléments des deux.

Des outils moins sophistiqués imposent un degré élevé de couplage entre les
version du logiciel testé et le script de test lui-même : si vous déplacez un
boîte de dialogue ou réduisez la taille d'un bouton, le test risque de ne pas le trouver, et
peut tomber. La plupart des outils de test GUI modernes utilisent un certain nombre de
techniques pour contourner ce problème et essayer de s'adapter à une mise en page mineure
différences.

Cependant, vous ne pouvez pas tout automatiser. Andy a travaillé sur un graphisme
système permettant à l'utilisateur de créer et d'afficher un visuel non déterministe
effets simulant divers phénomènes naturels. Malheureusement, pendant
test, vous ne pouviez pas simplement saisir un bitmap et comparer la sortie avec un
précédent, car il a été conçu pour être différent à chaque fois. Pour
situations comme celle-ci, vous n'aurez peut-être pas d'autre choix que de vous fier au manuel
interprétation des résultats des tests.

L'un des nombreux avantages de l'écriture de code découplé (voir Découplage et


la loi de Déméter) est un test plus modulaire. Par exemple, pour les données
traitement des applications qui ont une interface graphique, votre conception doit être
suffisamment découplé pour que vous puissiez tester la logique de l'application sans avoir
une interface graphique présente. Cette idée revient à tester d'abord vos sous-composants.
Une fois la logique applicative validée, il devient plus facile de localiser
bogues qui apparaissent avec l'interface utilisateur en place (il est probable que les bogues
ont été créés par le code de l'interface utilisateur).
Tester
Tester les
les tests
tests

Parce que nous ne pouvons pas écrire un logiciel parfait, il s'ensuit que nous ne pouvons pas écrire
logiciel de test parfait non plus. Nous devons tester les tests.

Considérez notre ensemble de suites de tests comme un système de sécurité élaboré, conçu pour
sonner l'alarme lorsqu'un bug apparaît. Comment mieux tester un système de sécurité
que d'essayer de s'introduire ?

Après avoir écrit un test pour détecter un bogue particulier, provoquez le bogue
délibérément et assurez-vous que le test se plaint. Cela garantit que le test
attrapera le bogue si cela se produit pour de vrai.

Astuce
Astuce 64
64

Utilisez des saboteurs pour tester vos tests

Si vous êtes vraiment sérieux au sujet des tests, vous voudrez peut-être nommer un projet
saboteur. Le rôle du saboteur est de prendre une copie séparée de l'arbre source,
introduisez des bogues exprès et vérifiez que les tests les détecteront.

Lors de l'écriture des tests, assurez-vous que les alarmes sonnent quand elles le devraient.

Tester
Tester soigneusement
soigneusement

Une fois que vous êtes sûr que vos tests sont corrects et que vous trouvez des bogues, vous
créer, comment savez-vous si vous avez testé la base de code à fond
assez?

La réponse courte est "vous ne le faites pas", et vous ne le ferez jamais. Mais il existe des produits
sur le marché qui peut aider. Ces outils d'analyse de couverture surveillent votre code
pendant les tests et garder une trace des lignes de code qui ont été exécutées et
qui n'ont pas. Ces outils vous donnent une idée générale de la façon dont
vos tests sont complets, mais ne vous attendez pas à une couverture à 100 %.

Même si vous touchez chaque ligne de code, ce n'est pas tout.


Ce qui est important, c'est le nombre d'états que votre programme peut avoir.
Les états ne sont pas équivalents à des lignes de code. Par exemple, supposons que vous ayez un
fonction qui prend deux nombres entiers, chacun pouvant être un nombre compris entre 0 et
9 9

En théorie, cette fonction à trois lignes possède 1 000 000 d'états logiques, 999 999 de
qui fonctionnera correctement et une qui ne fonctionnera pas (lorsque a + b est égal à zéro).
Le simple fait de savoir que vous avez exécuté cette ligne de code ne vous dit pas
cela - vous auriez besoin d'identifier tous les états possibles du programme.

Malheureusement, en général, c'est un problème très difficile. Dur comme dans "Le
le soleil sera une masse froide et dure avant que vous ne puissiez le résoudre."

Astuce
Astuce 65
65

Couverture de l'état du test, pas de la couverture du code

Même avec une bonne couverture de code, les données que vous utilisez pour les tests ont toujours un énorme
impact, et, plus important encore, l'ordre dans lequel vous parcourez le code peut
ont le plus grand impact de tous.

Quand
Quand tester
tester

De nombreux projets ont tendance à laisser les tests à la dernière minute, là où ils seront
être coupé contre le tranchant d'un délai. [8] Nous devons commencer beaucoup plus tôt
que ça. Dès qu'un code de production existe, il doit être testé.

[8]
[8] morts
morts
......ligne \ded-lîn\ n (1864) une ligne tracée à l'intérieur ou autour d'une prison qu'un prisonnier passe au risque d'être

tir—Dictionnaire collégial Webster.

La plupart des tests doivent être effectués automatiquement. Il est important de noter que par
"automatiquement" signifie que les résultats du test sont interprétés automatiquement
aussi. Voir Ubiquitous Automation , pour plus d'informations à ce sujet.

Nous aimons tester aussi souvent que possible, et toujours avant de vérifier le code
dans le référentiel source. Certains systèmes de contrôle de code source, comme Aegis,
p e

Habituellement, ce n'est pas un problème d'exécuter des régressions sur l'ensemble de l'unité individuelle
tests et tests d'intégration aussi souvent que nécessaire.

Mais certains tests peuvent ne pas être facilement exécutés aussi fréquemment. Stress
les tests, par exemple, peuvent nécessiter une configuration ou un équipement spécial, et une certaine main
holding. Ces tests peuvent être exécutés moins souvent - hebdomadairement ou mensuellement, peut-être.
Mais il est important qu'ils soient exécutés sur une base régulière et planifiée. Si ça ne peut pas
être fait automatiquement, puis assurez-vous qu'il apparaît sur le calendrier, avec tous
les ressources nécessaires allouées à la tâche.

Resserrer
Resserrer le
le filet
filet

Enfin, nous aimerions révéler le concept le plus important dans les tests. Il
est une évidence, et pratiquement tous les manuels disent de le faire de cette façon. Mais
pour une raison quelconque, la plupart des projets ne le font toujours pas.

Si un bogue se glisse dans le filet des tests existants, vous devez ajouter un nouveau test à
attrapez-le la prochaine fois.

Astuce
Astuce 66
66

Trouver des bogues une fois

Une fois qu'un testeur humain trouve un bogue, ce devrait être la dernière fois qu'un testeur humain
trouve ce bogue. Les tests automatisés doivent être modifiés pour vérifier que
bogue particulier à partir de là, à chaque fois, sans exception, peu importe comment
trivial, et peu importe à quel point le développeur se plaint et dit : "Oh,
Cela n'arrivera plus jamais."
Parce des
après que bugs
cela se
quereproduira. Et nous n'avons
les tests automatisés tout simplement
auraient pas leNous
pu nous trouver. temps d'aller chasser
devons
passons notre temps à écrire du nouveau code et de nouveaux bugs.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Le chat a mangé mon code source


• • Débogage
• • Le découplage et la loi de Déméter
• • Refactorisation
• • Code facile à tester
• • Automatisation omniprésente

Défis
Défis

• • Pouvez-vous tester automatiquement votre projet ? De nombreuses équipes sont obligées


pour répondre "non". Pourquoi? Est-il trop difficile de définir les résultats acceptables ?
Cela ne rendra-t-il pas difficile de prouver aux sponsors que le projet est
"fait"?

Est-il trop difficile de tester la logique de l'application indépendamment de l'interface graphique ?


Qu'est-ce que cela dit sur l'interface graphique ? A propos de couplage?

De
De grandes
grandes attentes
attentes

Soyez étonnés, ô cieux, de cela, et ayez une peur horrible…

Jérémie
Jérémie 2:12
2:12

Une entreprise annonce des bénéfices records et le cours de son action chute de 20 %. Le
des nouvelles financières ce soir-là expliquent que l'entreprise n'a pas réussi à se réunir
attentes des analystes. Un enfant ouvre un cadeau de Noël coûteux et
éclate en sanglots - ce n'était pas la poupée bon marché que l'enfant espérait. UN
l'équipe du projet fait des miracles pour mettre en œuvre une solution d'une complexité phénoménale
application, seulement pour la voir boudée par ses utilisateurs parce qu'elle n'a pas de
système d'aide.

Dans un sens abstrait, une application est réussie si elle implémente correctement
ses spécifications. Malheureusement, cela ne paie que des factures abstraites.

En réalité, le succès d'un projet se mesure à sa capacité à répondre aux


attentes de ses utilisateurs. Un projet qui tombe en deçà de leurs attentes est
considéré comme un échec, quelle que soit la qualité du livrable en termes absolus.
Cependant, comme le parent de l'enfant qui attend la poupée bon marché, allez trop loin et
vous serez un échec, aussi.

Astuce
Astuce 69
69

Dépassez en douceur les attentes de vos utilisateurs

Cependant, l'exécution de cette astuce nécessite un certain travail.

Communiquer
Communiquer les
les attentes
attentes

Les utilisateurs viennent d'abord vers vous avec une vision de ce qu'ils veulent. C'est possible
incomplet, incohérent ou techniquement impossible, mais c'est le leur, et, comme
l'enfant à Noël, ils y investissent une certaine émotion. Vous ne pouvez pas
n'y faites pas attention.

Au fur et à mesure que votre compréhension de leurs besoins se développera, vous découvrirez des domaines où leurs
attentes ne peuvent être satisfaites, ou lorsque leurs attentes sont peut-être trop
conservateur. Une partie de votre rôle est de communiquer cela. Travaillez avec votre
utilisateurs afin que leur compréhension de ce que vous allez fournir soit exacte.
Et faites-le tout au long du processus de développement. Ne perdez jamais de vue la
les problèmes métier que votre application est censée résoudre.

Certains consultants appellent ce processus « gérer les attentes » — activement


contrôler ce que les utilisateurs devraient espérer obtenir de leurs systèmes. Nous pensons que cela
est une position quelque peu élitiste. Notre rôle n'est pas de contrôler les espoirs de nos
utilisateurs. Au lieu de cela, nous devons travailler avec eux pour parvenir à un accord
compréhension du processus de développement et du livrable final, ainsi que
avec ces attentes qu'ils n'ont pas encore verbalisées. Si l'équipe est
communiquer couramment avec le monde extérieur, ce processus est presque
automatique; tout le monde devrait comprendre ce qui est attendu et comment ce sera
construit.

Certaines techniques importantes peuvent être utilisées pour faciliter cette


processus. Parmi celles-ci, les balles
, et traçantes
Prototypes et Post-it , sont les
le plus important. Les deux permettent à l'équipe de construire quelque chose que l'utilisateur peut
voir. Les deux sont des moyens idéaux de communiquer votre compréhension de leur
exigences. Et les deux vous permettent, à vous et à vos utilisateurs, de vous entraîner à communiquer
avec l'un l'autre.

Le
Le mille
mille supplémentaire
supplémentaire

Si vous travaillez en étroite collaboration avec vos utilisateurs, partagez leurs attentes et
communiquer ce que vous faites, il y aura peu de surprises lorsque
le projet est livré.

C'est une mauvaise chose. Essayez de surprendre vos utilisateurs. Ne pas leur faire peur, attention,
mais ravis-les.

Donnez-leur un peu plus que ce à quoi ils s'attendaient. Le petit plus de


l'effort requis pour ajouter une fonctionnalité orientée utilisateur au système paiera
pour lui-même maintes et maintes fois dans la bonne volonté.

Écoutez vos utilisateurs au fur et à mesure que le projet progresse pour obtenir des indices sur les fonctionnalités
les ravirait vraiment. Certaines choses que vous pouvez ajouter assez facilement
sembler bon à l'utilisateur moyen comprennent :

• • Aide bulle ou info-bulle


• • Raccourcis clavier
• • Un guide de référence rapide en complément du manuel d'utilisation
• • Colorisation
• • Analyseurs de fichiers journaux
• • Installation automatisée
• • Outils de vérification de l'intégrité du système
• • La possibilité d'exécuter plusieurs versions du système pour la formation
• • Un écran de démarrage personnalisé pour leur organisation

Toutes ces choses sont relativement superficielles et ne surchargent pas vraiment


le système avec fonctionnalité ballonnement. Cependant, chacun indique à vos utilisateurs que le
l'équipe de développement s'est souciée de produire un excellent système, qui a été
destiné à un usage réel. N'oubliez pas de ne pas casser le système en ajoutant ces
nouvelles fonctionnalités.

Les
Les sections
sections connexes
connexes comprennent
comprennent ::

• • Logiciel suffisamment bon


• • Balles traçantes
• • Prototypes et Post-it
• • La fosse aux exigences

Défis
Défis

• • Parfois, les critiques les plus sévères d'un projet sont les personnes qui
travaillé dessus. Avez-vous déjà été déçu que votre
vos propres attentes n'ont pas été satisfaites par quelque chose que vous avez produit ? Comment
cela pourrait-il être? Peut-être y a-t-il plus que de la logique à l'œuvre ici.
• • Que commentent vos utilisateurs lorsque vous fournissez un logiciel ? Est
leur attention aux différents domaines de l'application proportionnelle à
l'effort que vous avez investi dans chacun ? Qu'est-ce qui les ravit ?

Orgueil
Orgueil et
et préjugés
préjugés

Vous nous avez ravis assez longtemps.

Jane
Jane Austen,
Austen, Orgueil
Orgueil et
et préjugés
préjugés

Les programmeurs pragmatiques ne se dérobent pas à la responsabilité. Au lieu de cela, nous nous réjouissons
à relever des défis et à faire connaître notre expertise. Si nous sommes
responsables d'un design ou d'un morceau de code, nous faisons un travail dont nous pouvons être fiers.

Astuce
Astuce 70
70

Signez votre travail

Les artisans d'autrefois étaient fiers de signer leur travail. Tu devrais être,
aussi.

Cependant, les équipes de projet sont toujours composées de personnes et cette règle peut entraîner
inquiéter. Sur certains projets, l'idée de propriété du code peut provoquer une coopération

problèmes. Les gens peuvent devenir territoriaux ou ne pas vouloir travailler sur des projets communs
éléments de fondation. Le projet peut finir comme un tas de petits insulaires
fiefs. Vous développez des préjugés en faveur de votre code et contre votre
collègues de travail.

Ce n'est pas ce que nous voulons. Vous ne devriez pas défendre jalousement votre code contre
intrus ; de la même manière, vous devez traiter le code des autres avec
respect. La règle d'or ("Fais aux autres ce que tu voudrais qu'ils fassent
vous") et une base de respect mutuel entre les développeurs est essentielle pour
faire fonctionner cette astuce.

L'anonymat, en particulier sur les grands projets, peut constituer un terreau fertile pour
négligence, erreurs, paresse et mauvais code. Il devient trop facile de voir
vous-même comme un simple rouage dans la roue, produisant des excuses boiteuses dans un statut sans fin
des rapports au lieu d'un bon code.

Bien que le code doive appartenir à un individu, il n'est pas nécessaire qu'il appartienne à un individu. Dans
En fait, la méthode de programmation eXtreme réussie de Kent Beck [ URL ] 45
recommande la propriété commune du code (mais cela nécessite également des
pratiques, telles que la programmation en binôme, pour se prémunir contre les dangers de
anonymat).

Nous voulons voir la fierté de la propriété. "J'ai écrit ceci, et je me tiens derrière mon
travail." Votre signature devrait être reconnue comme un indicateur de
qualité. Les gens devraient voir votre nom sur un morceau de code et s'attendre à ce qu'il soit
solide, bien écrit, testé et documenté. Un travail vraiment professionnel.
Ecrit par un vrai professionnel.

Un programmeur pragmatique.
Annexe A. Ressources
La seule raison pour laquelle nous avons pu couvrir autant de terrain dans ce livre est que
nous avons vu beaucoup de nos sujets d'une haute altitude. Si nous leur avions donné le
couverture approfondie qu'ils méritaient, le livre aurait été dix fois
plus long.

Nous avons commencé le livre avec la suggestion que les programmeurs pragmatiques
devrait toujours apprendre. Dans cette annexe, nous avons répertorié les ressources qui peuvent
vous aider dans cette démarche.

Dans la section Sociétés professionnelles, nous donnons des détails sur l'IEEE et les
ACM. Nous recommandons aux programmeurs pragmatiques de rejoindre l'un (ou les deux) de
ces sociétés. Ensuite, dans Construire une bibliothèque, nous mettons en évidence des périodiques, des livres,
et les sites Web qui, selon nous, contiennent des informations pertinentes et de haute qualité
(ou qui sont tout simplement amusants).

Tout au long du livre, nous avons fait référence à de nombreuses ressources logicielles accessibles via
l'Internet. Dans la section Ressources Internet, nous listons les URL de ces
ressources, accompagnées d'une brève description de chacune. Cependant, la nature de
le Web signifie que bon nombre de ces liens pourraient bien être obsolètes au moment où vous
lis ce livre. Vous pouvez essayer l'un des nombreux moteurs de recherche pour en savoir plus.
lien à jour ou visitez notre site Web à l'adresse www.pragmaticprogrammer.com
et consultez notre section de liens.

Enfin, cette annexe contient la bibliographie du livre.

Sociétés
Sociétés professionnelles
professionnelles

Il existe deux sociétés professionnelles de classe mondiale pour les programmeurs : la


[1] et l'ordinateur IEEE
Association pour les machines informatiques (ACM)
Société.[2] Nous recommandons que tous les programmeurs appartiennent à l'un (ou aux deux)
ces sociétés. De plus, les développeurs en dehors des États-Unis peuvent vouloir
d'adhérer à leurs sociétés nationales, comme la BCS au Royaume-Uni.

[1] Services aux membres ACM, PO Box 11414, New York, NY 10286, États-Unis.

www.acm.org

[2] 1730 Massachusetts Avenue NW, Washington, DC 20036-1992, États-Unis.

www.ordinateur.org

L'adhésion à une société professionnelle présente de nombreux avantages. Les conférences


et les réunions locales vous offrent d'excellentes occasions de rencontrer des personnes ayant les mêmes
intérêts, et les groupes d'intérêts spéciaux et les comités techniques vous donnent
la possibilité de participer à l'établissement des normes et des lignes directrices utilisées
autour du monde. Vous tirerez également beaucoup de leurs publications, de
des discussions de haut niveau sur la pratique de l'industrie à la théorie de l'informatique de bas niveau.

Construire
Construire une
une bibliothèque
bibliothèque

Nous sommes grands sur la lecture. Comme nous l'avons noté dans Votre portefeuille de connaissances , une bonne
programmeur est toujours en train d'apprendre. Se tenir au courant des livres et
les périodiques peuvent aider. En voici quelques-uns que nous aimons.

Périodiques
Périodiques

Si vous êtes comme nous, vous conserverez de vieux magazines et périodiques jusqu'à ce qu'ils soient
empilés assez haut pour transformer ceux du bas en feuilles plates de diamant. Ce
signifie qu'il vaut la peine d'être assez sélectif. Voici quelques périodiques que nous lisons.

• • Ordinateur IEEE. Envoyé aux membres de l'IEEE Computer


Société, l'informatique a une orientation pratique mais n'a pas peur de la théorie.
Certaines questions sont orientées autour d'un thème, tandis que d'autres sont simplement
recueils d'articles intéressants. Ce magazine a une bonne
rapport signal sur bruit.
• • Logiciel IEEE. Ceci est une autre excellente publication bimensuelle de
l'IEEE Computer Society destinée aux praticiens du logiciel.
• • Communications de l'ACM. Le magazine de base reçu par
tous membres de l'ACM, CACM a été une norme dans l'industrie
pendant des décennies, et a probablement publié plus d'articles fondateurs que
toute autre source.
• • SIGPLAN. Produit par le groupe d'intérêt spécial de l'ACM sur
Langages de programmation, SIGPLAN est un ajout facultatif à votre
Adhésion à l'ACM. Il est souvent utilisé pour la langue de publication
spécifications, ainsi que des articles d'intérêt pour tous ceux qui aiment
regarder profondément dans la programmation.
• • Journal du Dr Dobbs. Un magazine mensuel, disponible par
abonnement et dans les kiosques à journaux, le Dr Dobbs est excentrique, mais a
articles allant de la pratique au niveau du bit à la théorie lourde.
• • Le Journal Perl. Si vous aimez Perl, vous devriez probablement
abonnez-vous au Perl Journal ( www.tpj.com ).
• • Magazine de développement logiciel. Un magazine mensuel
se concentrant sur les questions générales de gestion de projet et de logiciel
développement.

Documents
Documents commerciaux
commerciaux hebdomadaires
hebdomadaires

Il existe plusieurs journaux hebdomadaires publiés pour les développeurs et leurs


gestionnaires. Ces documents sont en grande partie une collection de communiqués de presse d'entreprises,
redressés comme des articles. Cependant, le contenu est toujours précieux - il vous permet
suivre ce qui se passe, se tenir au courant des annonces de nouveaux produits et
suivre les alliances de l'industrie à mesure qu'elles se forgent et se brisent. Ne vous attendez pas à beaucoup de
une couverture technique approfondie, cependant.

Livres
Livres

Les livres d'informatique peuvent être coûteux, mais choisissez-les avec soin et ils sont un
investissement qui en vaut la peine. Voici une poignée des nombreux que nous aimons.

Analyse
Analyse et
et conception
conception
•• •• Construction
Construction de de logiciels
logiciels orientés
orientés objet,
objet, 2ème
2ème
Édition. Le livre épique de Bertrand Meyer sur les fondamentaux de
développement orienté objet, le tout en 1300 pages environ [ Mey97b ].
• • Modèles de conception. Un modèle de conception décrit une façon de résoudre un
classe particulière de problèmes à un niveau plus élevé qu'une programmation
idiome de la langue. Ce livre désormais classique [] GHJV95
par le Gang de
Quatre décrit 23 modèles de conception de base, y compris Proxy, Visitor,
et Singleton.
• • Modèles d'analyse. Un trésor d'architecture de haut niveau
modèles tirés d'une grande variété de projets réels et
distillé sous forme de livre. Un moyen relativement rapide d'avoir un aperçu de
de nombreuses années d'expérience en modélisation]. [ Fow96

Equipes
Equipes et
et Projets
Projets

• • Le Mois de l'Homme Mythique. Le classique de Fred Brooks sur les périls de


organiser des équipes de projet, récemment mis à jour [ Bro95 ].
• • Dynamique du développement logiciel. Une série de courts essais
sur la construction de logiciels dans de grandes équipes, en se concentrant sur la dynamique
entre les membres de l'équipe, et entre l'équipe et le reste de la
monde [ McC95 ].
•• •• Survivre
Survivre aux
aux projets
projets orientés
orientés objet
objet :: un
un gestionnaire
gestionnaire
Guide. Les "rapports des tranchées" d'Alistair Cockburn illustrent
bon nombre des périls et des pièges de la gestion d'un projet OO—

surtout votre premier. M. Cockburn fournit des conseils et des techniques


pour vous aider à résoudre les problèmes les plus courants]. [ Coc97b

Environnements
Environnements spécifiques
spécifiques

• • Unix. W. Richard Stevens a plusieurs excellents livres


y compris la programmation avancée dans l'environnement Unix et le
Livres de programmation réseau Unix [ Ste92 , Ste98 , Ste99 ].
• • Les fenêtres. Les services système Win32 de Marshall Brain [ Bra95 ] sont
une référence concise aux API de bas niveau. de Charles Petzold
Programmation Windows [ Pet98 ] est la bible de Windows GUI
développement.
• • C++. Dès que vous vous retrouvez sur un projet C++, lancez, ne
marcher, aller à la librairie et acheter Effective C++ de Scott Meyer, et
C++ éventuellement plus efficace [ Mey97a , Mey96 ]. Pour les systèmes de construction
de toute taille appréciable, vous avez besoin du C++ à grande échelle de John Lakos
Conception de logiciels [ Lak96 ]. Pour les techniques avancées, tournez-vous vers Jim
Styles et idiomes de programmation C++ avancés de Coplien [ Cop92 ],

De plus, la série O'Reilly Nutshell ( www.ora.com ) donne des


traitements complets de sujets et de langues divers tels que
perl, yacc, sendmail, composants internes de Windows et expressions régulières.

La
La toile
toile

Trouver du bon contenu sur le Web est difficile. Voici plusieurs liens que nous
vérifier au moins une fois par semaine.

• • Slashdot. Présenté comme "Des nouvelles pour les nerds. Des trucs qui comptent",
Slashdot est l'un des foyers Internet de la communauté Linux. Ainsi que
mises à jour régulières sur l'actualité Linux, le site propose des informations sur
des technologies cool et des problèmes qui affectent les développeurs.

www.slashdot.org

• • Liens Cetus. Des milliers de liens sur des sujets orientés objet.

www.cetus-links.org
• • WikiWikiWeb. Le référentiel de modèles de Portland et les modèles
discussion. Non seulement une excellente ressource, le site WikiWikiWeb est un
expérience intéressante d'édition collective d'idées.

www.c2.com

Ressources
Ressources Internet
Internet

Les liens ci-dessous renvoient à des ressources disponibles sur Internet. Ils étaient valides
au moment de la rédaction, mais (le Net étant ce qu'il est) ils pourraient bien être hors de
date au moment où vous lisez ceci. Si oui, vous pouvez essayer une recherche générale pour le
noms de fichiers ou rendez-vous sur le site Web de Pragmatic Programmer
( www.pragmaticprogrammer.com ) et suivez nos liens.

Éditeurs
Éditeurs

Emacs et vi ne sont pas les seuls éditeurs multiplateformes, mais ils sont librement
disponible et largement utilisé. Un rapide tour d'horizon d'un magazine tel que Dr.
Dobbs proposera plusieurs alternatives commerciales.

Emacs
Emacs

Emacs et XEmacs sont disponibles sur les plates-formes Unix et Windows.

[URL
[URL l]l] L'éditeur
L'éditeur Emacs
Emacs

www.gnu.org

Le nec plus ultra des grands éditeurs, contenant toutes les fonctionnalités dont dispose n'importe quel éditeur
jamais eu, Emacs a une courbe d'apprentissage presque verticale, mais rembourse généreusement
une fois que vous l'avez maîtrisé. Il fait également un excellent centre commercial et un lecteur de nouvelles,
carnet d'adresses, calendrier et agenda, jeu d'aventure, ….

[URL
[URL 2]
2] L'éditeur
L'éditeur XEmacs
XEmacs

www.xemacs.org

Issu de l'Emacs original il y a quelques années, XEmacs est réputé pour


ont des composants internes plus propres et une interface plus attrayante.

vi
vi

Il existe au moins 15 clones vi différents disponibles. Parmi ceux-ci, vim est probablement
porté sur la plupart des plates-formes, et serait donc un bon choix d'éditeur si vous
se retrouver à travailler dans de nombreux environnements différents.

[URL
[URL 3]
3] L'éditeur
L'éditeur Vim
Vim

ftp://ftp.fu-berlin.de/misc/editors/vim

D'après la documentation : "Il y a beaucoup d'améliorations au-dessus de vi : multi


annulation de niveau, multi-fenêtres et tampons, coloration syntaxique, ligne de commande
édition, complétion de nom de fichier, aide en ligne, sélection visuelle, etc…."

[URL
[URL 4]
4] L'éditeur
L'éditeur elvis
elvis

www.fh-wedel.de/elvis

Un clone vi amélioré prenant en charge X.

[URL
[URL 5]
5] Mode
Mode Emacs
Emacs Vipère
Vipère

http://www.cs.sunysb.edu/~kifer/emacs.html

Viper est un ensemble de macros qui font ressembler Emacs à vi. Certains peuvent douter de
la sagesse de prendre le plus grand éditeur du monde et de l'étendre pour imiter un
éditeur dont la force est sa compacité. D'autres prétendent qu'il combine le meilleur
des deux mondes.

Compilateurs,
Compilateurs, langages
langages et
et outils
outils de
de développement
développement

[URL
[URL 6]
6] Le
Le compilateur
compilateur GNU
GNU C/C++
C/C++

www.fsf.org/software/gcc/gcc.html

L'un des compilateurs C et C++ les plus populaires de la planète. Cela fait aussi
Objectif c. (Au moment de la rédaction, le projet egcs, qui
séparé de gcc, est en train de se fondre dans le giron.)

[URL
[URL 7]
7] Le
Le langage
langage Java
Java de
de Sun
Sun

java.sun.com

Accueil de Java, y compris les SDK téléchargeables, la documentation, les didacticiels,


nouvelles, et plus encore.

[URL
[URL 8]
8] Page
Page d'accueil
d'accueil du
du langage
langage Perl
Perl

www.perl.com

O'Reilly héberge cet ensemble de ressources liées à Peri.

[URL
[URL 9]
9] Le
Le langage
langage Python
Python

www.python.org

Le langage de programmation orienté objet Python est interprété et


interactif, avec une syntaxe légèrement décalée et un public large et fidèle.

[URL
[URL 10]
10] PetitEiffel
PetitEiffel

PetitEiffel.loria.fr

Le compilateur GNU Eiffel s'exécute sur n'importe quelle machine disposant d'un compilateur ANSI C
et un environnement d'exécution Posix.

[URL
[URL 11]
11] ISE
ISE Eiffel
Eiffel

www.eiffel.com
Interactive Software Engineering est à l'origine de Design by Contract,
et vend un compilateur Eiffel commercial et les outils associés.

[URL
[URL 12]
12] Sather
Sather

www.icsi.berkeley.edu/~sather

Sather est un langage expérimental issu d'Eiffel. Il vise à


prendre en charge les fonctions d'ordre supérieur et l'abstraction d'itération ainsi que
Common Lisp, CLU ou Scheme, et être aussi efficace que C, C++ ou Fortran.

[URL
[URL 13]
13] Visual
Visual Works
Works

www.objectshare.com

Accueil de l'environnement VisualWorks Smalltalk. Versions non commerciales


pour Windows et Linux sont disponibles gratuitement.

[URL
[URL 14]
14] L'environnement
L'environnement du
du langage
langage Squeak
Squeak

squeak.cs.uiuc.edu

Squeak est une implémentation portable et disponible gratuitement de Smalltalk-80


écrit en soi; il peut produire une sortie de code C pour des performances supérieures.

[URL
[URL 15]
15] Le
Le langage
langage de
de programmation
programmation TOM
TOM

www.gerbil.org/tom

Un langage très dynamique avec des racines en Objective-C.

[URL
[URL 16]
16] Le
Le projet
projet Beowulf
Beowulf

www.beowulf.org

Un projet qui construit des ordinateurs hautes performances à partir de clusters en réseau
de boîtes Linux bon marché.

[URL
[URL 17]
17] iContract—Outil
iContract—Outil de
de conception
conception par
par contrat
contrat pour
pour Java
Java

www.reliable-systems.com

Design by Contract formalisme des préconditions, postconditions et


invariants, implémentés comme préprocesseur pour Java. Honore l'héritage,
implémente des quantificateurs existentiels, et plus encore.

[URL
[URL 18]
18] Nana
Nana :: journalisation
journalisation et
et assertions
assertions pour
pour C
C et
et C++
C++

www.cs.ntu.edu.au/homepages/pjm/nana-home/index.html

Prise en charge améliorée de la vérification des assertions et de la journalisation en C et C++. Ça aussi


fournit un support pour la conception par contrat.

[URL
[URL 19]
19] DDD–Débogueur
DDD–Débogueur d'affichage
d'affichage de
de données
données
www.cs.tu-bs.de/softech/ddd

Une interface graphique gratuite pour les débogueurs Unix.

[URL
[URL 20]
20] Navigateur
Navigateur de
de refactorisation
refactorisation de
de John
John Brant
Brant

st-www.cs.uiuc.edu/users/brant/Refactory

Un navigateur de refactorisation populaire pour Smalltalk.

[URL
[URL 21
21 ]] Générateur
Générateur de
de documentation
documentation DOC++
DOC++

www.zib.de/Visual/software/doc++/index.html

DOC++ est un système de documentation pour C/C++ et Java qui génère à la fois

et sortie HTML pour une navigation en ligne sophistiquée de votre


documentation directement à partir de l'en-tête C++ ou de la classe Java vole.

[URL
[URL 22]
22] Cadre
Cadre de
de test
test xUnit–Unit
xUnit–Unit

www.XProgranming.com

Un concept simple mais puissant, le cadre de test unitaire xUnit fournit un


plate-forme cohérente pour tester des logiciels écrits dans une variété de langues.

[URL
[URL 23]
23] Le
Le langage
langage Tcl
Tcl

www.scriptics.com

Tcl ("Tool Command Language") est un langage de script conçu pour être facile
à intégrer dans une application.

[URL
[URL 24]
24] Attendre—Automatiser
Attendre—Automatiser l'interaction
l'interaction avec
avec les
les programmes
programmes

expect.nist.gov

Une extension basée sur Tcl [ URL 23 ], expect vous permet de scripter l'interaction
avec des programmes. En plus de vous aider à écrire des mouches de commande (pour
exemple) récupérer des fichiers sur des serveurs distants ou étendre la puissance de votre shell,
expect peut être utile lors de l'exécution de tests de régression. Un graphique

version, expectk, vous permet d'envelopper des applications non graphiques avec un fenêtrage
l'extrémité avant.

[URL
[URL 25]
25] Espaces
Espaces TT

www.almaden.ibm.com/cs/TSpaces

De leur page Web : "T Spaces est un tampon de communication réseau avec
capacités de la base de données. Il permet la communication entre les applications et
périphériques dans un réseau d'ordinateurs et de systèmes d'exploitation hétérogènes. J
Spaces fournit des services de communication de groupe, des services de base de données,
Services de transfert de fichiers basés sur URL et services de notification d'événements."

[[ ]]
[URL
[URL 26]
26] javaCC—Compilateur-compilateur
javaCC—Compilateur-compilateur Java
Java
www.metamata.com/javacc

Un générateur d'analyseur étroitement couplé au langage Java.

[URL
[URL 27]
27] Le
Le générateur
générateur d'analyseur
d'analyseur bison
bison

www.gnu.org/software/bison/bison.html

bison prend une spécification de grammaire d'entrée et génère à partir de celle-ci le C


code source d'un parseur approprié.

[URL
[URL 28]
28] SWIG
SWIG :: wrapper
wrapper simplifié
simplifié et
et générateur
générateur d'interface
d'interface

www.swig.org

SWIG est un outil de développement logiciel qui connecte des programmes écrits en C,
C++ et Objective-C avec une variété de langages de programmation de haut niveau
tels que Perl, Python et Tcl/Tk, ainsi que Java, Eiffel et Guile.

[URL
[URL 29]
29] Le
Le groupe
groupe de
de gestion
gestion d'objets,
d'objets, Inc.
Inc.

www.omg.org

L'OMG est le garant de diverses spécifications pour la production distribuée


systèmes à base d'objets. Leur travail comprend la demande d'objet commun
Broker Architecture (CORBA) et le protocole Internet Inter-ORB (IIOP).

Combinées, ces spécifications permettent aux objets de communiquer


les uns avec les autres, même s'ils sont écrits dans des langues différentes et exécutés sur
différents types d'ordinateurs.

Outils
Outils Unix
Unix sous
sous DOS
DOS

[URL
[URL 30]
30] Les
Les outils
outils de
de développement
développement UWIN
UWIN

www.gtlinc.com/Products/Uwin/uwin.html

Global Technologies, Inc., Old Bridge, NJ

Le package UWIN fournit des bibliothèques de liens dynamiques Windows (DLL) qui
émuler une grande partie de l'interface de la bibliothèque de niveau Unix C. En utilisant ceci
interface, GTL a porté un grand nombre d'outils de ligne de commande Unix vers
Les fenêtres. Voir aussi [ URL 31 ].

[URL
[URL 31
31 ]] Les
Les outils
outils Cygnus
Cygnus Cygwin
Cygwin

sourceware.cygnus.com/cygwin/

Cygnus Solutions, Sunnyvale, Californie

Le package Cygnus émule également l'interface de la bibliothèque Unix C, et


fournit un large éventail d'outils de ligne de commande Unix sous Windows
système opérateur.

[URL
[URL 32]
32] Outils
Outils électriques
électriques Perl
Perl

www.perl.com/pub/language/ppt/

Un projet pour réimplémenter le jeu de commandes Unix classique en Perl, rendant le


commandes disponibles sur toutes les plates-formes qui supportent Perl (et c'est beaucoup de
plateformes).

Outils
Outils de
de contrôle
contrôle du
du code
code source
source

[URL
[URL 33]
33] RCS—Système
RCS—Système de
de contrôle
contrôle de
de révision
révision

prep.ai.mit.edu

Système de contrôle de code source GNU pour Unix et Windows NT.

[URL
[URL 34]
34] CVS—Système
CVS—Système de
de versions
versions simultanées
simultanées

www.cvshome.com

Système de contrôle de code source disponible gratuitement pour Unix et Windows NT.
Étend RCS en prenant en charge un modèle client-serveur et un accès simultané à
des dossiers.

[URL
[URL 35]
35] Gestion
Gestion de
de la
la configuration
configuration basée
basée sur
sur les
les transactions
transactions Aegis
Aegis

http://www.canb.auug.org.au/~millerp/aegis.html

Un outil de contrôle de révision orienté processus qui impose des normes de projet
(par exemple, vérifier que le code enregistré réussit les tests).

[URL
[URL 36]
36] ClearCase
ClearCase

www.rational.com

Contrôle de version, gestion de l'espace de travail et de la construction, contrôle des processus.

[URL
[URL 37]
37] Intégrité
Intégrité de
de la
la source
source MKS
MKS

www.mks.com

Contrôle de version et gestion de configuration. Certaines versions intègrent


fonctionnalités permettant aux développeurs distants de travailler sur les mêmes fichiers
simultanément (un peu comme CVS).

[URL
[URL 38]
38] Gestion
Gestion de
de la
la configuration
configuration PVCS
PVCS

www.merant.com

Un système de contrôle de code source, très populaire pour les systèmes Windows.

[URL
[URL 39]
39] Visual
Visual SourceSafe
SourceSafe

www.microsoft.com

Un système de contrôle de version qui s'intègre au visuel de Microsoft


outils de développement.
[URL
[URL 40]
40] Forcément
Forcément

www.perforce.com

Un système de gestion de configuration logicielle client-serveur.

Autres
Autres outils
outils

[URL
[URL 41]
41] WinZip—Utilitaire
WinZip—Utilitaire d'archivage
d'archivage pour
pour Windows
Windows

www.winzip.com

Nico Mak Computing, Inc., Mansfield, Connecticut

Un utilitaire d'archivage de fichiers basé sur Windows. Prend en charge les formats zip et tar.

[URL
[URL 42]
42] Le
Le shell
shell ZZ

sunsite.auc.dk/zsh

Un shell conçu pour une utilisation interactive, même s'il s'agit également d'un script puissant
langue. De nombreuses fonctionnalités utiles de bash, ksh et tcsh ont été
incorporé dans zsh ; de nombreuses caractéristiques originales ont été ajoutées.

[URL
[URL 43]
43] Un
Un client
client SMB
SMB gratuit
gratuit pour
pour les
les systèmes
systèmes Unix
Unix

samba.anu.edu.au/pub/samba/

Samba vous permet de partager des fichiers et d'autres ressources entre Unix et Windows
systèmes. Samba comprend :

• • Un serveur SMB, pour fournir Windows NT et LAN


Services de fichiers et d'impression de style gestionnaire pour les clients PME tels que
Windows 95, Warp Server, smbfs et autres.
• • Un serveur de noms Netbios, qui donne entre autres
prise en charge de la navigation. Samba peut être le navigateur principal de votre
LAN si vous le souhaitez.

• • Un client SMB de type ftp qui vous permet d'accéder au PC


ressources (disques et imprimantes) d'Unix, Netware et autres
systèmes d'exploitation.

Articles
Articles et
et publications
publications

[URL
[URL 44]
44] La
La FAQ
FAQ comp.object
comp.object

www.cyberdyne-object-sys.com/oofaq2

Une FAQ substantielle et bien organisée pour groupe de discussion comp.object.

[URL
[URL 45]
45] Programmation
Programmation extrême
extrême

www.XProgramming.com

Extrait du site Web : "Dans XP, nous utilisons une combinaison très légère de
pratiques pour créer une équipe capable de produire rapidement des produits extrêmement fiables,
logiciel efficace et bien factorisé. De nombreuses pratiques XP ont été créées et
testé dans le cadre du projet Chrysler C3, qui est une paie très réussie
système implémenté dans Smalltalk."
[URL
[URL 46]
46] Page
Page d'accueil
d'accueil d'Alistair
d'Alistair Cockburn
Cockburn

membres.aol.com/acockburn

Recherchez "Structurer les cas d'utilisation avec des objectifs" et utilisez des modèles de cas.

[URL
[URL 47]
47] Page
Page d'accueil
d'accueil de
de Martin
Martin Fowler
Fowler

ourworld.CompuServe.com/homepages/martin_fowler

Auteur de Analysis Patterns et co-auteur de UML Distilled and


Refactoring : amélioration de la conception du code existant. La maison de Martin Fowler
page discute de ses livres et de son travail avec l'UML.

[URL
[URL 48]
48] Page
Page d'accueil
d'accueil de
de Robert
Robert C.
C. Martin
Martin

www.objectmentor.com

Bons articles d'introduction sur les techniques orientées objet, y compris


analyse de dépendance et métriques.

[URL
[URL 49]
49] Programmation
Programmation orientée
orientée aspect
aspect

www.pare.xerox.com/csl/projects/aop/

Une approche pour ajouter des fonctionnalités au code, à la fois orthogonalement et


déclarativement.

[URL
[URL 50]
50] Spécification
Spécification JavaSpaces
JavaSpaces

java.sun.com/products/javaspaces

Un système de type Linda pour Java qui prend en charge la persistance distribuée et
algorithmes distribués.

[URL
[URL 51]
51] Code
Code source
source Netscape
Netscape

www.mozilla.org

La source de développement du navigateur Netscape.

[URL
[URL 52]
52] Le
Le fichier
fichier Jargon
Jargon

www.jargon.org

Eric S.Raymond

Définitions pour de nombreuses industries informatiques courantes (et moins courantes)


termes, avec une bonne dose de folklore.

[URL
[URL 53]
53] Papiers
Papiers d'Eric
d'Eric S.
S. Raymond
Raymond

www.tuxedo.org/~esr

Les articles d'Eric sur La cathédrale et le bazar et Homesteading the


Noo-sphère décrivant la base psychosociétale et les implications de la
Mouvement Open Source.
[URL
[URL 54]
54] L'environnement
L'environnement de
de bureau
bureau K
K

www.kde.org

De leur page Web : "KDE est un puissant environnement de bureau graphique


pour les postes de travail Unix. KDE est un projet Internet et vraiment ouvert dans tous
sens."

[URL
[URL 55]
55] Le
Le programme
programme de
de manipulation
manipulation d'images
d'images GNU
GNU

gimp.org

Gimp est un programme librement distribué utilisé pour la création d'images, la composition,
et retouche.

[URL
[URL 56]
56] Le
Le projet
projet Demeter
Demeter

www.ccs.neu.edu/research/demeter

Recherche visant à faciliter la maintenance et l'évolution des logiciels en utilisant


Programmation adaptative.

Divers
Divers

[URL
[URL 57]
57] Le
Le projet
projet GNU
GNU

www.gnu.org

Fondation du logiciel libre, Boston, MA

La Free Software Foundation est une organisation caritative exonérée d'impôt qui collecte des fonds pour
le projet GNU. L'objectif du projet GNU est de produire une version complète, libre et
Système de type Unix. Bon nombre des outils qu'ils ont développés en cours de route ont
deviennent des standards de l'industrie.

[URL
[URL 58]
58] Informations
Informations sur
sur le
le serveur
serveur Web
Web

www.netcraft.com/survey/servers.html

Liens vers les pages d'accueil de plus de 50 serveurs Web différents. Certains sont
produits commerciaux, tandis que d'autres sont disponibles gratuitement.
Bibliographie
Bibliographie

[Bak72] FT Baker. Programmeur en chef équipe gestion de la production


la programmation. IBM Systems Journal, ll(l):56–73, 1972.

[Bbm96] V. Basili, L. Briand et WL Melo. Une validation de


métriques de conception orientée objet comme indicateurs de qualité. Transactions IEEE sur
Génie logiciel, 22(10):751–761, octobre 1996.

[Ber96] Albert J. Bernstein. Cerveau de dinosaure : faire face à tous ceux-là


Les personnes impossibles au travail. Ballantine Books, New York, NY, 1996.

[Bra95] Cerveau Marshall. Services système Win32. Prentice Hall, Englewood


Falaises, New Jersey, 1995.

[Bro95] Frederick P. Brooks Jr. Le mois de l'homme mythique : essais sur


Génie logiciel. Addison-Wesley, Reading, MA, édition anniversaire,
1995.

[CG90] N. Carriero et D. Gelenter. Comment écrire des programmes parallèles : A


Premier cours. MIT Press, Cambridge, MA, 1990.

[CN91] Brad J. Cox et Andrex J. Novobilski. Orienté objet


Programmation, une approche évolutive. Addison-Wesley, Reading, MA,
1991.

[Coc97a] Alistair Cockburn. Objectifs et cas d'utilisation. Journal d'objet


Programmation orientée, 9(7):35–40, septembre 1997.

[Coc97b] Alistair Cockburn. Projets orientés objet survivants : A


Guide du gestionnaire. Addison Wesley Longman, Reading, MA, 1997.

[Cop92] James O. Coplien. Styles et idiomes de programmation C++ avancés.


Addison-Wesley, Reading, MA, 1992.
[DL99] Tom Demarco et Timothy Lister. Peopleware : projets productifs
et les équipes. Dorset House, New York, NY, deuxième édition, 1999..

[FBB + 99] Martin Fowler, Kent Beck, John Brant, William Opdyke et Don
Roberts. Refactoring : amélioration de la conception du code existant. Addison
Wesley Longman, Reading, MA, 1999.

[Fow96] Martin Fowler. Modèles d'analyse : modèles d'objets réutilisables.


Addison Wesley Longman, Reading, MA, 1996.

[FS97] Martin Fowler et Kendall Scott. UML Distillé : Application de la


Langage standard de modélisation d'objets. Addison Wesley Longman, lecture,
MA, 1997.

[GHJV95] Erich Gamma, Richard Helm, Ralph Johnson et John Vlissides.


Modèles de conception : éléments de logiciels réutilisables orientés objet.
Addison-Wesley, Reading, MA, 1995.

[Gla99a] Robert L. Verre. Inspections—Quelques découvertes surprenantes.


Communications de l'ACM, 42(4): 17–19, avril 1999.

[Gla99b] Robert L. Verre. Les réalités des avantages de la technologie logicielle.


Communications de l'ACM, 42(2):74–79, février 1999.

[Hol78] Michael Holt. Puzzles et jeux mathématiques. Dorset Press, New York,
NY, 1978.

[Jac94] Ivar Jacobson. Ingénierie logicielle orientée objet : un cas d'utilisation


Approche pilotée. Addison-Wesley, Reading, MA, 1994.

[KLM + 97] Gregor Kiczales, John Lamping, Anurag Mendhekar, Chris


Maeda, Cristina Videira Lopes, Jean-Marc Loingtier et John Irwin.
Programmation orientée aspect. In Conférence européenne sur l'orientation objet
Programmation (ECOOP), volume LNCS 1241. Springer-Verlag, juin 1997.

[Knu97a] Donald Ervin Knuth. L'art de la programmation informatique :


Algorithmes fondamentaux, volume 1. Addison Wesley Longman, Reading,
MA, troisième édition, 1997.

[Knu97b] Donald Ervin Knuth. L'art de la programmation informatique :


Algorithmes semi-numériques, volume 2. Addison Wesley Longman, Reading,
MA, troisième édition, 1997.

[Knu98] Donald Ervin Knuth. L'art de la programmation informatique : trier


and Searching, volume 3. Addison Wesley Longman, Reading, MA, deuxième
édition, 1998.

[KP99] Brian W. Kernighan et Rob Pike. La pratique de la programmation.


Addison Wesley Longman, Reading, MA, 1999.

[Kru98] Philippe Kruchten. Le processus unifié rationnel : une introduction.


Addison Wesley Longman, Reading, MA, 1998.

[Lak96] John Lakos. Conception de logiciels C++ à grande échelle. Addison Wesley
Longman, Reading, MA, 1996.
[LH89] Karl J. Lieberherr et Ian Holland. Assurer un bon style pour
programmes orientés objet. Logiciel IEEE, pages 38–48, septembre 1989.

[Lis88] Barbara Liskov. Abstraction et hiérarchie des données. Avis SIGPLAN,


23(5), mai 1988.

[LMB92] John R. Levine, Tony Mason et Doug Brown. Lex et Yacc.


O'Reilly & Associates, Inc., Sébastopol, Californie, deuxième édition, 1992.

[McC95] Jim McCarthy. Dynamique du développement logiciel. Microsoft


Press, Redmond, WA, 1995.

[Mey96] Scott Meyers. C++ plus efficace : 35 nouvelles façons d'améliorer votre
Programmes et conceptions. Addison-Wesley, Reading, MA, 1996.

[Mey97a] Scott Meyers. C++ efficace : 50 façons spécifiques d'améliorer votre


Programmes et conceptions. Addison Wesley Longman, Reading, MA, deuxième
édition, 1997.

[Mey97b] Bertrand Meyer. Construction logicielle orientée objet.


Prentice Hall, Englewood Cliffs, NJ, deuxième édition, 1997.

[Pet98] Charles Petzold. Programmation de Windows, le guide définitif de


l'API Win32. Microsoft Press, Redmond, WA, cinquième édition, 1998.

[Sch95] Bruce Schneier. Cryptographie appliquée : protocoles, algorithmes et


Code source dans C. John Wiley & Sons, New York, NY, deuxième édition, 1995.

[Sed83] Robert Sedgewick. Algorithmes. Addison-Wesley, Reading, MA,


1983.

[Sed92] Robert Sedgewick. Algorithmes en C++. Addison-Wesley, Reading,


MA, 1992.

[SF96] Robert Sedgewick et Philippe Flajolet. Une introduction à la


Analyse d'algorithmes. Addison-Wesley, Reading, MA, 1996.

[Ste92] W. Richard Stevens. Programmation avancée sous Unix


Environnement. Addison-Wesley, Reading, MA, 1992.

[Ste98] W. Richard Stevens. Programmation réseau Unix, volume 1 :


API de mise en réseau : Sockets et Xti. Prentice Hall, falaises d'Englewood, NJ,
deuxième édition, 1998.

[Ste99] W. Richard Stevens. Programmation réseau Unix, volume 2 :


Communications interprocessus. Prentice Hall, Englewood Cliffs, NJ, deuxième
édition, 1999.

[Str35] James Ridley Stroop. Études des interférences dans les séries verbales
réactions. Journal de psychologie expérimentale, 18: 643–662, 1935.

[WK82] James Q. Wilson et George Kelling. La police et le quartier


sécurité. The Atlantic Monthly, 249(3):29–38, mars 1982.

[YC86] Edward Yourdon et Larry L. Constantine. Conception structurée :


Principes fondamentaux d'une discipline de conception de programmes et de systèmes informatiques.
Prentice Hall, Englewood Cliffs, NJ, deuxième édition, 1986.

[Vous95] Edward Yourdon. Gérer des projets pour produire assez bien
logiciel. Logiciel IEEE, mars 1995.
Annexe B. Réponses aux exercices

Exercer de l'orthogonalité
Exercer
1:
1:
Vous écrivez une classe appelée Split, qui divise les lignes d'entrée en
des champs. Laquelle des deux signatures de classe Java suivantes est la
c

Répondre
RépondreA notre façon de penser, la classe Split2 est plus orthogonal. Il
1:
1: se concentre sur sa propre tâche, divise les lignes et ignore les détails
comme d'où viennent les lignes. Non seulement cela
rendre le code plus facile à développer, mais cela le rend également plus
flexible. Split2 peut diviser les lignes lues à partir d'un fichier, généré par
une autre routine, ou transmis via l'environnement .

Exercer de l'orthogonalité
Exercer
22 ::
Ce qui conduira à une conception plus orthogonale : non modale ou modale
Boîtes de dialogue?

Répondre
RépondreSi c'est fait correctement, probablement sans mode. Un système qui utilise
22 :: les boîtes de dialogue non modales seront moins concernées par ce qui se passe
à un moment donné dans le temps. Il aura probablement un meilleur
infrastructure de communications intermodules qu'une infrastructure modale
système, qui peut avoir des hypothèses intégrées sur l'état de
le système - hypothèses qui conduisent à un couplage accru et
diminution de l'orthogonalité.
Exercer
Exercer de l'orthogonalité
33 ::
Qu'en est-il des langages procéduraux par rapport à la technologie objet ?

Qu'est-ce qui donne un système plus orthogonal ?

RépondreC'est un peu délicat. La technologie objet peut fournir un plus


Répondre
33 :: système orthogonal, mais parce qu'il a plus de fonctionnalités à abuser, il
est en fait plus facile de créer un système non orthogonal à l'aide d'objets
qu'il utilise un langage procédural. Des fonctionnalités telles que
héritage multiple, exceptions, surcharge d'opérateurs et
le remplacement de la méthode parent (via le sous-classement) fournit amplement
possibilité d'augmenter le couplage de manière non évidente.

Avec la technologie objet et un petit effort supplémentaire, vous pouvez obtenir un


système beaucoup plus orthogonal. Mais alors que vous pouvez toujours écrire
"code spaghetti" dans un langage procédural, orienté objet
les langues mal utilisées peuvent ajouter des boulettes de viande à vos spaghettis.

Exercer à partir de prototypes et de post-it


Exercer
44 ::
Le marketing aimerait s'asseoir et réfléchir à quelques
Conceptions de pages Web avec vous. Ils pensent au cliquable
des images cliquables pour vous emmener vers d'autres pages, et ainsi de suite. Mais ils ne peuvent pas
décider d'un modèle pour l'image - peut-être une voiture, ou un téléphone, ou
une maison. Vous disposez d'une liste de pages cibles et de contenu ; ils aimeraient
pour voir quelques prototypes. Oh, au fait, vous avez 15 minutes.
Quels outils pourriez-vous utiliser ?

Répondre
RépondreLa low-tech à la rescousse ! Dessinez quelques caricatures avec des marqueurs sur un
44 :: tableau blanc : une voiture, un téléphone et une maison. Cela ne doit pas être
grand art; les contours en forme de bâton sont bons. Mettez des Post-it qui
décrire le contenu des pages cibles sur les zones cliquables. Comme
la réunion avance, vous pouvez affiner les dessins et
placement des Post-it .

Exercer
Exercer à partir des langues du domaine
55 ::
Nous voulons implémenter un mini-langage pour contrôler un simple
package de dessin (peut-être un système de graphiques de tortues). Le
le langage se compose de commandes à une seule lettre. Quelques commandes
sont suivis d'un seul chiffre. Par exemple, ce qui suit
'l e

W 2 # t
Implémentez le code qui parse ce langage. Ça devrait être
conçu pour qu'il soit simple d'ajouter de nouvelles commandes.

Répondre
RépondreParce que nous voulons rendre le langage extensible, nous allons faire
55 :: la table d'analyseur pilotée. Chaque entrée du tableau contient les
lettre de commande, un drapeau pour dire si un argument est requis,
et le nom de la routine à appeler pour gérer ce particulier
c

Le programme principal est assez simple : lire une ligne, rechercher le


commande, obtenez l'argument si nécessaire, puis appelez le gestionnaire
of

La fonction qui recherche une commande effectue une recherche linéaire de


la table, renvoyant soit l'entrée correspondante, UN soit

,Enfi

Exercer
Exercer à partir des langues du domaine
66 ::
Concevoir une grammaire BNF pour analyser une spécification temporelle. La totalité de la
el
Répondre
RépondreEn utilisant BNF, une spécification de temps pourrait être
66 ::

<eh

<a
<eh

<umin

<c

Exercer à partir des langues du domaine


Exercer
7:
7:
Implémentez un parseur pour la grammaire BNF dans l'exercice 6 en utilisant
yacc, bison ou un analyseur-générateur similaire.

RépondreoN
Répondre
7:
7: Pour plus de clarté, nous ne montrons ici que le corps de l'analyseur. Regarder
à al
; un

Exercer à partir des langues du domaine


Exercer
88 ::
Implémentez l'analyseur de temps en utilisant Perl. [Astuce : Régulier
les expressions font de bons analyseurs.]

Répondre
Répondre
8 :

Exercer
Exercer de l'estimation
99 ::
On vous demande "Qui a une bande passante plus élevée : un 1Mbps
ligne de communication ou une personne marchant entre deux
ordinateurs avec une bande complète de 4 Go dans leur poche ? »
mettrez-vous des contraintes sur votre réponse pour vous assurer que la portée
de votre réponse est-elle correcte ? (Par exemple, vous pourriez dire que le
le temps nécessaire pour accéder à la bande est ignoré.)

Répondre
RépondreNotre réponse doit reposer sur plusieurs hypothèses :
99 ::
• La bande contient les informations dont nous avons besoin pour être
transféré.
• Nous connaissons la vitesse à laquelle la personne marche.
• Nous connaissons la distance entre les machines.

• Nous ne tenons pas compte du temps qu'il faut pour transférer


informations vers et depuis la bande.
• La surcharge de stockage des données sur une bande est à peu près égale à
le surcoût de l'envoyer sur une ligne de communication.

Exercer
Exercer de l'estimation
dix:
dix:
Alors, qui a la bande passante la plus élevée ?

Répondre
RépondreSous réserve des mises en garde de la réponse 9 : Une bande de 49 Go contient 32 × 10
dix:
dix: bits, donc une ligne 1Mbps devrait pomper des données pour environ 32 000
secondes, soit environ 9 heures, pour transférer le montant équivalent
d'information. Si la personne marche à une vitesse constante de 3½ mph,
alors nos deux machines devraient être distantes d'au moins 31 miles
pour que la ligne de communication surpasse notre service de messagerie.
Sinon, la personne gagne.

Exercer
Exercer de la manipulation de texte
11
11 ::
Votre programme C utilise un type énuméré pour représenter l'un des
100 états. Vous aimeriez pouvoir imprimer l'état sous forme de chaîne
(par opposition à un nombre) à des fins de débogage. Écrire un scénario
q

oPr

et le nom du fichier.c, qui contient

RépondreoN
Répondre
11
11 ::

*/
*/

En utilisant le principe DRY, nous n'allons pas couper et coller ce nouveau fichier dans
notre code. Au lieu de cela, nous l'inclurons : le fichier plat est la source principale
de ces constantes. Cela signifie que nous aurons besoin d'un makefile pour
régénérer l'en-tête lorsque le fichier change. L'extrait suivant
p

Exercer
Exercer de la manipulation de texte
12
12 ::
A mi-chemin de l'écriture de ce livre, nous avons réalisé que nous n'avions pas
mettre la directive use strict dans beaucoup de nos exemples Perl.
Rédigez un script qui passe par le fichiers .pl dans un répertoire et
ajoute un
utiliser strict à la fin du bloc de commentaire initial pour tous
fichiers qui n'en ont pas déjà un. N'oubliez pas de conserver une sauvegarde de
tous les fichiers que vous modifiez.

RépondreVoici notre réponse, écrite en Perl .


Répondre
12
12 ::

Exercer des générateurs de code


Exercer
13:
13:

Écrivez un générateur de code qui prend le fichier d'entrée de la figure 3.4 ,


et génère une sortie dans deux langues de votre choix. Essayez de
faciliter l'ajout de nouvelles langues.
Répondre
RépondreNous utilisons Perl pour implémenter notre solution. Il charge dynamiquement un
13:
13: module pour générer la langue demandée, ajoutant ainsi de nouvelles
langues est facile. La routine principale charge le back-end (basé
sur un paramètre de ligne de commande), puis lit son entrée et appelle
routines de génération de code basées sur le contenu de chaque ligne. Étaient
pas particulièrement pointilleux sur la gestion des erreurs - nous apprendrons à connaître
a

Écrire un back-end de langage est simple : fournissez un module qui


em

tE
Exercer
Exercer de la conception par contrat
14:
14:
Qu'est-ce qui fait un bon contrat ? N'importe qui peut ajouter des conditions préalables et
postconditions, mais vous seront-elles utiles ? Pire encore, sera
ils font en fait plus de mal que de bien? Pour l'exemple ci-dessous
et pour ceux des Exercices 15 et 16, décidez si le
contrat spécifié est bon, mauvais ou laid, et expliquez pourquoi.

Prenons d'abord un exemple Eiffel. Ici, nous avons une routine pour
ajouter une chaîne à une liste circulaire doublement liée (rappelez-vous que
les préconditions sont étiquetées avec require et les postconditions avec

ég

Répondre
Répondre Cet exemple Eiffel est bon. Nous exigeons que les données non nulles soient
14:
14: passé, et nous garantissons que la sémantique d'une circulaire,
liste doublement liée sont honorés. Cela aide aussi à pouvoir trouver le
chaîne que nous avons stockée. Puisqu'il s'agit d'une classe différée, le véritable
la classe qui l'implémente est libre d'utiliser tout sous-jacent
mécanisme qu'il veut. Il peut choisir d'utiliser des pointeurs ou un
tableau, ou autre chose ; tant qu'il respecte le contrat, nous ne
se soucier .

Exercer de la conception par contrat


Exercer
15:
15:
Essayons ensuite un exemple en Java, un peu similaire au
exemple dans l'exercice 14. insertNumber insère un entier dans un
liste ordonnée. Les conditions préalables et postérieures sont étiquetées comme dans iContract
(voir [ URL 17 ])
Répondre
Répondre C'est mauvais. Le calcul dans la clause d'index ( index-1 ) ne fonctionnera pas
15:
15: sur les conditions aux limites telles que la première entrée .

La postcondition suppose une implémentation particulière : nous


veulent que les contrats soient plus abstraits que cela.

Exercer
Exercer de la conception par contrat
16:
16:
Voici un fragment d'une classe de pile en Java. Est-ce un bon
c

Répondre
Répondre C'est un bon contrat, mais une mauvaise mise en œuvre. Ici le
16:
16: l'infâme "Heisenbug" [URL 52 ] dresse sa vilaine tête. Le
le programmeur vient probablement de faire une simplepop aufaute
lieu de frappe—
haut. Bien qu'il s'agisse d'un exemple simple et artificiel, les effets secondaires dans
les assertions (ou à n'importe quel endroit inattendu dans le code) peuvent être très
difficile à diagnostiquer.

Exercer
Exercer de la conception par contrat
17:
17:
Les exemples classiques de DEC (comme dans les exercices 14 à 16) montrent une
mise en œuvre d'un ADT (Abstract Data Type) - généralement un
pile ou file d'attente. Mais peu de gens écrivent vraiment ce genre de
classes de bas niveau.

Donc, pour cet exercice, concevez une interface vers un mixeur de cuisine. Il
sera éventuellement un système basé sur le Web, compatible avec Internet et basé sur CORBA
blender, mais pour l'instant nous avons juste besoin de l'interface pour le contrôler. Il
a dix réglages de vitesse (0 signifie éteint). Vous ne pouvez pas le faire fonctionner à vide,
et vous ne pouvez modifier la vitesse que d'une unité à la fois (c'est-à-dire
de 0 à 1, et de 1 à 2, et non de 0 à 2).

Voici les méthodes. Ajouter des conditions préalables et postérieures appropriées


et un invariant.

tin

Répondre
Répondre Nous allons montrer les signatures de fonction en Java, avec les pré- et
17:
17: postconditions étiquetées comme dans iContract .

oT
sEn

Exercer de la conception par contrat


Exercer
18:
18:
Combien y a-t-il de nombres dans la série 0,5,10,15,…, 100 ?

Répondre
Répondre Il y a 21 termes dans la série. Si vous avez dit 20, vous venez de
18:
18: a rencontré une erreur de clôture .

Exercer de la Programmation Assertive


Exercer
19:
19:
Une rapide vérification de la réalité. Laquelle de ces choses "impossibles" peut
arriver?

1. Un mois de moins de 28 jours


2. stat("." ,&sb) == -1 (c'est-à-dire, impossible d'accéder au
annuaire)
3. DansC
4. Un triangle dont la somme des angles intérieurs ? 180°
5. Une minute qui n'a pas 60 secondes
6

Répondre
Répondre Le 1er septembre 1752 n'avait que 19 jours. Cela a été fait pour
19:
19: synchroniser les calendriers dans le cadre du grégorien
Réformation.
2. Le répertoire a peut-être été supprimé par un autre
processus, vous n'êtes peut-être pas autorisé à le lire, &sb
peut être invalide - vous obtenez l'image.
3. Nous n'avons pas précisé les types de a et b. Opérateur
la surcharge aurait pu définir +, = ou ! = avoir
comportement inattendu. De plus, a et b peuvent être des alias pour le
même variable, donc la deuxième affectation écrasera
la valeur stockée dans le premier.
4. En géométrie non euclidienne, la somme des angles d'un
triangle ne totalisera
cartographié pas 180°.
sur la surface Pensez
d'une à un triangle
sphère.
5. Les minutes intercalaires peuvent avoir 61 ou 62 secondes.
6. Le débordement peut laisser le résultat
a + 1denégatif (cela peut
se produisent également en C et C++).

Exercer de la Programmation Assertive


Exercer
20:
20:
Développer une classe de vérification d'assertion simple pour Java.

Répondre
RépondreNous avons choisi d'implémenter une classe très simple avec un seul statique
20:
20: méthode, TEST, qui imprime un message et une trace de pile si le
el

Exercer
Exercer à partir de Quand utiliser les exceptions
21:
21:
Lors de la conception d'une nouvelle classe de conteneur, vous identifiez les
conditions d'erreur possibles suivantes :

1. Pas de mémoire disponible pour un nouvel élément dans la routine d'ajout


2. L'entrée demandée n'a pas été trouvée dans la routine de récupération
3. pointeur nul passé à la routine d'ajout

Comment chacun doit-il être manipulé ? Si une erreur est générée,


si une exception devait être soulevée, ou si la condition devait être
ignoré ?

Répondre
RépondreLe manque de mémoire est une condition exceptionnelle, nous nous sentons donc
21:
21: ce cas (1) devrait soulever une exception .

L'impossibilité de trouver une entrée est probablement tout à fait normale.


L'application qui appelle notre classe de collection peut très bien écrire
code qui vérifie si une entrée est présente avant d'ajouter un
doublon potentiel. Nous pensons que le cas (2) devrait simplement renvoyer un
erreur.

Le cas (3) est plus problématique—si la valeur null est significative pour
la demande, alors il peut être à juste titre ajouté à la
récipient. Si, toutefois, cela n'a aucun sens de stocker des valeurs nulles, un
exception devrait probablement être levée.

Exercer
Exercer de Comment équilibrer les ressources
22:
22:
Certains développeurs C et C++ mettent un point d'honneur à définir un pointeur vers
NULL après avoir désalloué la mémoire à laquelle il fait référence. Pourquoi est-ce
une bonne idée?

Répondre
RépondreDans la plupart des implémentations C et C++, il n'y a aucun moyen de vérifier
22:
22: qu'un pointeur pointe réellement vers une mémoire valide. Un commun
l'erreur est de désallouer un bloc de mémoire et de référence qui
mémoire plus tard dans le programme. À ce moment-là, la mémoire indiquait
peut très bien avoir été réaffecté à une autre fin. Par
en définissant le pointeur sur NULL, les programmeurs espèrent empêcher
ces références malveillantes - dans la plupart des cas, déréférencer un NULL
le pointeur générera une erreur d'exécution.

Exercer
Exercer de Comment équilibrer les ressources
23:
23:
Certains développeurs Java mettent un point d'honneur à définir une variable objet
à NULL après avoir fini d'utiliser l'objet. Pourquoi est-ce un
bonne idée?

Répondre
RépondreEn définissant la référence sur NULL, vous réduisez le nombre de
23:
23: pointeurs vers l'objet référencé par un. Une fois que ce décompte atteint

zéro, l'objet est éligible pour la récupération de place. Réglage de la


les références à NULL peuvent être importantes pour les programmes de longue durée,
où les programmeurs doivent s'assurer que l'utilisation de la mémoire
n'augmente pas avec le temps.

Exercer du découplage et de la loi de Déméter


Exercer
24:
24:
Nous avons abordé le concept de découplage physique dans l'encadré.
Lequel des fichiers d'en-tête C++ suivants est le plus étroitement couplé
au reste du système ?

personne1.h
personne1.h :: personne2.h
personne2.h ::

#icn d
"d c
c p
p
p
p

/
Répondre
RépondreUn fichier d'en-tête est censé définir l'interface entre le
24:
24: mise en œuvre correspondante et le reste du monde. Le
le fichier d'en-tête lui-même n'a pas besoin de connaître les composants internes du
Classe de date - il suffit de dire au compilateur que la
Le constructeur prend une Date comme paramètre. Donc, à moins que l'en-tête
le fichier utilise des dates dans les fonctions en ligne, le deuxième extrait fonctionnera
bien .

Quel est le problème avec le premier extrait ? Sur un petit projet, rien,
sauf que vous faites inutilement tout ce qui utilise un
La classe Personl inclut également le fichier d'en-tête pour Date. Une fois ce genre
d'utilisation devient courant dans un projet, vous constaterez bientôt que l'inclusion
un fichier d'en-tête finit par inclure la plupart du reste du
système - un sérieux frein aux temps de compilation.

Exercer du découplage et de la loi de Déméter


Exercer
25
25 ::
Pour l'exemple ci-dessous et pour ceux des Exercices 26 et 27,
déterminer si les appels de méthode affichés sont autorisés en fonction de la
Loi de Déméter. Ce premier est en Java.

RépondreaL
Répondre
25
25 :: l'appel est autorisé. Cependant, l'appel de amt.printFormat() ne l'est pas. Nous
ne "possède" pas amt et il ne nous a pas été transmis. On pourrait éliminer
eL

Exercer du découplage et de la loi de Déméter


Exercer
26:
26:
C

ev

Répondre
RépondrePuisque Colada crée et possède à la fois myBlender et myStuff, le
26:
26: les appels à addIngredients et elements sont autorisés.

Exercer du découplage et de la loi de Déméter


Exercer
27:
27:
C
a

Répondre
RépondreDans ce cas, processTransaction possède amt — il est créé sur le
27:
27: pile, acct est passé, donc setValue et setBalance sont
autorisé. Mais processTransaction ne possède pas qui, donc l'appel
who->name() est en violation. La loi de Déméter suggère
e

Le code dans processTransaction ne devrait pas avoir à savoir quel


sous-objet dans unBankAccount détient le nom—cette structure
la connaissance ne doit pas apparaître dans le contrat de BankAccount.
Au lieu de cela, nous demandons au compte bancaire le nom sur le compte. Il
s
ou dans un objet Client polymorphe).

Exercer de la métaprogrammation
Exercer
28:
28:
Laquelle des choses suivantes serait mieux représentée comme
code dans un programme, et lequel en externe comme métadonnées ?

1. Affectations des ports de communication


2. Un support d'éditeur pour la mise en évidence de la syntaxe de divers
langues
3. Le support d'un éditeur pour différents périphériques graphiques
4. Une machine d'état pour un analyseur ou un scanner
5. Exemples de valeurs et de résultats à utiliser dans les tests unitaires

Répondre
RépondreIl n'y a pas de réponses définitives ici - les questions étaient
28:
28: destiné avant tout à vous donner matière à réflexion. Cependant, ceci est
ce que nous pensons :

1. Affectations des ports de communication. Clairement, cela


les informations doivent être stockées sous forme de métadonnées. Mais à quoi
niveau de détail? Certains programmes de communication Windows
vous permet de sélectionner uniquement le débit en bauds et le port (disons COM1 à COM4 ).
Mais peut-être avez-vous besoin de spécifier la taille du mot, la parité, l'arrêt
bits, ainsi que le paramètre duplex. Essayez de permettre le meilleur
niveau de détail lorsque cela est pratique.

2.
2. Un
Un support
support d'éditeur
d'éditeur pour
pour la
la mise
mise en
en évidence
évidence de
de la
la syntaxe
syntaxe de
de divers
divers
langues. Cela devrait être implémenté sous forme de métadonnées.
Vous ne voudriez pas avoir à pirater du code simplement parce que le
la dernière version de Java a introduit un nouveau mot-clé.
3. Le support d'un éditeur pour différents périphériques graphiques. Ce
serait probablement difficile à mettre en œuvre strictement
métadonnées. Vous ne voudriez pas alourdir votre candidature
avec plusieurs pilotes de périphériques uniquement pour en sélectionner un lors de l'exécution.
Vous
le pouvez
pilote cependant
et charger utiliser des le
dynamiquement métadonnées pour
code. Ceci est unspécifier
autre le nom de
bon argument pour conserver les métadonnées dans un
format lisible par l'homme ; si vous utilisez le programme pour configurer
un pilote vidéo dysfonctionnel, vous ne pourrez peut-être pas utiliser
le programme pour le remettre en place.
4. Une machine d'état pour un analyseur ou un analyseur. Cela dépend
sur ce que vous analysez ou scannez. Si vous analysez
certaines données définies de manière rigide par un organisme de normalisation et
est peu susceptible de changer sans un acte du Congrès, alors
codage dur c'est bien. Mais si vous êtes confronté à un plus
situation volatile, il peut être avantageux de définir l'état
tableaux en externe.
5. Exemples de valeurs et de résultats à utiliser dans les tests unitaires. La plupart
les applications définissent ces valeurs en ligne dans les tests
harnais, mais vous pouvez obtenir une meilleure flexibilité en déplaçant le
données de test—et la définition de la
résultats—hors du code lui-même.

Exercer
Exercer de C'est juste une vue
29:
29:
Supposons que vous disposiez d'un système de réservation de compagnie aérienne comprenant
el

Si vous ajoutez un passager à la liste d'attente, il sera mis sur le vol

automatiquement lorsqu'une place se libère.

Il y a un énorme travail de reportage qui passe par la recherche de


vols surréservés ou complets à suggérer lorsque des vols supplémentaires
pourrait être programmé. Cela fonctionne bien, mais cela prend des heures à fonctionner.

On aimerait avoir un peu plus de souplesse dans le traitement des listes d'attente
passagers, et nous devons faire quelque chose à propos de ce gros
rapport—il prend trop de temps à s'exécuter. Utilisez les idées de cette section
pour repenser cette interface.

Répondre
RépondreNous allonsVol
prendre
et ajouter quelques méthodes supplémentaires pour
29:
29: maintenir deux listes d'auditeurs : une pour la notification de la liste d'attente,
e
Si nous essayons d'ajouter un passager et échouons parce que le vol est complet, nous pouvons,
éventuellement, mettez
Passager
le sur liste d'attente. Lorsqu'une place se libère,
waitList-Available sera appelé. Cette méthode peut alors choisir de
ajouter le
Passager automatiquement ou avoir un représentant de service
appeler le client pour lui demander s'il est toujours intéressé, ou quoi que ce soit. Nous
ont maintenant la flexibilité d'effectuer différents comportements sur un
par client.

Ensuite, nous voulons éviter que BigReport ne parcoure des tonnes de


records à la recherche de vols complets. En enregistrant BigReport en tant que
auditeur sur les vols, chaque vol individuel peut signaler quand il est
plein ou presque plein, si nous voulons. Désormais, les utilisateurs peuvent être en direct,
rapports de dernière minute deBigReport instantanément, sans attendre

heures pour qu'il fonctionne comme avant.

Exercer des tableaux noirs


Exercer
30:
30:
Pour chacune des applications suivantes, un tableau noir
le système est-il approprié ou non ? Pourquoi?

1. Traitement d'images. Vous aimeriez avoir plusieurs


les processus parallèles saisissent des morceaux d'une image, les traitent,
et remettre le morceau terminé.
2. Calendrier de groupe. Vous avez des gens dispersés à travers
le globe, dans différents fuseaux horaires, et parlant différemment
langues, essayant de programmer une réunion.
3. Outil de surveillance du réseau. Le système rassemble
statistiques de performances et collecte des rapports de panne. Vous feriez
aimerions implémenter certains agents pour utiliser ces informations pour
chercher des problèmes dans le système.

Répondre
Répondre 1. Traitement d'images. Pour une planification simple d'une charge de travail
30:
30: parmi les processus parallèles, une file d'attente de travail partagée peut
être plus que suffisant. Vous voudrez peut-être envisager un
système de tableau noir s'il y a une rétroaction impliquée, c'est-à-dire,
si les résultats d'un morceau traité affectent d'autres morceaux,
comme dans les applications de vision industrielle ou la 3D complexe
transformations de distorsion d'image.
2. Calendrier de groupe. Cela pourrait être un bon ajustement. Tu peux
après les réunions planifiées et la disponibilité pour le
tableau noir. Vous avez des entités fonctionnant de manière autonome,
les commentaires sur les décisions sont importants et les participants
peuvent aller et venir.

Vous voudrez peut-être envisager de partitionner ce type de


système de tableau noir selon qui cherche : junior
le personnel peut ne se soucier que du bureau immédiat, humain
les ressources peuvent ne vouloir que des bureaux anglophones
dans le monde entier, et le PDG peut vouloir toute l'enchilada.
Il y a aussi une certaine flexibilité sur les formats de données : nous sommes libres
d'ignorer les formats ou les langues que nous ne comprenons pas. Nous
doivent comprendre différents formats uniquement pour ces bureaux
qui ont des réunions les uns avec les autres, et nous n'avons pas besoin
exposer tous les participants à une fermeture transitive complète de tous
formats possibles. Cela réduit le couplage là où il se trouve
nécessaire, et ne nous contraint pas artificiellement.

3. Outil de surveillance du réseau. Ceci est très similaire au


programme de demande d'hypothèque/de prêt décrit. Tu as
rapports de panne envoyés par les utilisateurs et statistiques signalées
automatiquement, tout affichage au tableau noir. Un humain ou
l'agent logiciel peut analyser le tableau noir pour diagnostiquer
pannes de réseau : deux erreurs sur une ligne peuvent être cosmiques
rayons, mais 20 000 erreurs et vous avez un matériel
problème. Tout comme les détectives résolvent le mystère du meurtre,
vous pouvez avoir plusieurs entités analysant et contribuant
idées pour résoudre les problèmes de réseau.

Exercer de la programmation par coïncidence


Exercer
31:
31:
Pouvez-vous identifier des coïncidences dans le code C suivant
fragment? Supposons que ce code est enfoui profondément dans une bibliothèque
or

Répondre
RépondreIl existe plusieurs problèmes potentiels avec ce code. D'abord, il
31:
31: suppose un environnement tty. Cela peut être bien si l'hypothèse
est vrai, mais que se passe-t-il si ce code est appelé à partir d'un environnement graphique
où ni stderr ni stdin n'est ouvert ?

Deuxièmement, il y a les get problématiques, qui écriront autant de


caractères tels qu'ils sont reçus dans le tampon transmis. Malicieux
les utilisateurs ont utilisé ce défaut pour créer une sécurité de dépassement de mémoire tampon
t

Troisièmement, le code suppose que l'utilisateur comprend l'anglais.

Enfin, personne de sensé n'enterrerait jamais l'utilisateur


interaction comme celle-ci dans une routine de bibliothèque.

Exercer de la programmation par coïncidence


Exercer
32:
32:
Ce morceau de code C peut fonctionner de temps en temps, sur certains
Machines. Là encore, ce n'est peut-être pas le cas. Qu'est-ce qui ne va pas?

Répondre
RépondrePOSIX strcpy n'est pas garanti de fonctionner pour les chaînes qui se chevauchent.
32:
32: Il peut arriver que cela fonctionne sur certaines architectures, mais uniquement en
hasard .

Exercer
Exercer de la programmation par coïncidence
33:
33:
Ce code provient d'une suite de traçage Java à usage général. Le
La fonction écrit une chaîne dans un fichier journal. Il réussit son test unitaire, mais
échoue lorsqu'un des développeurs Web l'utilise. Quelle coïncidence
s

Répondre
RépondreCela ne fonctionnera pas dans un contexte d'applet avec des restrictions de sécurité
33:
33: contre l'écriture sur le disque local. Encore une fois, quand vous avez le choix
de s'exécuter dans des contextes GUI ou non, vous voudrez peut-être vérifier
dynamiquement pour voir à quoi ressemble l'environnement actuel. Dans ce
cas, vous voudrez peut-être placer un fichier journal ailleurs que dans le
disque local s'il n'est pas accessible.

Exercer à partir de la vitesse de l'algorithme


Exercer
34:
34:
Nous avons codé un ensemble de routines de tri simples, qui peuvent être
téléchargé depuis notre site Web
(http://www.pragmaticprogrammer.com). Exécutez-les sur divers
machines à votre disposition. Vos chiffres suivent-ils les prévisions
courbes? Que pouvez-vous en déduire des vitesses relatives de votre
Machines? Quels sont les effets de diverses optimisations du compilateur
paramètres? Le tri par base est-il bien linéaire ?

Répondre
RépondreDe toute évidence, nous ne pouvons pas donner de réponses absolues à cet exercice.
34:
34: Cependant, nous pouvons vous donner quelques indications.

Si vous constatez que vos résultats ne suivent pas une courbe régulière, vous
voudriez peut-être vérifier si une autre activité utilise certains de
la puissance de votre processeur. Vous n'obtiendrez probablement pas de bons chiffres sur un
système multi-utilisateurs, et même si vous êtes le seul utilisateur que vous pouvez trouver
que les processus d'arrière-plan prennent périodiquement des cycles
vos programmes. Vous pouvez également vérifier la mémoire : si le
l'application commence à utiliser l'espace d'échange, les performances chuteront.

Il est intéressant d'expérimenter avec différents compilateurs et


différents paramètres d'optimisation. Nous en avons trouvé d'aussi jolis
des accélérations surprenantes étaient possibles en permettant des
optimisation. Nous avons également constaté que sur le RISC plus large
architectures les compilateurs du fabricant ont souvent surpassé
le GCC plus portable. Vraisemblablement, le fabricant est au courant
aux secrets d'une génération de code efficace sur ces machines.

Exercer
Exercer à partir de la vitesse de l'algorithme
35
35 ::
La routine ci-dessous imprime le contenu d'un arbre binaire.
En supposant que l'arbre est équilibré, à peu près combien d'espace de pile
la routine utilisera-t-elle lors de l'impression d'un arbre de 1 000 000 éléments ?
(Supposons que les appels de sous-programmes n'imposent aucune pile significative
s
Répondre
RépondreLa routine printTree utilise environ 1 000 octets d'espace de pile pour
35
35 :: la variable tampon. Il s'appelle récursivement descendre à travers
l'arborescence, et chaque appel imbriqué ajoute 1 000 octets supplémentaires à
empiler. Il s'appelle également lorsqu'il atteint les nœuds feuilles, mais quitte
immédiatement lorsqu'il découvre que le pointeur transmis est

NUL. Si la profondeur de l'arbre est D, la pile maximale


l'exigence est donc d'environ 1000 x (D + 1) .

Un arbre binaire équilibré contient deux fois plus d'éléments à chaque


niveau. Un arbre de profondeur D contient 1 + 2+4+8 J–1)+, ou
… +22
D- 1,

éléments. Notre arbre à un million d'éléments aura donc besoin de |


lg(l 000 001) |, soit 20 niveaux.

Nous nous attendrions donc à ce que notre routine utilise environ 21 000 octets de
empiler.

Exercer à partir de la vitesse de l'algorithme


Exercer
36:
36:
Pouvez-vous voir un moyen de réduire les exigences de pile du
routine dans l'exercice 35 (en plus de réduire la taille de la
amortir)?

Répondre
RépondreQuelques optimisations me viennent à l'esprit. Premièrement
p la
36:
36: la routine s'appelle sur les nœuds feuilles, seulement pour sortir car il n'y a pas
enfants. Cet appel augmente la profondeur de pile maximale d'environ
1 000 octets. Nous pouvons également éliminer la récursivité de la queue (la seconde
appel récursif), bien que cela n'affecte pas la pile dans le pire des cas
u

Le gain le plus important, cependant, provient de l'attribution d'un seul


tampon, partagé par toutes les invocations de printTree. Passez ce tampon en tant que
paramètre aux appels récursifs, et seuls 1 000 octets seront
a

}
Exercer
Exercer à partir de la vitesse de l'algorithme
37:
37:
À la page 180, nous avons affirmé qu'un hachage binaire est O(lg(n)). Peux-tu
prouver cela ?

Répondre
RépondreIl y a plusieurs façons d'y arriver. L'une consiste à tourner le
37:
37: problème sur sa tête. Si le tableau n'a qu'un seul élément, nous ne
itérer autour de la boucle. Chaque itération supplémentaire double le
taille du tableau que nous pouvons rechercher. La formule générale de la
la taille du tableau est donc nm=, où
2 m est le nombre de
itérations. Si vous amenez des bûches à la base 2 de chaque côté, vous obtenez lg(n)
= lg(2 m), qui par définition des logs devient lg(n) = m.

Exercer de la refactorisation
Exercer
38:
38:
Le code suivant a évidemment été mis à jour plusieurs fois
au fil des ans, mais les changements n'ont pas amélioré sa structure.
eR

Répondre
RépondreNous pourrions suggérer ici une restructuration assez légère : assurez-vous
38:
38: que chaque test est effectué une seule fois, et faire tous les
c
apparaît à d'autres endroits du programme, nous devrions probablement
en faire une fonction. Nous n'avons pas pris la peine ici.

Nous avons ajouté un tableau rate_lookup, initialisé pour que les entrées
autres que le Texas, l'Ohio et le Maine ont une valeur de 1.
permet d'ajouter facilement des valeurs pour d'autres états dans le
avenir. Selon le modèle d'utilisation prévu, nous pourrions
veux faire le p

Exercer
Exercer de la refactorisation
39:
39:
La classe Java suivante doit prendre en charge quelques formes supplémentaires.
eR
c

Répondre
RépondreLorsque vous voyez quelqu'un utiliser des types énumérés (ou leurs
39:
39: équivalent en Java) pour distinguer les variantes d'un type,
ov

Exercer
Exercer de la refactorisation
40
40 ::
Ce code Java fait partie d'un framework qui sera utilisé
tout au long de votre projet. Refactorisez-le pour qu'il soit plus général et
plus facile à étendre à l'avenir.
p

Répondre
RépondreCe cas est intéressant. A première vue, il semble raisonnable qu'un
40
40 :: fenêtre doit avoir une largeur et une hauteur. Cependant, considérez
l'avenir. Imaginons que l'on veuille soutenir arbitrairement
fenêtres en forme (ce qui sera difficile si la classe Window sait
tout sur les rectangles et leurs propriétés) .

Nous suggérons d'abstraire la forme de la fenêtre hors du


C

Notez que dans cette approche, nous avons utilisé la délégation plutôt que
sous-classement : une fenêtre n'est pas une forme "en quelque sorte" - une fenêtre "a-un"

forme. Il utilise une forme pour faire son travail. Vous trouverez souvent la délégation
utile lors de la refactorisation.

Nous aurions également pu étendre cet exemple en introduisant un Java


interface qui spécifie les méthodes qu'une classe doit prendre en charge pour prendre en charge
la forme fonctionne. C'est une bonne idée. Cela signifie que lorsque vous
étendre le concept d'une forme, le compilateur vous avertira de
classes que vous avez affectées. Nous vous recommandons d'utiliser des interfaces
de cette façon lorsque vous déléguez toutes les fonctions d'une autre classe.

Exercer
Exercer de Code facile à tester
41
41 ::
Concevoir un gabarit de test pour l'interface du mélangeur décrit dans le
réponse à l'exercice 17. Écrivez un script shell qui effectuera une
test de régression pour le mélangeur. Vous devez tester de base
fonctionnalité, conditions d'erreur et aux limites, et tout
obligations contractuelles. Quelles sont les restrictions imposées à
changer la vitesse? Sont-ils honorés ?

Répondre
RépondreTout d'abord, nousprincipal pour
ajouterons unagir en tant que pilote de test unitaire. Il acceptera un
41
41 :: très petit langage simple comme argument : "E" pour vider le
emix

Vei
e

Les tests vérifient si des changements de vitesse illégaux sont détectés, si vous
essayez de vider le mélangeur en cours d'exécution, et ainsi de suite. Nous mettons cela dans le
makefile afin que nous puissions compiler et exécuter le test de régression simplement
t

Notez que nous avons la sortie de test avec 0 ou 1 afin que nous puissions l'utiliser comme partie
d'un test plus large également.

Il n'y avait rien dans les exigences qui parlait de conduire ce


composant via un script, voire à l'aide d'un langage. Les utilisateurs finaux pourront
jamais le voir. Mais nous avons un outil puissant que nous pouvons utiliser pour tester notre
code, rapidement et de manière exhaustive.

Exercer
Exercer de la fosse aux exigences
42:
42:
Parmi les exigences suivantes, lesquelles sont probablement de véritables exigences ? Reformulez ceux
qui ne sont pas pour les rendre plus utiles (si possible).

1. Le temps de réponse doit être inférieur à 500 ms.


2. Les boîtes de dialogue auront un fond gris.
3. L'application sera organisée comme un certain nombre de front-end
processus et un serveur principal.
4. Si un utilisateur saisit des caractères non numériques dans un champ numérique, le
le système émettra un bip et ne les acceptera pas.
5. Le code d'application et les données doivent tenir dans 256 Ko.

Répondre
Répondre 1. Cette affirmation ressemble à une exigence réelle : il peut y avoir
42:
42: contraintes imposées à l'application par son environnement.
2. Même s'il s'agit d'une norme d'entreprise, ce n'est pas un
exigence. Il serait mieux indiqué comme "L'arrière-plan de la boîte de dialogue
doit être configurable par l'utilisateur final. Comme expédié, la couleur sera
gris." Encore mieux serait la déclaration plus large "Tous les visuels
les éléments de l'application (couleurs, polices et langues) doivent être
configurable par l'utilisateur final."
3. Cette déclaration n'est pas une exigence, c'est une architecture. Lorsqu'ils sont confrontés
avec quelque chose comme ça, vous devez creuser profondément pour savoir ce que le
l'utilisateur pense.
4. L'exigence sous-jacente est probablement quelque chose de plus proche de "La
le système empêchera l'utilisateur de faire des entrées invalides dans les champs,
et avertira l'utilisateur lorsque ces entrées seront effectuées."
5. Cette déclaration est probablement une exigence stricte.

Vous aimerez peut-être aussi