IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Penser en Java 2nde édition - Sommaire |  Préface |  Avant-propos | Chapitre : 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15 |  Annexe : A B C D  | Tables des matières - Thinking in Java

  Chapitre 1 - Introduction sur les « objets »

pages : 1 2 3 4 5 6 7 8 

J'ai étudié à différentes reprises les techniques d'analyse et de conception depuis que je suis sorti de l'école. Le concept de Programmation Extreme (XP) est le plus radical et divertissant que j'ai vu. Il est rapporté dans Extreme Programming Explained de Kent Beck (Addison-Wesley, 2000) et sur le web à www.xprogramming.com.

XP est à la fois une philosophie à propos de la programmation et un ensemble de règles de bases. Certaines de ces règles sont reprises dans d'autres méthodologies récentes, mais les deux contributions les plus importantes et novatrices, sont à mon sens « commencer par écrire les tests » et « programmation en binôme ». Bien qu'il soutienne et argumente l'ensemble de la théorie, Beck insiste sur le fait que l'adoption de ces deux pratiques améliore grandement la productivité et la fiabilité.

Commencer par écrire les tests

Les tests ont traditionnellement été relégués à la dernière partie d'un projet, une fois que « tout marche, mais c'est juste pour s'en assurer ». Ils ne sont généralement pas prioritaires et les gens qui se spécialisent dedans ne sont pas reconnus à leur juste valeur et se sont souvent vus cantonnés dans un sous-sol, loin des « véritables programmeurs ». Les équipes de test ont réagi en conséquence, allant jusqu'à porter des vêtements de deuil et glousser joyeusement quand ils trouvaient des erreurs (pour être honnête, j'ai eu moi aussi ce genre de sentiments lorsque je mettais des compilateurs en faute).

XP révolutionne complètement le concept du test en lui donnant une priorité aussi importante (ou même plus forte) que le code. En fait, les tests sont écrits avant le code qui sera testé, et les tests restent tout le temps avec le code. Ces tests doivent être exécutés avec succès à chaque nouvelle intégration dans le projet (ce qui peut arriver plus d'une fois par jour).

Ecrire les tests d'abord a deux effets extrêmement importants.

Premièrement, cela nécessite une définition claire de l'interface d'une classe. J'ai souvent suggéré que les gens « imaginent la classe parfaite qui résolve un problème particulier » comme outil pour concevoir le système. La stratégie de test de XP va plus loin - elle spécifie exactement ce à quoi la classe doit ressembler pour le client de cette classe, et comment la classe doit se comporter. Dans des termes non ambigus. On peut écrire tout ce qu'on veut, ou créer tous les diagrammes qu'on veut, décrivant comment une classe devrait se comporter et ce à quoi elle ressemble, mais rien n'est aussi réel qu'une batterie de tests. Le premier est une liste de voeux, mais les tests sont un contrat certifié par un compilateur et un programme qui marche. Il est dur d'imaginer une description plus concrète d'une classe que des tests.

En créant les tests, on est forcé de penser complètement la classe et souvent on découvre des fonctionnalités nécessaires qui ont pu être manquées lors de l'utilisation des diagrammes UML, des cartes CRC, des cas d'utilisation, etc...

Le deuxième effet important dans l'écriture des tests en premier vient du fait qu'on peut lancer les tests à chaque nouvelle version du logiciel. Cela permet d'obtenir l'autre moitié des tests réalisés par le compilateur. Si on regarde l'évolution des langages de programmation de ce point de vue, on se rend compte que les améliorations réelles dans la technologie ont en fait tourné autour du test. Les langages assembleur vérifiaient uniquement la syntaxe, puis le C a imposé des restrictions sémantiques, et cela permettait d'éviter certains types  d'erreurs. Les langages orientés objet imposent encore plus de restrictions sémantiques, qui sont quand on y pense des formes de test. « Est-ce que ce type de données est utilisé correctement ? » et « Est-ce que cette fonction est appelée correctement ? » sont le genre de tests effectués par le compilateur ou le système d'exécution. On a pu voir le résultat d'avoir ces tests dans le langage même : les gens ont été capables de construire des systèmes plus complexes, et de les faire marcher, et ce en moins de temps et d'efforts. Je me suis souvent demandé pourquoi, mais maintenant je réalise que c'est grâce aux tests : si on fait quelque chose de faux, le filet de sécurité des tests intégré au langage prévient qu'il y a un problème et montre même où il réside.

Mais les tests intégrés permis par la conception du langage ne peuvent aller plus loin. A partir d'un certain point, il est de notre responsabilité de produire une suite complète de tests (en coopération avec le compilateur et le système d'exécution) qui vérifie tout le programme. Et, de même qu'il est agréable d'avoir un compilateur qui vérifie ce qu'on code, ne serait-il pas préférable que ces tests soient présents depuis le début ? C'est pourquoi on les écrit en premier, et qu'on les exécute automatiquement à chaque nouvelle version du système. Les tests deviennent une extension du filet de sécurité fourni par le langage.

L'utilisation de langages de programmation de plus en plus puissants m'a permis de tenter plus de choses audacieuses, parce que je sais que le langage m'empêchera de perdre mon temps à chasser les bugs. La stratégie de tests de XP réalise la même chose pour l'ensemble du projet. Et parce qu'on sait que les tests vont révéler tous les problèmes introduits (et on ajoute de nouveaux tests au fur et à mesure qu'on les imagine), on peut faire de gros changements sans se soucier de mettre le projet complet en déroute. Ceci est une approche particulièrement puissante.

