Comparaison de langages de programmation pour débutant(e)s

Ce qui suit présente quelques exemples de programmes types d'un cours de 1re session en informatique, du moins pour la formation traditionnellement jugée « fondamentale » au Collège (il est, évidemment, possible de remettre en question le caractère fondamental de ces choix; la démocratie prime, et il s'agit d'un autre débat).

Ce que je tente de faire ici est de montrer (très brièvement, faute de temps) un comparatif de diverses approches pour des problèmes classiques (ce qui ne veut pas dire que ce soit ces problèmes qui devraient être utilisés pour enseigner les bases, évidemment, mais j'ai utilisé ceux que nous utilisions quand j'était de ceux qui offraient cette formation), et d'identifier les difficultés et les qualités de chacune des approches. Sans surprises, il y a des avantages et des inconvénients à chacune.

Dans chaque cas, la clientèle visée étant débutante, j'ai essayé de faire des choix (en particulier, des using) que je ne ferais pas dans du code de production, le tout visant à alléger la syntaxe et à aller à l'essentiel.

Cas typique d'un Hello World

Mise en situation : un premier programme, un apprivoisement de la forme et un premier contact avec les outils.

Langage Pseudocode C++ C# Java
Code
Écrire "J'aime mon prof"
#include <iostream>
using namespace std;
int main() {
   cout << "J'aime mon prof"
        << endl;
}
using System;
namespace Hello
{
   class Program
   {
      static void Main(string [] args)
      {
         Console.WriteLine("J'aime mon prof");
      }
   }
}
public class Hello {
   public static void main(String [] args) {
      System.out.println("J'aime mon prof");
   }
}
Objectifs conceptuels

Un premier programme

Écrire un programme, apprivoiser l'éditeur.

Particularités techniques

Les guillemets pour le texte.

La primitive Écrire

Directive #include et instruction using namespace std; (toutes deux sous forme de formule magique).

Syntaxe du programme principal :

int main() {
   ...
}

Mots cout et endl, et symbole <<

Les guillemets pour le texte.

Le rôle du ;

Instruction using System; (sous forme de formule magique).

Le namespace (qui correspond au nom du projet).

Le class Program (sous forme de formule magique, probablement).

Syntaxe du programme principal :

static void Main(string [] args)
{
   ...
}

Mots clés static, void et string, de même que les symboles [] (typiquement, ça reste de la magie à ce stade)

Expression Console.WriteLine()

Les guillemets pour le texte.

Le rôle du ;

Le public class Hello (qui correspond au nom du fichier).

Syntaxe du programme principal :

public static void main(String [] args) {
   ...
}

Mots clés public, static, void et String, de même que les symboles [] (typiquement, ça reste de la magie à ce stade)

Expression System.out.println()

Les guillemets pour le texte.

Le rôle du ;

Remarques

Tellement simple que ça ressemble à peine à un programme. On donne un ordre à un ordinateur, il obéit.

Surtout pour apprivoiser l'environnement et constater qu'on peut rapidement faire quelque chose qui fonctionne.

Surtout pour apprivoiser l'environnement et constater qu'on peut rapidement faire quelque chose qui fonctionne.

Surtout pour apprivoiser l'environnement et constater qu'on peut rapidement faire quelque chose qui fonctionne.

Calcul du volume d'une sphère

Mise en situation : un algorithme qui comprend une séquence, une lecture, une écriture, un traitement (avec risque d'erreur technique, c'est volontaire), une variable, une constante, des littéraux, une affectation, une lecture et une écriture. Pas mal le plus petit programme pertinent possible (l'un d'eux, du moins).

