WinDev et le Design pattern : adaptateur

Design pattern de type structure : adaptateur

WinDev est un EDI édité par la société française PC-Soft et conçu pour développer des applications. Il propose son propre langage de programmation : W-langage. Cet EDI offre de nombreux avantages :

  • gestion des événements simplifiée ;
  • fonctions W-langage complètes pour la programmation courante ;
  • réalisation rapide d'interfaces graphiques élégantes ;
  • ...

Cette facilité apportée par WinDev ne doit pas empêcher de structurer un projet et de mettre en place une analyse de conception, en d'autres termes ne pas foncer tête baissée en enquillant les lignes de code. Lors des précédents articles, nous avons vu la mise en place des patrons de conception :

Cet article explique la mise en place d'un Design pattern de type structure : adaptateur (adaptater en anglais).

Commentez Donner une note à l'article (5)

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Définition de design pattern de structure

Image non disponible

Pour commencer, nous allons voir la définition d'un Design Pattern de type structure (source Wikibooks) :

« Un patron de structure permet de résoudre les problèmes liés à la structuration des classes et leur interface en particulier. »

et celle du Design Pattern Adaptateur (source livre : Design Patterns - Tête la première) :

« Le pattern Adaptateur convertit l'interface d'une classe en une autre conforme à celle du client. L'Adaptateur permet à des classes de collaborer, alors qu'elles n'auraient pas pu le faire du fait d'interface incompatible. »

Le pattern adaptateur permet de convertir une interface de classe existante en une interface de classe attendue. Il peut être implémenté dans les cas suivants :

  • intégration d'une classe sans la modifier ;
  • intégration de bibliothèques externes en faisant correspondre la signature de ses fonctions à celles déjà mises en place ;
  • harmonisation/normalisation de l'existant sans modifier tout le code.

L'adaptateur fait correspondre un appel de fonction par le programme client avec la fonction de la classe adaptée. L'implémentation de ce Design Pattern permet d'isoler le programme client des changements de classes adaptées et de faciliter les futures implémentations de classes adaptées.

II. Diagramme UML

Pour continuer un peu dans la théorie, ci-dessous le diagramme UML :

Image non disponible

Le schéma UML suivant utilise deux concepts de la POO :

  • l'héritage : l'adaptateur hérite de l'interface ;dans notre cas ce sera une classe abstraite, les interfaces n'existent pas (encore) en WinDev ;
  • la composition : l'adaptateur est composé de l'adapté.

III. Description du problème

Maintenant que nous avons vu la théorie, place à la pratique. Nous allons prendre l'exemple d'une société 'ZZZ', prestataire de services qui qualifie des fiches clients. Cette société reçoit de ces clients des informations basiques (nom, prénom, date naissance, adresse) sur leur portefeuille client et doit les qualifier. Le but de la société 'ZZZ' est de compléter les renseignements des fiches qui lui sont fournies :

  • situation familiale ;
  • profession ;
  • activités ;
  • vacances ;

Les clients récupèrent des fiches enrichies et peuvent mettre en place des actions commerciales. Au départ, la société 'ZZZ' travaillait pour des PME/PMI et imposait son format d'échange (TXT ou CSV), elle avait développé son module de récupération et d'intégration dans sa base de données. Tout fonctionne dans le meilleur des mondes… jusqu'à une certaine réunion.

Image non disponible

Le responsable et le chef de projet convoquent l'ensemble des équipes pour informer qu'un gros contrat vient d'être signé avec un géant du e-commerce.

Les consignes sont les suivantes :

  • les équipes de 'call ' devront continuer d'effectuer du démarchage téléphonique, mais en affinant le détail des qualifiants ;
  • les équipes de développement doivent mettre en place cette intégration.

Les développeurs sont sereins, le programme est déjà en place, rien à faire …. Mais, car il y a toujours un mais, le chef de projet prend la parole :

« La société nous impose son format de fichier et nous livre un WDL pour lire celui-ci. Nous devons intégrer cette ressource externe sans en modifier l'existant. »

IV. Programmation du design pattern

IV-A. Existant

La société a déjà mis en place plusieurs intégrations de fichier externe avec la conception suivante :

  • une classe abstraite pour définir le comportement des classes filles, elle servira d'interface de programmation ;
  • des classes filles spécifiques à chaque type d'intégration.

IV-A-1. Classe abstraite (Interface de programmation)