Programmation en binôme

La programmation en binôme va à l'encontre de l'individualisme farouche endoctriné, depuis l'école (où on réussit ou échoue suivant nos mérites personnels, et où travailler avec ses voisins est considéré comme « tricher »), et jusqu'aux médias, en particulier les films hollywoodiens dans lequel le héros se bat contre la conformité [17]. Les programmeurs aussi sont considérés comme des parangons d'individualisme - des « codeurs cowboy » comme aime à le dire Larry Constantine. Et XP, qui se bat lui-même contre la pensée conventionnelle, soutient que le code devrait être écrit avec deux personnes par station de travail. Et cela devrait être fait dans un endroit regroupant plusieurs stations de travail, sans les barrières dont raffolent les gens des Moyens Généraux. En fait, Beck dit que la première tâche nécessaire pour implémenter XP est de venir avec des tournevis et d'enlever tout ce qui se trouve dans le passage [18](cela nécessite un responsable qui puisse absorber la colère du département des Moyens Généraux).

Dans la programmation en binôme, une personne produit le code tandis que l'autre y réfléchit. Le penseur garde la conception générale à l'esprit - la description du problème, mais aussi les règles de XP à portée de main. Si deux personnes travaillent, il y a moins de chance que l'une d'entre elles s'en aille en disant « Je ne veux pas commencer en écrivant les tests », par exemple. Et si le codeur reste bloqué, ils peuvent changer leurs places. Si les deux restent bloqués, leurs songeries peuvent être remarquées par quelqu'un d'autre dans la zone de travail qui peut venir les aider. Travailler en binôme permet de garder une bonne productivité et de rester sur la bonne pente. Probablement plus important, cela rend la programmation beaucoup plus sociable et amusante.

J'ai commencé à utiliser la programmation en binôme durant les périodes d'exercice dans certains de mes séminaires et il semblerait que cela enrichisse l'expérience personnelle de chacun.

Les raisons du succès de Java

Java est si populaire actuellement car son but est de résoudre beaucoup de problèmes auxquels les programmeurs doivent faire face aujourd'hui. Le but de Java est d'améliorer la productivité. La productivité vient de différents horizons, mais le langage a été conçu pour aider un maximum tout en entravant le moins possible avec des règles arbitraires ou l'obligation d'utiliser un ensemble particulier de caractéristiques. Java a été conçu pour être pratique ; les décisions concernant la conception de Java furent prises afin que le programmeur en retire le maximum de bénéfices.

Les systèmes sont plus faciles à exprimer et comprendre

Les classes conçues pour résoudre le problème sont plus faciles à exprimer. La solution est mise en oeuvre dans le code avec des termes de l'espace problème (« Mets le fichier à la poubelle ») plutôt qu'en termes machine, l'espace solution (« Positionne le bit à 1 ce qui veut dire que le relais va se fermer »). On traite de concepts de plus haut niveau et une ligne de code est plus porteuse de sens.

