Paradigme – Le procédural et modulaire

Derrière le terme procédural, se cache simplement la notion de fonction, de procédure, de routine. Cela va nous permettre de créer des blocs de code réutilisables et de faire une croix sur le goto afin d’éviter de faire de la programmation trop spaghetti.

Il est bon de savoir que le paradigme procédural est un sous ensemble du paradigme impératif et fait partie intégrante de la programmation structurée. Mince ça fait mal ça…

Quelques définitions

Nous allons décrire quelques définition pour mieux comprendre de bout en bout le paradigme procédural et comment il s’intègre en Javascript par apport à C ou C++. Même si vous l’utilisez tous les jours, il est bon de faire un petit rappel pour remettre les idées en place.

Programmation structurée

Le but de la programmation structurée est d’améliorer la lisibilité, la qualité et le contrôle d’un code source. Au sein de la programmation structuré on retrouve les structures de contrôles classiques comme le for, le if, le while, etc. Si ces notions vous paraissent familières, elle n’est pas forcément présente dans tout les langages de programmation. La programmation structurée est aussi une méthodologie visant à la transmission de meilleures pratiques de développement. Ces méthodes vont de la décomposition des tâches à accomplir en petit blocs éventuellement réutilisables mais surtout facilement compréhensible. Prévenir les effets de bords en évitant l’utilisation de variables globales, limiter la taille d’une routine ou d’un module…

Routine

Une routine est une encapsulation de code source (un bloc de code), avec éventuellement un certain nombre de paramètres en entré, chargé d’effectuer une action particulière grâce à l’exécution d’une séquence d’instructions. Une routine suit donc le paradigme impératif. Elle peut ainsi être utilisée plusieurs fois au sein d’un programme d’un autre programme ou même parfois être utilisée au sein d’une autre routine. Pour faire simple, une routine est ce qu’on appelle un sous programme. Les routines se décomposent en deux sous ensembles, les procédures et les fonctions.

Procédure

Une procédure est une forme de routine qui ne retourne pas de valeur. Elle sert donc à exécuter une ou plusieurs tâches. Sous la forme de programmation orientée objet on appelle la procédure, une méthode.

En JavaScript la procédure, comme la fonction, se détermine à partir du mot-clé function. Il s’agit donc simplement d’une fonction qui ne retourne rien.

function displayAdd(a, b)
{
    console.log(a+b);
}

En C et C++ la procédure est aussi une fonction qui ne retourne rien, plus précisément void :

void displayAdd(int a, int b)
{
    printf("%i",a+b);
}

Fonction

Une fonction est une forme de routine qui retourne une valeur. Elle sert donc généralement à calculer une valeur dépendante aux paramètres d’entré (généralement). Elle peut tout comme une procédure exécuter une ou plusieurs tâches, en déduire des valeurs, ou tout simplement en déduire si la tâche à réussi ou non.

En javascript la définition reste la même que pour une procédure, par contre on retrouve le mot-clé return dans le corps de la fonction.

function add(a, b)
{
    return a + b;
}

En C et C++ la signature diffère de celle de la procédure car le type de retour doit être renseigné :

int add(int a, int b)
{
    return a + b;
}

Récursivité

Une routine en son sein, peut s’appeler elle-même, dans ce cas on parle de récursivité. La récursivité a la propriété intéressante de pouvoir à la fois décrire un traitement itératif en quelques lignes seulement mais surtout de permettre des parcours de graphes.

Parcours itératif par récursivité

Par exemple on peut trouver facilement par récursivité la factorielle d’un nombre. Cette approche récursive, peut être traité par une simple boucle, c’est pour cette raison qu’on appelle cela un parcours itératif par récursivité.

function factorial(n)
{
  if (n > 1)
    return n*factorial(n-1);
  else
    return 1;
}

factorial(5); // Affiche 120

On retrouve le même résultat itérativement :

function factorial(n)
{
    var fact = 1;
    for (var i = 2; i < n + 1; i++)
        fact *= i;
    return fact;
}

factorial(5) ; // Affiche 120

Parcours de graphe

La récursion trouve vraiment sa place dans le parcours de graphes, qui est plus facile à implémenter que la manière itérative avec une pile (avis personnel).