Déclaration de la classe ac_ImportCient
Sélectionnez
1.
2.
3.
ac_importClient est une Classe, abstraite
lt_LstClient est un tableau dynamique
FIN

Avec les fonctions suivantes :

Procédure abstraire Rcp_Client
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
// Résumé : Récupère les clients dans le fichier externe. Fonction à redéfinir dans les classes filles
// Syntaxe :
//[ <Résultat> = ] Rcp_Client ()
//
// Paramètres :
//    Aucun
// Valeur de retour :
//     Tableau dynamique : Tableau de clients
//
// Exemple :
// Rcp_Client().
//
PROCEDURE ABSTRAITE Rcp_Client()
procédure InsertBdd
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
// Résumé : Insert dans la Bdd les clients contenus dans le membre lt_LstClient. Fonction factorisée, n'est pas à redéfinir
// Syntaxe :
//[ <Résultat> = ] InsertBdd ()
//
// Paramètres :
//    Aucun
// Valeur de retour :
//     booléen : Faux si erreur, vrai si OK
//
// Exemple :
// InsertBdd()
//
PROCEDURE InsertBdd()

//----->Déclaration des variables    
ls_Masquerequete,ls_requete,ls_nomReq est une chaîne
ls_nomReq="reqInsertClient"
ls_Masquerequete="INSERT INTO Express_client (cli_nomPrenom,cli_dateNaissance,cli_adresse1, cli_adresse2, cli_CP,cli_ville) VALUES ('%1','%2','%3','%4','%5','%6')"

POUR li_i=1 _A_ TableauInfo(:lt_LstClient,tiNombreLignes)
    ls_requete=ChaîneConstruit(ls_Masquerequete,:lt_LstClient[li_i,1],:lt_LstClient[li_i,2],:lt_LstClient[li_i,3],:lt_LstClient[li_i,4],:lt_LstClient[li_i,5],:lt_LstClient[li_i,6])
    SI PAS HExécuteRequêteSQL(ls_nomReq,ls_requete) ALORS
        Erreur(HErreurInfo(hErrComplet))
        RENVOYER Faux
    FIN    
FIN
RENVOYER Vrai

IV-A-2. Importation des fichiers clients

Dans ce paragraphe, nous allons voir le code développé pour intégrer les fichiers de type TXT. La classe pc_ImportTxt gère l'importation d'un fichier texte.

La définition de la classe :

Déclaration de la classe
Sélectionnez
1.
2.
3.
pc_ImportClient_Txt est une Classe
hérite de ac_importClient
FIN

Le constructeur alloue le tableau stockant le contenu du fichier

Constructeur de la classe pc_ImportTexte
Sélectionnez
1.
2.
3.
PROCEDURE Constructeur()

:lt_LstClient=allouer un tableau de 0 par 6 chaîne

La fonction Rcp_Client parcourt le fichier texte et récupère les données en les stockant dans le tableau : lt_LstClient.

Procédure Rcp_Client
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
PROCEDURE Rcp_Client()
//------>Déclaration des variables
ls_ligne est composée de
    ls_nomPrenom est une chaîne fixe de 70
    ls_dateNaissance est une chaîne fixe sur 8
    ls_adresse1 est une chaîne fixe sur 32
    ls_adresse2 est une chaîne fixe sur 32
    ls_CP est une chaîne fixe sur 5
    ls_ville est une chaîne fixe sur 50
FIN
ls_LigneLue est une chaîne
li_fichier est un entier

ls_ligne.ls_nomPrenom=""
ls_ligne.ls_dateNaissance=""
ls_ligne.ls_adresse1=""
ls_ligne.ls_adresse2=""
ls_ligne.ls_CP=""
ls_ligne.ls_ville=""    

li_fichier= fOuvre(".\File_ClientImport.txt",foLecture)
SI li_fichier=-1 ALORS
    Erreur(ErreurInfo(errComplet))
SINON
    ls_LigneLue=fLitLigne(li_fichier)
    TANTQUE ls_LigneLue<>EOT
        ls_ligne=ls_LigneLue
        TableauAjouteLigne(:lt_LstClient,ls_ligne.ls_nomPrenom,ChaîneVersDate(ls_ligne.ls_dateNaissance,"AAAAMMJJ"),ls_ligne.ls_adresse1,ls_ligne.ls_adresse2,ls_ligne.ls_CP,ls_ligne.ls_ville)    
        ls_LigneLue=fLitLigne(li_fichier)
    FIN
FIN

Le principe est le même pour une importation du fichier CSV.

