mardi 15 mars 2016

Une approche pour le développement des "petits" projets scientifiques (part. 5)

Au sommaire :



Le dernier article était plus proche d'un cours en biologie mais il peut faire sujet d'une bonne adaptation. Je rappelle les deux points à retenir :
  1. La cellule de départ contient toutes les informations nécessaires,
  2. Le principe de spécialisation donne naissance à de nouveaux organes qui se concentrent sur une seule tâche.
Ces deux points peuvent constituer le début d'une approche descendante, rapide, efficace et bien formalisée mais limitée (dans un première temps) à des systèmes de recherche d'une taille relativement réduite.
Nous pouvons proposer l'adapation suivante :
Le développement du système commence par la construction d'un seul programme fonctionnel qui exécute le traitement dans sa forme la plus basique (sans cas d'utilisation et sans données complexes) : le programme en question ne doit pas définir des objets du système ou de créer des modules, mais, il consiste en un traitement de base sans des structures complexes de données. L'élément le plus important est qu'il soit fonctionnel pour le cas choisi. Ce dernier doit être un cas général sans caractéristiques particulières comme il ne doit pas être un cas particulier.
Chaque partie du traitement est reprise dans un "organe" (fonction, objet) créant séparément selon sa spécialisation. A ce niveau, il est possible de se concentrer sur ce nouveau organe et de le raffiner en traitant les cas particuliers. Il est aussi important de penser à ajouter des "organes" pour gérer les entrées et les sorties.
De ce point, nous pouvons penser à plusieurs améliorations possibles telles que :
  1. Affaiblir le couplage en ajoutant des interfaces entre les différents parties du systèmes,
  2. Ajouter un niveau de configuration pour permettre une meilleure gestion du couplage des différentes partie.
Il est clair que ces deux dernières propositions sont déjà présentes dans le domaine informatique et elles sont utilisées par plusieurs technologies présentes sur le marché. Le point que je veut expliquer est qu'il est possible de produire un processus tiré directement du processus biologique mais qui est mieux adapté et plus performant dans le cadre du génie-logiciel.
Il est évident que cette proposition est loin d'être complète, cela pourra prendre un mémoire entier pour présenter les différents aspects théoriques, faire une étude comparative, analyser au mieux le processus biologique pour enfin construire une proposition complète, néanmoins, cela peut être encourageant à utiliser une telle approche simplifiée pour les projets de "petite" taille (cela nécessite aussi une quantification) et d'avoir suffisamment d'arguments en cas où on est amené à défendre un tel choix.
J'insiste, aussi, sur un point très important : cette approche proposée peut apparaître comme un processus évolutif tel que le prototypage, néanmoins, elle est sur un niveau technique contrairement aux notions et aux étapes définies par les processus évolutifs, ces notions que j'ai repris une partie dans les premiers articles de cette série.
Dans le dernier article, je vais donner un exemple en Java qui démontre les concepts présentés dans cette série.
Dans cet article, nous allons essayer de développer un système (si on veut dire) qui calcule la somme de deux entiers (de "petite" taille comme j'ai dit).
Notre objectif principal est de calculer la somme, ainsi, le programme le plus simple commence par l'initialisation de deux variables, calculer la somme et mettre le résultat dans une troisième variable, et enfin, afficher le résultat :



public class CalculerSomme{
 public static void main(String args[]){
  int a = 10;
  int b = 20;
  
  int s = a + b;
  
  System.out.println("La somme est : " + s); 
 } 
}


Nous remarquons que le programme se divise en trois parties principales :
  1. Récupérer les valeurs des paramètres,
  2. Faire le calcul,
  3. Rendre le résultat.
Ainsi, pour une première spécialisation, nous allons créer un objet pour chacune des trois parties.
Les entrées :


import java.util.Scanner;

public class Entree{

 Scanner lectureClavier;
 public Entree(){
  lectureClavier = new Scanner(System.in);
 }
 
 public void chargerParametres(){
  CalculerSomme.a = lectureClavier.nextInt();
  CalculerSomme.b = lectureClavier.nextInt();
 }

}


Les sorties :


public class Sortie{
 public void afficher(String message){
  System.out.println(message);
 }
}



Le calcul :


public class Calculette{
 int a;
 int b;
 int s;
 
 public Calculette(int a, int b){
  this.a = a;
  this.b = b;
 }
 
 public void executer(){
  s = a + b;
 }
 
 public int obtenirResultat(){
  return s;
 }
}



Le programme principal devient plus simple, il devient le contrôleur principal parce qu'en réalité il ne fait que appeler et coordonner entre les autres objets, il n'effectue aucun traitement :


public class CalculerSomme{
 
 public static Entree e;
 public static Sortie s;
 public static Calculette c;
 
 // Les paramètres
 public static int a;
 public static int b;
 
 public static void main(String args[]){
  e = new Entree();
  s = new Sortie();
  
  e.chargerParametres();
  
  c = new Calculette(a, b);
  c.executer();  
  
  s.afficher("Le résultat est : " + c.obtenirResultat());
 }
}



C'était l'idée de base, mais nous pouvons continuer plus loins : pourquoi ne pas ajouter des interfaces. La déclaration des différents objets utilise les interfaces et non pas les noms des classes directement, tout le reste (instantiation et appel :
Interface pour sortie :


public interface ISortie{
 public void afficher(String message);
}


Interface pour entrée :


public interface IEntree{
 public void chargerParametres();
}


Interface pour Calculette :


public interface ICalculette{
 public void executer();
 public int obtenirResultat();
}


La déclaration dans le programme principal :


public static IEntree e;
 public static ISortie s;
 public static ICalculette c;


Un faible couplage nous permet d'étendre facilement notre système en proposant différents "organes" pour la même fonctionnalité. Pour notre exemple, nous allons ajouter deux classes de sortie et d'entrée qui respectent les interface définies et qui sont dotées d'une interface graphique :
La fenêtre d'entrée :


Le message de sortie :



Le programme principal se dote d'une configuration pour les différents cas possibles : exécuter dans la ligne de commande et exécuter en utilisant l'interface graphique.

A la fin de cet exemple, je veux insister sur quelques points :
J'ai pas gardé l'appellation standard en Java (set, get, etc.), j'ai  voulu garder tout le contenu dans une seule langue,
Il est claire qu'il est possible d'optimiser mieux le code source ou le passage de paramètres; cet exemple est pour illustrer l'idée, ainsi, j'essaie d'oublier que je travaille sur un A+B et d'imaginer que le nombre de paramètres et un peu plus grand,
La proposition faite est loin d'être complète : le passage de paramètres et des messages n'est pas bien défini.

(Pour plus d'informations sur l'auteur et le blog, c'est par ici)

Aucun commentaire:

Enregistrer un commentaire