L'autre aspect bénéfique de cette facilité d'expression se retrouve dans la maintenance, qui représente (s'il faut en croire les rapports) une grosse part du coût d'un programme. Si un programme est plus facile à comprendre, il est forcément plus facile à maintenir. Cela réduit aussi le coût de création et de maintenance de la documentation.

Puissance maximale grâce aux bibliothèques

La façon la plus rapide de créer un programme est d'utiliser du code déjà écrit : une bibliothèque. Un des buts fondamentaux de Java est de faciliter l'emploi des bibliothèques. Ce but est obtenu en convertissant ces bibliothèques en nouveaux types de données (classes), et utiliser une bibliothèque revient à ajouter de nouveaux types au langage. Comme le compilateur Java s'occupe de l'interfaçage avec la bibliothèque - garantissant une initialisation et un nettoyage propres, et s'assurant que les fonctions sont appelées correctement - on peut se concentrer sur ce qu'on attend de la bibliothèque, et non sur les moyens de le faire.

Traitement des erreurs

L'une des difficultés du C est la gestion des erreurs, problème connu et largement ignoré - le croisement de doigts est souvent impliqué. Si on construit un programme gros et complexe, il n'y a rien de pire que de trouver une erreur enfouie quelque part sans qu'on sache d'où elle vienne. Le traitement des exceptions de Java est une façon de garantir qu'une erreur a été remarquée, et que quelque chose est mis en oeuvre pour la traiter.

Mise en oeuvre de gros projets

Beaucoup de langages traditionnels imposent des limitations internes sur la taille des programmes et leur complexité. BASIC, par exemple, peut s'avérer intéressant pour mettre en oeuvre rapidement des solutions pour certains types de problèmes ; mais si le programme dépasse quelques pages de long, ou s'aventure en dehors du domaine du langage, cela revient à tenter de nager dans un liquide encore plus visqueux. Aucune limite ne prévient que le cadre du langage est dépassé, et même s'il en existait, elle serait probablement ignorée. On devrait se dire : « Mon programme BASIC devient trop gros, je vais le réécrire en C ! », mais à la place on tente de glisser quelques lignes supplémentaires pour implémenter cette nouvelle fonctionnalité. Le coût total continue donc à augmenter.

Java a été conçu pour pouvoir mettre en oeuvre toutes les tailles de projets - c'est à dire, pour supprimer ces frontières liées à la complexité croissante d'un gros projet. L'utilisation de la programmation orientée objet n'est certainement pas nécessaire pour écrire un programme utilitaire du style « Hello world ! », mais les fonctionnalités sont présentes quand on en a besoin. Et le compilateur ne relâche pas son attention pour dénicher les bugs - produisant indifféremment des erreurs pour les petits comme pour les gros programmes.  

Stratégies de transition

Si on décide d'investir dans la POO, la question suivante est généralement : « Comment convaincre mes directeur / collègues / département / collaborateurs d'utiliser les objets ? ». Il faut se mettre à leur place et réfléchir comment on ferait s'il fallait apprendre un nouveau langage et un nouveau paradigme de programmation. Ce cas s'est sûrement déjà présenté de par le passé. Il faut commencer par des cours et des exemples ; puis lancer un petit projet d'essai pour inculquer les bases sans les perdre dans les détails. Ensuite passer à un projet « réel » qui réalise quelque chose d'utile. Au cours du premier projet, continuer l'apprentissage par la lecture, poser des questions à des experts et échanger des astuces avec des amis. Cette approche est celle recommandée par de nombreux programmeurs expérimentés pour passer à Java. Si toute l'entreprise décide de passer à Java, cela entraînera bien sûr une dynamique de groupe, mais cela aide de se rappeler à chaque étape comment une personne seule opérerait.

Règles de base

Voici quelques indications à prendre en compte durant la transition vers la programmation orientée objet et Java.

1. Cours

La première étape comprend une formation. Il ne faut pas jeter la confusion pendant six ou neuf mois dans l'entreprise, le temps que tout le monde comprenne comment fonctionnent les interfaces. Il vaut mieux se contenter d'un petit groupe d'endoctrinement, composé de préférence de personnes curieuses, s'entendant bien entre elles et suffisamment indépendantes pour créer leur propre réseau de support concernant l'apprentissage de Java.

Une approche alternative suggérée quelquefois comprend la formation de tous les niveaux de l'entreprise à la fois, en incluant à la fois des cours de présentation pour les responsables et des cours de conception et de programmation pour les développeurs. Ceci est particulièrement valable pour les petites entreprises qui n'hésitent pas à introduire des changements radicaux dans leurs manières de faire, ou au niveau division des grosses entreprises. Cependant, comme le coût résultant est plus important, certains choisiront de commencer avec des cours, de réaliser un projet pilote (si possible avec un mentor extérieur), et de laisser l'équipe du projet devenir les professeurs pour le reste de l'entreprise.

2. Projet à faible risque

Tester sur un projet à faible risque qui autorise les erreurs. Une fois gagnée une certaine expérience, on peut soit répartir les membres de cette première équipe sur les autres projets ou utiliser cette équipe comme support technique de la POO. Le premier projet peut ne pas fonctionner correctement dès le début, il ne faut donc pas qu'il soit critique pour l'entreprise. Il doit être simple, indépendant et instructif : cela veut dire qu'il doit impliquer la création de classes qui soient compréhensibles aux autres programmeurs quand arrivera leur tour d'apprendre Java.

3. S'inspirer de bonnes conceptions

Rechercher des exemples de bonnes conceptions orientées objet avant de partir de zéro. Il y a de fortes chances que quelqu'un ait déjà résolu le problème, et s'ils ne l'ont pas résolu exactement modifier le système existant (grâce à l'abstraction, cf plus haut) pour qu'il remplisse nos besoins. C'est le concept général des patrons génériques, couverts dans Thinking in Patterns with Java, téléchargeable à www.BruceEckel.com.

