Savoir décomposer un problème

L'enseignement de la programmation évoque souvent des questions de choix de langage (faut-il commencer par Python, Java, ou un langage destiné plus particulièrement à l'enseignement), d'où la critique que, le monde informatique évoluant vite, ce que les étudiants apprennent soit démodé quelques années plus tard. Outre une certaine surestimation du renouvellement en informatique (le langage C a 40 ans, et ne parlons pas de Fortran et Cobol…), cette critique passe à côté d'un fait important : la principale difficulté de l'apprentissage de la programmation, ce ne sont pas les particularités, souvent inintéressantes, de tel ou tel langage ou de tel ou tel système, c'est la capacité, ou l'incapacité, à prendre un problème complexe et à le diviser en sous-problèmes bien identifiés et de complexité maîtrisable, de former des hypothèses sur ces sous-problèmes et de les tester, et d'identifier ce qui est important et ce qui ne l'est pas. Ceci implique, notamment, la capacité à fixer des objectifs intermédiaires et à les évaluer.

Prenons un exemple concret. Une amie aurait voulu un logiciel qui prenne l'ensemble des fichiers audio stockés dans son ordinateur et en fasse une liste triée par durée d'écoute. Les systèmes de gestion à sa disposition ne permettaient pas de produire une telle liste. Je lui ai donc proposé un petit programme, qui dans un premier temps fournissait la liste des fichiers d'un seul répertoire, puis explorait les sous-répertoires. Ce qui est intéressant, c'est sa réaction à la première version du programme, que je lui avais demandé d'essayer : elle était inutile, disait-elle, vu qu'elle n'explorait pas les sous-répertoires. Visiblement, l'idée qu'avant d'accoupler deux difficultés (l'extraction des données d'un fichier audio, d'une part, et le parcours récursif de sous-répertoires, d'autre part), il faut tester chacune indépendamment, ne lui était pas naturelle.

Les étudiants qui n'ont pas acquis cette « compétence », pour employer le vocabulaire éducatif à la mode, ne parviennent pas à réaliser leurs projets : soit que devant l'ampleur de la tâche, ils ne sachent pas par quoi débuter, soit qu'ils passent trop de temps sur des détails au risque, de toute façon, de devoir revenir dessus.

Savoir se remettre en cause

On sait bien que ce qui est pénible dans la programmation, c'est le déboguage, autrement dit la recherche de la source d'un dysfonctionnement dans un logiciel. La première difficulté du déboguage est la remise en cause des certitudes et de la fierté du développeur.

On voit parfois des étudiants qui, devant leur programme qui ne fonctionnent pas, évoquent la possibilité d'un bug non pas dans leur propre production, mais dans l'environnement de développement utilisé. C'est bien sûr une occurrence du proverbe « un mauvais ouvrier a toujours de mauvais outils », avec ce trait bizarre d'incongruité ou d'excessive confiance en soi qu'il y a à évoquer en première hypothèse la possibilité d'un dysfonctionnement dans un système professionnel et utilisé par des millions de personnes plutôt que dans le programme d'un débutant…

De même, on entend souvent des étudiants se plaindre d'avoir été notés « injustement ». Comme le rappelle Gilles Dowek, l'exécution incorrecte d'un programme est un fait objectif : s'il affiche 3 ou s'arrête inopinément alors qu'il devrait afficher 10, il n'y a nulle possibilité d'invoquer la sévérité excessive de l'enseignant ou de dénoncer la subjectivité de la notation d'une dissertation.

Un logiciel est une création de l'esprit : il n'y a pas de contingence matérielle. Un dysfonctionnement d'un logiciel créé par un individu (la responsabilité est bien entendue plus facile à diluer s'il s'agit d'un groupe d'individus) est donc, sauf bug dans l'environnement de programmation, due à une erreur de conception, une erreur de pensée. Ceci est difficile à admettre, et la première difficulté du déboguage est de savoir se remettre en cause et d'admettre que l'on a fait une erreur.

