Paradigme – Le procédural et modulaire

Derrière le terme procédural, se cache simplement ce qu’on appelle fonctionprocédure et routine. Ces outils nous permettent de créer des blocs de code réutilisables.

Le paradigme procédural est un sous ensemble du paradigme impératif et fait partie intégrante de la programmation structurée.

Éléments clés

Programmation structurée

Comme décris en introduction, le procédural fait partie intégrante de la programmation structurée. Le but de la programmation structurée est d’améliorer la qualité d’un code source : sa lisibilité, sa maintenabilité et sa flexibilité. Au sein de la programmation structurée on retrouve les structures de contrôles classiques comme le for, le if, le while, etc. Si ces notions peuvent vous paraître familières, sachez qu’elles ne sont pas forcément présentes 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 ont pour but la décomposition des tâches à accomplir en petit blocs facilement compréhensibles et éventuellement réutilisables. Cela permet de prévenir les effets de bords indésirables, 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ée d’effectuer un traitement particulier en suivant l’exécution d’une séquence d’instructions. Une routine suit donc le paradigme impératif. Elle peut être utilisée plusieurs fois au sein du programme où elle a été définie, d’un autre programme ou même 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. Notez qu’en programmation orientée objet, on appelle une routine, une méthode.

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.

JavaScript

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); 
}

C / C++

En C et C++ la procédure est aussi une fonction qui ne retourne rien, plus précisément, elle retourne 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 à partir des paramètres qu’elle reçoit en entrée. 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 a réussit 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.

JavaScript

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

C / C++

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 sans utiliser explicitement une pile. Certains langages utilisent exclusivement la récursivité comme moyen pour effectuer des traitements en boucle (par exemple haskell, un langage fonctionnel pur). C’est pour cette raison que je vous disais plus haut que les structures de contrôle qui vous sont si familières ne sont pas forcément présentes partout.

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ée 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'effets de bord par l'utilisation de variables extérieures à la procédure (variables 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ésirables 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 
    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 de granularité supérieur et permet la ré-utilisation 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. On leur donne une entrée pour obtenir une sortie sans forcément connaitre comment le résultat est calculé.

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 si la POO intégre ce paradigme, il est beaucoup plus vaste est complet que celui-ci.

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.

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ée 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

%d blogueurs aiment cette page :