Langage Pseudocode C++ C# Java
Code
PI ← 3.14159
Lire rayon
volume ← 4/3 * PI * rayon^3
Écrire volume
#include <iostream>
using namespace std;
int main() {
   const float PI = 3.14159f;
   float rayon,
         volume;
   cin >> rayon;
   volume = 4.0f/3.0f * PI * rayon * rayon * rayon;
   cout << volume << endl;
}
using System;
namespace Sphère
{
   class Program
   {
      static void Main(string [] args)
      {
         const float PI = 3.14159f;
         float rayon,
               volume;
         rayon = float.Parse(Console.ReadLine());
         volume = 4.0f/3.0f * PI * rayon * rayon * rayon;
         Console.WriteLine(volume);
      }
   }
}
import java.io.*;
public class Sphère {
   public static void main(String [] args) {
      final float PI = 3.14159f;
      float rayon,
            volume;
      try {
         rayon = Float.parseFloat(
                    new BufferedReader(
                       new InputStreamReader(System.in)
                    ).readLine());
         volume = 4.0f/3.0f * PI * rayon * rayon * rayon;
         System.out.println(volume);
      } catch (Exception e) {
      }
   }
}
Code (avec appel de fonction mathématique)
PI ← 3.14159
Lire rayon
Volume ← 4/3 * PI * rayon^3
Écrire volume
#include <iostream>
#include <cmath>
using namespace std;
int main() {
   const float PI = 3.14159f;
   float rayon,
         volume;
   cout << "Rayon? ";
   cin >> rayon;
   volume = 4.0f/3.0f * PI * pow(rayon,3);
   cout << volume << endl;
}
using System;
namespace Sphère
{
   class Program
   {
      static void Main(string [] args)
      {
         const float PI = 3.14159f;
         float rayon,
               volume;
         Console.Write("Rayon? ");
         rayon = float.Parse(Console.ReadLine());
         volume = 4.0f/3.0f * PI * (double) Math.Pow(rayon,3);
         Console.WriteLine(volume);
      }
   }
}
import java.io.*;
public class Sphère {
   public static void main(String [] args) {
      final float PI = 3.14159f;
      float rayon,
            volume;
      System.out.print("Rayon? ");
      try {
         rayon = Float.parseFloat(
                    new BufferedReader(
                       new InputStreamReader(System.in)
                    ).readLine());
         volume = 4.0f/3.0f * PI * (float) Math.pow(rayon,3);
         System.out.println(volume);
      } catch (Exception e) {
      }
   }
}
Objectifs conceptuels

Un premier vrai programme

Écrire un programme, apprivoiser l'éditeur et les erreurs, de logique ou techniques. Faire la correspondance entre les idées (le pseudocode) et leur actualisation (le code).

Particularités techniques

Les primitives (Lire, Écrire,pour l'affectation)

Expressions artihmétiques (et priorité des opérateurs)

Séquence (se lit de haut en bas, sans sauter d'étapes)

Variables (volume, rayon)

Constantes (PI)

Intrants (rayon)

Extrants ou sortants, selon les choix de dénomination (volume)

Traitement (calcul du volume)

Traduction d'un algorithme de pseudocode à du code dans un langage de programmation (met en relief la différence entre l'algo presque pur et son implémentation, où on trouve plus de cossins techniques)

Déclaration et définition des constantes (mot clé const)

Déclaration des variables avant utilisation

Quelques types (float)

Littéraux (3.14159f, 4.0f, 3.0f)

Lire x devient cin >> x

Écrire x devient cout << x (le endl pour changer de ligne devient du formatage)

x ← y devient x = y

Appel de fonction mathématique (pow()), découlant du constat qu'il n'y a pas d'opérateur d'exponentiation dans le langage.

Pas le droit aux caractères accentués.

Traduction d'un algorithme de pseudocode à du code dans un langage de programmation (met en relief la différence entre l'algo presque pur et son implémentation, où on trouve plus de cossins techniques)

Déclaration et définition des constantes (mot clé const)

Déclaration des variables avant utilisation

Quelques types (float)

Littéraux (3.14159f, 4.0f, 3.0f)

Lire x devient float.Parse(Console.ReadLine())

Écrire x devient Console.Write(x) ou Console.WriteLine(x) selon les besoins.

x ← y devient x = y

Appel de fonction mathématique (Math.pow()), découlant du constat qu'il n'y a pas d'opérateur d'exponentiation dans le langage.

Introduire le transtypage (cast en float).

Voir ce qui sera fait avec la notation . suivant float (invocation de méthode; sans doute présenté comme une recette).

Droit aux caractères accentués.

Traduction d'un algorithme de pseudocode à du code dans un langage de programmation (met en relief la différence entre l'algo presque pur et son implémentation, où on trouve plus de cossins techniques)

Déclaration et définition des constantes (mot clé final)

Déclaration des variables avant utilisation

Quelques types (float)

Littéraux (3.14159f, 4.0f, 3.0f)

Lire x devient... compliqué. Quand j'ai donné une formation de base en Java, j'ai écrit des classes enrobant tout ça et je les ai donné aux étudiant(e)s, mais il fallait qu'elles/ qu'ils prennent l'habitude tout de suite de manipuler leur environnement (copier des .class ou les importer)