function traverse(node)
{
    console.log(node.value);
    if (node.children === undefined)
        return;

    for (var i = 0; i < node.children.length; i++)
    {
        var child = node.children[i];
        traverse(child);
    }

    var graph = 
    {
        "value":"bobo",
        "children":[{
            "value":"child1",
            "children":[{
                "value":"child3"
            }],
            "value":"child2"
        }]
    }
}

traverse(graph); // Affiche "bobo", "child1", "child3", "child2"

Au sein du paradigme procédural rien n’empêche l’introduction d’effet de bord par l’utilisation de variable extérieures à la procédure (variable globales par exemple). On essaye cependant de limiter les effets de bord au sein du module ou sont implémentés les procédures pour éviter des effets indésirable lors de l’utilisation de ces modules dans un autre projet.

Le procédural étends la notion de portée des variables. La portée (scope), pour faire simple, c’est le contexte ou une variable est accessible. Par exemple, selon le design du langage, une variable déclarée dans une procédure peut-être accessible ou non en dehors de cette procédure.

Exemple Python:

def my_function():
    a = 10
    print(a)

my_function()
print(a)

Sortie :
10
Traceback (most recent call last):
  File "C:/Users/me/Desktop/test.py", line 6, in <module>
    print(a)
NameError: name 'a' is not defined

On remarque que la variable a est accessible dans my_function car la sortie affiche 10. Cependant elle est inaccessible en dehors, on obtient une magnifique erreur.

Le paradigme modulaire

Premier pas vers la programmation orientée objet, la programmation modulaire permet de regrouper un ensemble de routines au sein d’un bloc – le module – qui aura pour but de traiter une fonctionnalité précise. Le paradigme modulaire s’inscrit dans la programmation structurée car il permet de découper le code source d’un programme à un niveau supérieur et permet la ré-utilisabilité de ce code par d’autres applications.

Ce découpage permet aussi un travail en équipe plus aisé, chacun peut travailler sur son module. De plus, les modules peuvent être vus comme des boites noires à qui on fourni une entrée pour obtenir une sortie sans forcément connaitre comment le résultat est calculé.

Le paradigme modulaire est un premier pas vers le paradigme objet (programmation orientée objet dit aussi POO) ou les modules sont généralement remplacé par des classes. Il fait aussi apparaitre la notion de visibilité qui permet de déterminer si une procédure est accessible à l’extérieur du module (publique) ou uniquement à l’intérieur (privée). Le principe de portée des variables est aussi étendu au module.

Bien que ce paradigme soit accessible dans de nombreux langages non objets, on retrouve celui-ci dans la POO. Dans ce cas un module est généralement implémenté grâce à la création de classes statiques. Bien sûr en POO ce paradigme est poussé encore plus loin que le simple fait de regrouper un ensemble de fonctionnalités sous un même module.

Ainsi la manière la plus simple d’implémenter un module C / C++, sera de créer un fichier .c et un fichier .h contenant un ensemble de routines et de variables publiquement accessibles. Ce « module » sera ainsi accessible par le biais de son inclusion.

Avec JavaScript la constitution d’un module peut se faire par l’encapsulation du code source au sein d’une fonction immédiate (une fonction déclarée et directement appelée). Cette encapsulation permet de séparer les fonctions publiques de celles privées et compacte le tout dans un module utilisable [2].

Exemple de module en JavaScript :

// Fonction immédiate qui sert à représenter un module
var module = (function() {

    var self = {};

    // Déclaration attaché à la fonction immédiate module grâce à self
    self.version = function()
    {
        console.log('version du module 1.0');
    }

    // Notez la différence de déclaration avec le mot-clé var
    var privateFunction = function()
    {
        console.log('this is private');
    }

    return self;
})();

module.version(); // Affiche : version du module 1.0
module.privateFunction(); // TypeError : module.privateFunction is not a function

Ceci est bien sûr à prendre à titre d’exemple, car la définition de module peut-être implémenté sous d’autres formes en Javascript.

Pour conclure, on peut voir le paradigme modulaire comme un sur-ensemble de la programmation procédurale faisant partie de la programmation structurée.


Laisser un commentaire