4. Utiliser les bibliothèques de classes existantes

La motivation économique première pour passer à la POO est la facilité de réutilisation de code existant sous la forme de bibliothèques de classes (en particulier, les Bibliothèques Standard Java, couvertes tout au long de ce livre). On arrive au cycle de développement le plus court quand on crée et utilise des objets directement tirés des bibliothèques. Cependant, de nouveaux programmeurs ne saisissent pas ce point, ne connaissent pas l'existence de telles bibliothèques ou, fascinés par le langage, veulent réécrire des classes qui existent déjà. Le succès de la transition vers Java et la POO passe par des efforts pour encourager les gens à réutiliser le plus possible le code des autres.

5. Ne pas traduire du code existant en Java

Ce n'est généralement pas le meilleur usage de son temps qu'on puisse trouver que de prendre du code existant et fonctionnel et de le traduire en Java (si on doit le transformer en objets, on peut s'interfacer avec du code C ou C++ en utilisant l'Interface Native Java - JNI - décrite dans l'annexe B). Il y a bien sûr des avantages à le faire, particulièrement si ce code est destiné à être réutilisé. Mais il y a de fortes chances pour qu'on passe à côté de la spectaculaire amélioration de productivité espérée sauf si ce premier projet en est un nouveau. Java et la POO sont mis en valeur quand on suit un projet de la conception à la mise en oeuvre.

Les obstacles au niveau du management

Si on se situe du côté des responsables, le travail consiste à acquérir des ressources pour l'équipe, surmonter les obstacles pouvant gêner l'équipe, et en général tenter de fournir l'environnement le plus productif et agréable afin que l'équipe puisse accomplir ces miracles qu'on vous demande toujours de réaliser. Le passage à Java entre dans ces trois catégories, et ce serait merveilleux si de plus cela ne coûtait rien. Bien que le passage à Java puisse être moins onéreux - suivant les contraintes - que d'autres alternatives de POO pour une équipe de programmeurs C (et probablement pour les développeurs dans d'autres langages), ce coût n'est pas nul, et il y a des obstacles dont il faut être conscient avant de promouvoir le passage à Java à l'intérieur de l'entreprise et de s'embarquer dans la transition.

Coûts de mise en oeuvre

Le coût du passage à Java recouvre plus que l'acquisition d'un compilateur Java (le compilateur Java fourni par Sun est gratuit, cela n'est donc pas un obstacle). Les coûts à moyen et long terme seront minimisés si on investit dans la formation (et éventuellement dans la participation d'un consultant pour le premier projet), de même que si on identifie et achète des bibliothèques de classes qui résolvent les problèmes plutôt que de tenter de réécrire ces bibliothèques soi-même. Ce sont des investissements lourds qui doivent être relativisés dans une proposition raisonnable. De plus, il existe des coûts cachés dans la baisse de productivité liée à l'apprentissage d'un nouveau langage et éventuellement d'un nouvel environnement de développement. La formation et l'encadrement peuvent certainement les réduire, mais les membres de l'équipe devront  mener leur propre combat pour maîtriser la nouvelle technologie. Durant cette phase ils feront plus d'erreurs (c'est prouvé, et les erreurs comprises constituent le meilleur moyen de progresser) et seront moins productifs. Cependant, avec certains types de problèmes, les bonnes classes et le bon environnement de développement, il est possible d'être plus productif pendant l'apprentissage de Java (même en considérant qu'on fait plus d'erreurs et qu'on écrit moins de lignes de code par jour) que si on en était resté au C.

Problèmes de performances

Une question qui revient souvent est : « Est-ce que la POO ne rend pas obligatoirement mes programmes plus gros et plus lents ? ». La réponse est « Ca dépend. ». Les fonctionnalités de vérification introduites dans Java ont prélevé leur tribut sur la performance comparé à un langage comme le C++. Des technologies telles que le « hotspot » et les techniques de compilation ont significativement amélioré la vitesse dans la plupart des cas, et les efforts pour des performances accrues continuent.

Quand on se concentre sur le prototypage rapide, on assemble des composants aussi vite que possible en ignorant les problèmes liés à l'efficacité. Si on utilise des bibliothèques extérieures, celles-ci ont généralement été optimisées par leurs distributeurs ; de toutes façons ce n'est pas la préoccupation première quand on est en phase de développement rapide. Quand on dispose d'un système qui nous satisfait et s'il est suffisamment petit et rapide, alors le tour est joué. Sinon, on tente de mettre au point avec un outil de profilage, en cherchant en premier des améliorations qui peuvent être faites en réécrivant de petites portions de code. Si cela ne suffit pas, il faut chercher si on peut apporter quelques changements à l'implémentation sous-jacente afin qu'aucune classe particulière n'ait besoin de modifier son code. Il ne faut toucher à la conception que si rien d'autre ne résout le problème. Le fait que les performances soient si critiques dans cette phase de la conception est un indicateur que ce doit être un des critères essentiels de la conception. On a le bénéfice de s'en rendre compte relativement tôt en utilisant le prototypage rapide.

Si on trouve une fonction qui soit un goulot d'étranglement, on peut la réécrire en C ou en C++ en utilisant les méthodes natives de Java, sujet de l'annexe B.

Erreurs classiques de conception

Quand l'équipe commencera la programmation orientée objet et Java, les programmeurs vont typiquement passer par une série d'erreurs classiques de conception. Ceci est souvent du à des retours insuffisants de la part d'experts durant la conception et l'implémentation des premiers projets, puisqu'aucun expert n'existe encore au sein de l'entreprise et qu'il peut y avoir des réticences à engager des consultants. Il est facile de se dire trop tôt qu'on maîtrise la POO et partir sur de mauvaises bases. Quelque chose d'évident pour une personne expérimentée peut être le sujet d'un débat interne intense pour un novice. La plupart de ces difficultés peuvent être évitées en utilisant un expert extérieur pour la formation.

Ce livre a été écrit par Bruce Eckel ( télécharger la version anglaise : Thinking in java )
Ce chapitre a été traduit par Jérome Quelin ( groupe de traduction )
télécharger la version francaise (PDF) | Commandez le livre en version anglaise (amazon) | télécharger la version anglaise
pages : 1 2 3 4 5 6 7 8 
Penser en Java 2nde édition - Sommaire |  Préface |  Avant-propos | Chapitre : 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15 |  Annexe : A B C D  | Tables des matières - Thinking in Java