Écrire x devient System.out.print(x) ou System.out.println(x) selon les besoins.

x ← y devient x = y

Appel de fonction mathématique (Math.pow()), découlant du constat qu'il n'y a pas d'opérateur d'exponentiation dans le langage.

Introduire le transtypage (cast en float).

Exceptions (mots clés try et catch, mot Exception).

Rôle des accolades (au moins l'effleurer, à cause des exceptions)

Instruction import

Voir ce qui sera fait avec la notation . suivant Float, avec le mot new et avec tout ce bataclan.

Droit aux caractères accentués.

Distinguer float et Float

Remarques

Le vocabulaire de base des programmes les plus simples est contenu dans cet exemple

Constater la différence entre un algorithme, qui fonctionne « dans la tête », et son implémentation. Entre autres, lors d'un premier jet, on peut écrire PI sous la forme 3.14159 (sans suffixe f) et constater un message d'avertissement à la compilation. Aussi, laisser les étudiants écrire 4/3 initialement (division entière) met en relief la précision requise dans l'écriture des programmes.

Constater la différence entre un algorithme, qui fonctionne « dans la tête », et son implémentation. Entre autres, lors d'un premier jet, on peut écrire PI sous la forme 3.14159 (sans suffixe f) et constater un message d'erreur à la compilation. Aussi, laisser les étudiants écrire 4/3 initialement (division entière) met en relief la précision requise dans l'écriture des programmes..

Le choix du type float est volontaire, pour faire ressortir des avertissements (en C++) ou des erreurs, et du fait que le mot float évoque plus clairement l'idée de nombre à virgule flottante que ne le fait le mot double, mais (surtout en Java et en C#) le programme serait plus simple avec des double dû au type de retour de la méthode pow() (ou Pow())

Si un usager entre une valeur non numérique, le résultat affiché sera erroné ou une erreur apparaîtra à l'écran (selon les langages et les implémentations). Habituellement, le traitement des erreurs de domaines (entrer du texte quand ça prend un chiffre, par exemple) sont relégués en session S2, étant plus techniques.

Exercice sur les séquences

Mise en situation : l'énoncé va comme suit : « écrire le pseudocode de l'algorithme permettant de calculer et d'afficher le périmètre d'un triangle rectangle. Pour cela, vous devrez demander à l'utilisateur la longueur de l'hypoténuse ainsi que celle d'un des deux autres côtés (un côté d'un triangle rectangle qui n'est pas son hypoténuse se nomme une cathète). ».

Langage Pseudocode C++ C# Java
Code
Lire cathèteA
Lire hypothénuse
cathèteB ← (hypothénuse^2-cathèteA^2)^(1/2)
périmètre ← hypothénuse + cathèteA + cathèteB
Écrire périmètre
#include <iostream>
#include <cmath>
using namespace std;
int main() {
   float catheteA,
         catheteB,
         hypothenuse,
         perimetre;
   cin >> catheteA;
   cin >> hypothenuse;
   catheteB = sqrt(pow(hypothenuse,2)-
                   pow(cathete,2));
   perimetre = hypothenuse +
               catheteA +
               catheteB;
   cout << perimetre << endl;
}
using System;
namespace PérimètreTriangle
{
   class Program
   {
      static void Main(string [] args)
      {
         float cathèteA,
               cathèteB,
               hypothénuse,
               périmètre;
         cathèteA = float.Parse(Console.ReadLine());
         hypothénuse = float.Parse(Console.ReadLine());
         cathèteB = (float) (Math.Sqrt(Math.Pow(hypothénuse,2)-
                                       Math.Pow(cathèteA,2)));
         périmètre = hypothénuse +
                     cathèteA +
                     cathèteB;
         Console.WriteLine(périmètre);
      }
   }
}
import java.io.*;
public class PérimètreTriangle {
   public static void main(String [] args) {
      try {
         float cathèteA,
               cathèteB,
               hypothénuse,
               périmètre;
         cathèteA = Float.parseFloat(
                    new BufferedReader(
                       new InputStreamReader(System.in)
                    ).readLine());
         hypothénuse = Float.parseFloat(
                    new BufferedReader(
                       new InputStreamReader(System.in)
                    ).readLine());
         cathèteB = (float) Math.sqrt(Math.pow(hypothénuse,2)-
                                      Math.pow(cathèteA,2));
         périmètre = hypothénuse +
                     cathèteA +
                     cathèteB;
         System.out.println(périmètre);
      } catch (Exception e) {
      }
   }
}
Objectifs conceptuels

Séquences, variable intermédiaire, utilisation de fonctions mathématiques. Un peu d'algèbre pour identifier la bonne formule.

Particularités techniques

Variable intermédiaire (cathèteB)

Variable intermédiaire (cathèteB)

Nouvelle fonction mathématique (sqrt())

Variable intermédiaire (cathèteB)

Nouvelle fonction mathématique (Math.Sqrt())

Les méthodes comme Math.Sqrt() et Math.Pow() opèrent sur des double. Affecter la valeur retournée par Math.Sqrt() à un float exige un transtypage (un cast)

Variable intermédiaire (cathèteB)

Nouvelle fonction mathématique (Math.sqrt())

Les méthodes comme Math.sqrt() et Math.pow() opèrent sur des double. Affecter la valeur retournée par Math.sqrt() à un float exige un transtypage (un cast)

Remarques

La difficulté ici porte sur la réflexion algébrique et algorithmique, pas sur les détails de syntaxe. Comme mentionné plus haut, si Java ou C# était choisi comme langage de programmation pour débutants, l'essentiel des calculs seraient probablement faits avec des nombres à double précision, pour alléger l'écriture et réduire les transtypages.

Exercice sur les alternatives

Mise en situation : lire un nombre et afficher un message basé sur le fruit de l'évaluation d'une condition.

Langage Pseudocode C++ C# Java
Code
Lire val
Si val % 2 != 0
   Écrire "Impair"
Sinon
   Écrire "Pair"
#include <iostream>
using namespace std;
int main() {
   int val;
   cin >> val;
   if (val % 2 != 0) {
      cout << val
           << " est impair"
           << endl;
   } else {
      cout << val
           << " est pair"
           << endl;
   }
}
using System;
namespace Impairs
{
   class Program
   {
      static void Main(string [] args)
      {
         int val;
         val = int.Parse(Console.ReadLine());
         if (val %2 != 0)
         {
            Console.WriteLine("{0} est impair", val);
         }
         else
         {
            Console.WriteLine("{0} est pair", val);
         }
      }
   }
}
import java.io.*;
public class Impairs {
   public static void main(String [] args) {
      try {
         int val;
         val = Integer.parseInt(
                    new BufferedReader(
                       new InputStreamReader(System.in)
                    ).readLine());
         if (val % 2 != 0) {
            System.out.println(val + " est impair");
         }
         else {
            System.out.println(val + " est pair");
         }
      } catch (Exception e) {
      }
   }
}
Objectifs conceptuels

Alternatives, indentation, opérateur modulo (reste de la division entière)

Particularités techniques

Structures alternatives (Si et, parfois, Sinon)

Rôle de l'indentation dans la structure d'un programme

Expression du modulo (reste de la division entière), en particulier pour identifier les entiers pairs

Expressions relationnelles (= et !=, mais aussi <, <=, > et >=)

Quelques types (int). Typiquement, on évite de discuter du int avant main() à ce stade.

Opérateur modulo (%)

Opérateurs relationnels (==, !=, <, <=, > et >=).

Prudence avec la distinction entre = (affectation) et == (comparaison)

Si cond devient if (cond)

Sinon devient else

Rôle des accolades

Enchaînement des affichages

Quelques types (int).

Opérateur modulo (%)

Opérateurs relationnels (==, !=, <, <=, > et >=).

Prudence avec la distinction entre = (affectation) et == (comparaison)

Si cond devient if (cond)

Sinon devient else

Rôle des accolades

Affichages complexes (mentionner que la notation est basée zéro).

Quelques types (int).

Opérateur modulo (%)

Opérateurs relationnels (==, !=, <, <=, > et >=).

Prudence avec la distinction entre = (affectation) et == (comparaison)

Si cond devient if (cond)

Sinon devient else

Rôle des accolades

Affichages complexes (les valeurs converties en texte et la concaténation des chaînes de caractères exprimée avec +)

Remarques

Typiquement, on introduit aussi le morphogramme à ce stade pour visualiser la structure de l'algorithme.

Typiquement, on oblige les accolades pour les débutant(e)s, question de réduire les bogues bêtes pendant que la discipline n'est pas encore en place

Plusieurs autres problèmes semblables peuvent être utilisés (calculer et afficher la valeur absolue d'un nombre, identifier les positifs ou les négatifs, indiquer lequel de deux nombres est le plus petit, etc.)

On peut enrichir avec des alternatives imbriquées quand les étudiant(e)s deviennent plus à l'aise.

Suites

Pour les répétitives, je ne pense pas que la situation soit fortement différente d'un langage à l'autre, du moins pas pour les langages dont nous discutons ici. Les formules plus contemporaines (foreach en C#, for(X x : conteneur) en Java, for_each(debut, fin, operation) en C++ 03 et for_each(conteneur, operation) en C++ 11) se ressemblent assez pour que – à mon humble avis – les différences soient surtout idiomatiques. Les boucles while et do sont les mêmes. Outre des trucs mineurs (portée des variables déclarées à même le bloc d'initialisation d'une répétitive for, par exemple), ça se ressemble énormément ici.

Pour KA0, quelles sont les différences clés pour le reste? à mon avis, on parle de ce qui suit (la liste n'est sans doute pas exhaustive).

Thématique Pseudocode C++ C# Java
Travaux pratiques graphiques

Je ne pense pas que ce soit applicable (ou, du moins, que le jeu n'en vaille la chandelle).

Rien de naturel dans la bibliothèque standard. Stroustup, dans Programming, Principles and Practice using C++, fait du graphisme très tôt en utilisant une chic bibliothèque gratuite nommée FLTK, et c'est pas mal propre. Une avenue à considérer?

Sinon, il y a l'approche où les profs font le volet graphique et les étudiant(e)s font le bout procédural qui interagit avec (ce qu'on a fait à quelques reprises).

Autre option : un brin de C++/CLI pour interagir avec le cadriciel .NET, mais on vient alors de quitter les concepts de base pour un dialecte, et ça implique de toucher à des trucs qui ne sont pas traditionnellement vus comme « pour débutant(e)s », par exemple les pointeurs et les références, et beaucoup de syntaxe OO.

Accès au cadriciel .NET, donc c'est assez naturel, mais il faut introduire des éléments conceptuels et techniques qu'on montre traditionnellement dans des cours ultérieurs si on souhaite que les étudiant(e)s fassent la partie graphique et le code sous-jacent.

Accès au cadriciel de Java, donc c'est assez naturel, mais il faut introduire des éléments conceptuels et techniques qu'on montre traditionnellement dans des cours ultérieurs si on souhaite que les étudiant(e)s fassent la partie graphique et le code sous-jacent.

Introduction à l'approche OO

Le pseudocode a été proposé à une époque où le modèle objet n'était pas en vogue, et n'y est pas aussi adapté qu'on le souhaiterait.

Des trois, c'est celui qui ratisse le plus large (de loin), mais je doute qu'on exploite cette facette en première session.

Il est susceptible d'être réinvesti dans les deux branches, mais surtout en informatique industrielle. En informatique de gestion, il est plus probable que C#, Java et les langages orientés vers le Web occupent le haut du pavé.

Clairement applicables et plutôt semblables à bien des égards. Plusieurs comparatifs existent, évidemment : vous pouvez examiner ceci et cela si vous êtes curieuses/ curieux, mais toujours avec un oeil aguerri parce que les auteurs ont pratiquement toujours un biais a priori assez marqué. En particulier, le traitement de documents XML est plus intégré à ces langages qu'à C++, où il faut traditionnellement avoir recours à des bibliothèques de tiers parti.

Entrées/ sorties sur des fichiers

Je ne pense pas que ce soit applicable (ou, du moins, que le jeu n'en vaille la chandelle).

Le plus simple des trois, de beaucoup, parce qu'il évite toute considération en lien avec le traitement des exceptions et toute la logistique qui lui est associée. Par contre, les idiomes de C++ pour les entrées/ sorties sont très différents de ceux de Java et du monde .NET, alors la transition d'un modèle à l'autre peut être difficile.

Globalement, pour les éléments du tableau ci-dessus, une question me semble importante : s'agit-il d'objectifs de KA0? N'oublions pas les compétences à couvrir, soit la 016P, Résoudre des problèmes mathématiques et statistiques en informatique (en partie seulement); la 016S, Exploiter un langage de programmation structurée; et la 016W, Produire des algorithmes.

La discussion que nous avons amorcé il y a quelques années déjà est une discussion qui mérite d'être faite, mais je ne suis pas convaincu qu'il y ait une grande différence de simplicité entre les trois principaux langages examinés pour les éléments de la formation initiale qui, traditionnellement, tombent dans la cour de KA0. Cela dit, peut-être posons-nous mal la question...

Pistes et réflexions

Nous avons jusqu'ici posé la question de la valorisation de la formation initiale aux yeux de nos étudiant(e)s sur la base du choix du langage de programmation utilisé. On peut poursuivre dans cette voie, évidemment, mais (vous le voyez sans doute à partir des exemples ci-dessus) je ne suis pas convaincu que cela soit gagnant en première session (entendons-nous bien sur les termes). Dans la perspective de la première session, toutefois, je pense qu'il y a plusieurs autres pistes de réflexion à explorer.

Peu importe ce que nous ferons, le choix sera départemental.

Donner un virage Web plus rapide

Si notre objectif départemental est d'assurer une meilleure rétention de la clientèle en première session, et si nous estimons que les applications plus graphiques et orientées Web sont le chemin à suivre, il existe des moyens plus légers d'y arriver. Par exemple :

On se rapprocherait de la vocation plus Web, plus près du marché, dans chaque cas. Faudrait par contre voir comment articuler le reste de la formation si on utilise ces outils comme base pour notre formation initiale (car nous allons devoir éventuellement enseigner avec C++, C# et Java, et il faudra faire le pont vers ces langages et leurs modèles respectifs éventuellement).

Repenser le cursus de formation initiale

Notre DEC est présentement novateur en ce sens qu'il pousse l'approche OO dès la deuxième session, et débute une approche en ce sens dès la première session. Nous avons constaté, lors de l'élaboration du programme SIM, à quel point nous étions des moutons noirs à l'échelle du Québec en agissant ainsi, mais je pense que ce cachet est une de nos forces.

Peut-être devrait-on repenser le cursus pour y aller d'une approche OO dès le début? Tant qu'à être radicaux... Cela impliquerait de retravailler la grille et de donner une autre tangente à notre formation de base, mais si nous estimons que cela peut être positif, pourquoi pas? Je pense que si nous allons en ce sens, il faudra par contre repenser l'approche que nous avons traditionnellement appliquée, en ce sens que nous avons (à ma connaissance) construit la pensée structurée d'abord, puis amené la pensée OO comme un raffinement et une élévation conceptuelle de la pensée initiale. Si nous démarrons dès le début avec une pensée OO, la pensée structurée viendra ultérieurement et il faudra faire un pont différent entre les deux paradigmes.

Il faudra aussi, si nous procédons ainsi, réfléchir à ce que nous souhaitons voir apparaître dans la formation initiale (ce sera différent de ce que nous avons fait jusqu'ici). Tout cela indépendamment du langage choisi, d'ailleurs.

Retoucher le cursus de formation initiale

Autre avenue à envisager : changer des éléments seulement de la formation initiale. Par exemple, ne plus aborder les tableaux bruts en première session pour se limiter à des vecteurs standards, et mettre l'accent sur l'utilisation d'abord, pour glisser vers la compréhension par la suite (sessions S2 et S3) et introduire les structures sous-jacentes à ce moment seulement (peut-être avec des bases de C). C'est défendable (en pratique, les tableaux bruts sont beaucoup moins utiles qu'ils ne l'ont déjà été, et sont devenus plus un concept de programmation système qu'un concept de base).

Autre exemple : introduire plus rapidement les constructeurs pour initialiser les enregistrements. Nous avons enseigné, d'aussi loin que je me souvienne, la distinction entre définition et initialisation pour les variables, mais cette distanciation entre les deux n'est plus une pratique aussi saine qu'elle ne l'était auparavant.

Le pseudocode et les morphogrammes ont fait l'objet de discussions par le passé. Clairement, à l'usage, le pseudocode n'est pas une notation qui dépasse bien le stade de la formation vraiment initiale (jusqu'aux fonctions, peut-être, lorsque joint aux diagrammes hiérarchiques). Cela dit, je ne suis pas certain (du tout!) qu'on devrait s'en débarasser, mais il ne faut pas non plus lui accorder plus d'importance qu'il n'en a.

Autre exemple encore : si nous choisissons des langages mettant l'accent sur les outils graphiques, la gestion des événements devient plus importante que les répétitives... Que de réflexions en vue!


Valid XHTML 1.0 Transitional

CSS Valide !