IV-B. Implémentation du WDL

Comme nous l'avons vu dans la description du problème, nous devons intégrer la WDL fournie par le client. Nous avons la description du contenu de celle-ci, une fonction nous intéresse :

  • LectureFichier : retourne un tableau dynamique de sept chaînes renseignées par les informations suivantes :
  • Nom
  • Prenom
  • Adresse 1
  • Adresse 2
  • Code postal
  • Ville
  • Pays

Pour implémenter ce WDL et la fonction, nous allons créer une classe pc_ImportAdapteur. Nous retrouvons les deux notions  :

  • l'héritage : pour que le programme client ne modifie pas ces appels et lui faire croire qu'il communique avec les mêmes objets ;
  • la composition : pour obtenir une référence de l'adaptateur.
Déclaration de la classe pc_ImportAdapteur
Sélectionnez
pc_Importadapteur est une Classe
hérite de ac_importClient
PRIVÉE 
    mo_ImportSociete est un pc_ImportSociete
FIN

Nous définissons le constructeur, celui-ci initialise la référence de l'adaptée.

Constructeur de la classe pc_ImportAdapteur
Sélectionnez
PROCEDURE Constructeur()
:mo_ImportSociete=allouer un pc_ImportSociete()
:lt_LstClient=allouer un tableau de 0 par 6 chaîne

Maintenant, nous devons implémenter la méthode de l'interface.

Procédure Rcp_Client
Sélectionnez
// Redéfinition de la méthode ac_importClient.Rcp_Client
PROCEDURE Rcp_Client()

//----->Déclaration du tableau retourné par la classe à adapter
Lt_LstClientSociete est un tableau de 0 par 7 chaîne
//-----Appel de la procédure de la classe à adapter
Lt_LstClientSociete=mo_ImportSociete:LectureFichier()

//----->Initialisation du tableau à traiter
POUR li_i=1 _A_ TableauInfo(Lt_LstClientSociete,tiNombreLignes)
    TableauAjouteLigne(:lt_LstClient,Lt_LstClientSociete[li_i,1]+" "+Lt_LstClientSociete[li_i,2],"19000101",Lt_LstClientSociete[li_i,3],Lt_LstClientSociete[li_i,4],Lt_LstClientSociete[li_i,5],Lt_LstClientSociete[li_i,6])
FIN

Nous avons terminé la mise en place et le développement de notre adaptateur.

V. Test

Image non disponible

Dans ce paragraphe, nous allons tester ce que nous venons de voir dans les paragraphes précédents.

V-A. Jeux d'essai

Pour tester notre programmation, nous avons en notre possession le dernier fichier de prestataire A au format TXT contenant les informations suivantes :

Nom/prénom

Date de naissance

Adresse 1

Adresse 2

Code postal

Ville

Toto

19820101

1 rue de stade

 

75000

Paris

Tata

19841015

1 rue du stade

 

75000

Paris

Tutu

20101115

1 rue du stade

 

75000

Paris

Titi

20120820

1 rue du stade

 

75000

Paris

et le dernier fichier du prestataire B au format XML

Nom

prénom

Adresse 1

Adresse 2

Code postal

Ville

Pays

Tool

Pere

22 rue de l'église

 

75000

Paris

France

Tool

Mère

22 rue de l'église

 

75000

Paris

France

Tool

Junior

22 rue de l'église

 

75000

Paris

France

Tool

Fille

22 rue de l'église

 

75000

Paris

France

V-B. Programme de test

Les équipes de développement possèdent déjà un programme de tests pour les formats existants.

Programme d'importation
Sélectionnez
//----->Déclaration des variables
Lo_importClient est un ac_importClient dynamique

//----->Allocation du type de variable pour le prestataire A
Lo_importClient=allouer un pc_ImportClient_Txt()
//----->Lecture et récupération du fichier
Lo_importClient:Rcp_Client()
//----->Insertion dans la BDD
Lo_importClient:InsertBdd()

Encore un peu de programmation pour mettre en place l'adaptateur :

Programmation de l'adaptateur
Sélectionnez
Lo_importClient2 est un pc_Importadapteur()
Lo_importClient2:Rcp_Client()
Lo_importClient2:InsertBdd()

Lancez un test, et constatez le contenu de votre fichier de base de données. Ci-dessous la capture d'écran du contenu du fichier client :

Image non disponible

VI. Remerciements

Remerciements :

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2015 v.formet - dsr57. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.