Douter de tout, jusqu'à preuve du contraire

La grande difficulté du déboguage est que l'on arrive sur le programme avec des idées préconçues sur ce que chacune de ses parties est censé faire. Le mot « censé » est important, puisque, vu que l'on cherche un bug, c'est fort probablement qu'il y a une partie du logiciel qui ne se comporte pas comme on le pensait. Or, très souvent, on part sur une idée préconçue sur ce qui ne fonctionne pas et pourquoi.

Il y a quelques années, des étudiants me montraient une procédure de (si je me rappelle bien) parcours de graphe, qui m'avait l'air correcte, mais qui ne fonctionnait pas correctement. Cette procédure en appelait une autre qui gérait une structure de données simple. Je demandai ce que celle-ci faisait ; on me paraphrasa son nom. Je demandai s'ils étaient sûrs qu'elle faisait réellement ce que son nom laissait supposer. Il me fallut insister pour que les étudiants consentissent à vérifier cette procédure, qui était effectivement la coupable.

Je ne voudrais pas que l'on pense que je m'exonère des faiblesses humaines que j'attribue aux étudiants, aussi je dois avouer qu'il m'est parfois arrivé, devant le travail incorrect d'un étudiant, de penser avoir rapidement trouvé la cause du problème, en me trompant largement.

Pour déboguer efficacement, il faut donc se méfier des idées préconçues et des supputations, et procéder avec méthode. Recommandation que l'on peut appliquer dans bien d'autres domaines d'activité.

Douter des idées préconçues

En informatique, il est courant d'avoir des idées préconçues sur ce qui coûte cher ou non (en temps de calcul, en mémoire, etc.). Ces idées sont parfois adossées à un cadre théorique (étude de la complexité des algorithmes, classes de complexités de problèmes) ; mais se pose alors la question de l'applicabilité de résultats théoriques, obtenus sur un modèle simplifié de l'exécution d'un ordinateur, et donc les critères (par exemple, complexité dans le pire cas général) peuvent ne pas être pertinents pour le problème à résoudre effectivement — on touche ici à un problème épistémologique.

Or, ces idées préconçues s'appliquent parfois au cas d'espèce étudié… mais parfois non, et elles induisent alors en erreur — d'où le dicton de Daniel J. Bernstein, « Profile, don't speculate! » — « mesurez réellement les consommations en ressources plutôt que de supputer ».

Qui plus est, mesurer ces consommations n'est pas forcément aisé (par exemple, dans certains cas, il est pertinent de mesurer des consommations amorties sur un grand nombre d'action, et non la consommation de chaque action individuelle), et un choix inapproprié d'exemples ou de technique de mesure peut biaiser les résultats.

Il s'agit, là encore, de problèmes que l'on retrouve dans bien d'autres branches d'activités : dans d'autres sciences et techniques, bien sûr, mais aussi en politique — combien de débats sur des supputations et non sur des faits, sur des chiffres dont on ne sait pas comment et sur quels échantillons ils ont été obtenus, combien de mesures proposées qui n'auraient qu'une influence négligeable au regard de ce qu'elles seraient censées corriger…

Observer et réfléchir à des réponses pertinentes

Une partie des étudiants, devant un dysfonctionnement dans un programme pourtant pas si faux que cela, n'abordent pas la difficulté méthodiquement, mais au contraire essayent des modifications pas toujours très pertinentes, voire même sans rapport avec le problème rencontré. Au final, ils finissent souvent par produire quelque chose de plus faux que leur premier jet.

Par ailleurs, il est courant que les étudiants, malgré toutes les invitations des enseignants, ne lisent pas les messages d'erreur affichés par le système. Je n'ai pas d'explication ou de théorie quant à ce fait, mais je le constate année après année.

Ainsi, là où il faudrait s'informer et réfléchir posément à ce qui peut mal aller, l'étudiant va souvent absolument vouloir « faire quelque chose », un petit peu au hasard ou sur la base d'idées préconçues ; puis comme ça ne fonctionne toujours pas, il essaye autre chose, etc.

On peut sourire devant pareil comportement, mais que font d'autre nos parlementaires quand, dans la hâte et pour réagir à un « fait divers », et sans prendre le temps de s'informer, ils produisent une loi de circonstance afin de démontrer qu'ils « agissent » ?

L'apprentissage de la méthode

On peut résumer ce qui précède par : la programmation (et surtout le déboguage) nécessite un esprit méthodique, qui sait diviser un problème en sous-problèmes, tester et évaluer des hypothèses, et se remettre en question ; les esprits confus ou qui se perdent dans les détails n'arrivent pas à mener à bien leurs projets. Son apprentissage, mené sérieusement, devrait donc développer certaines qualités d'esprit transposables à d'autres domaines.

Ces qualités sont, en bonne partie, les mêmes que celles nécessaires pour les travaux scientifiques ; on pourrait aussi les développer au travers des sciences expérimentales. Cependant, il est bien plus simple et rapide d'arriver avec la programmation sur des problèmes intéressants, alors qu'en physique, chimie ou biologie les expériences sont plus longues, nécessitent du matériel et posent éventuellement des problèmes de sécurité.

Les difficultés des mesures et le danger des préjugés s'appliquent, bien sûr, également aux sciences sociales. Du cours de sciences économiques et sociales de seconde, je ne me rappelle que d'une chose : la facilité avec laquelle on peut se laisser abuser par les chiffres, suivant comment ceux-ci sont présentés (par exemple : comment on peut avoir, sans mensonge ni trucage, à la fois le salaire moyen qui baisse dans chaque catégorie professionnelle tout en ayant une augmentation du salaire moyen de la population entière des travailleurs). L'avantage de l'informatique est que l'on peut aborder cette question de la mesure, de la méthode de mesure, des préconceptions sur son résultat, sans que la réflexion ne soit incommodée par des considérations politiques et des supputations sur les biais idéologiques des enseignants.

Que faire ?

La question de l'enseignement de l'informatique à l'école primaire et dans le secondaire est posée en France depuis une trentaine d'années. Dans les années 1980, le « plan informatique pour tous » mettait des ordinateurs Thomson MO5 et TO7 dans les écoles primaires et les collèges ; si certains instituteurs, dont mon maître de CM2, savaient programmer, il semble que ce plan ait été un échec notamment en raison de manque de formation pour les enseignants et de manque de personnel compétent pour gérer le parc informatique. Dans les années 1990, il existait une option informatique au baccalauréat ; celle-ci a été supprimée par la suite, pour des raisons que j'ignore.

La programmation, orientée vers le calcul numérique scientifique, était enseignée dans les classes préparatoires aux grandes écoles scientifiques. Jusqu'en 1997 existait à l'agrégation de mathématiques une option informatique, portant il me semble en partie sur les mathématiques discrètes. Celle-ci a été supprimée, puis on a réintroduit plus tard une option informatique portant notamment sur la logique et les automates.

Parallèlement, on a introduit dans l'enseignement secondaire et supérieur des formations « informatiques » qui sont, si je ne m'abuse, plutôt des formations à certains usages de l'informatique (bureautique) et à leur cadre juridique.

Tout ceci nous montre bien l'inconstance, l'incohérence et l'inconscience des décideurs publics en la matière. Quant au débat public, il semble comporter d'une part ceux qui pensent que mettre de la programmation à l'école primaire est nécessaire pour l'économie (j'en doute fortement, pour tout avouer), d'autre part ceux qui pensent que la programmation est une activité « technique » qui n'a pas sa place dans l'enseignement général puisqu'elle ne forme pas la pensée. J'ai voulu répondre aux seconds.