WinDev et le Design pattern : adaptateur

Design pattern de type structure : adaptateur

v.formet

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 :

- singleton (création) ;

- stratégie (comportement).

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

Commentez

- Titre : WinDev et le Design pattern : adaptateur

- Auteur : v.formet

- Parution : 3 avril 2015

- Licence : 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.

Sommaire

- I. Définition de design pattern de structure

- II. Diagramme UML

- III. Description du problème

- IV. Programmation du design pattern

- IV-A. Existant

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

- IV-A-2. Importation des fichiers clients

- IV-B. Implémentation du WDL

- V. Test

- V-A. Jeux d'essai

- V-B. Programme de test

- VI. Remerciements

I - Définition de design pattern de structure

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 :

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.

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

1. ac_importClient est une Classe, abstraite

2. lt_LstClient est un tableau dynamique

3. FIN

Avec les fonctions suivantes :

Procédure abstraire Rcp_Client

1. // Résumé : Récupère les clients dans le fichier externe. Fonction à redéfinir dans les classes filles

2. // Syntaxe :

3. //[ <Résultat> = ] Rcp_Client ()

4. //

5. // Paramètres :

6. //    Aucun

7. // Valeur de retour :

8. //     Tableau dynamique : Tableau de clients

9. //

10. // Exemple :

11. // Rcp_Client().

12. //

13. PROCEDURE ABSTRAITE Rcp_Client()

procédure InsertBdd

1. // Résumé : Insert dans la Bdd les clients contenus dans le membre lt_LstClient. Fonction factorisée, n'est pas à redéfinir

2. // Syntaxe :

3. //[ <Résultat> = ] InsertBdd ()

4. //

5. // Paramètres :

6. //    Aucun

7. // Valeur de retour :

8. //     booléen : Faux si erreur, vrai si OK

9. //

10. // Exemple :

11. // InsertBdd()

12. //

13. PROCEDURE InsertBdd()

15. //----->Déclaration des variables

16. ls_Masquerequete,ls_requete,ls_nomReq est une chaîne

17. ls_nomReq="reqInsertClient"

18. 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')"

20. POUR li_i=1 _A_ TableauInfo(:lt_LstClient,tiNombreLignes)

21. 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])

22. SI PAS HExécuteRequêteSQL(ls_nomReq,ls_requete) ALORS

23. Erreur(HErreurInfo(hErrComplet))

24. RENVOYER Faux

25. FIN

26. FIN

27. 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

1. pc_ImportClient_Txt est une Classe

2. hérite de ac_importClient

3. FIN

Le constructeur alloue le tableau stockant le contenu du fichier

Constructeur de la classe pc_ImportTexte

1. PROCEDURE Constructeur()

3. :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

1. PROCEDURE Rcp_Client()

2. //------>Déclaration des variables

3. ls_ligne est composée de

4. ls_nomPrenom est une chaîne fixe de 70

5. ls_dateNaissance est une chaîne fixe sur 8

6. ls_adresse1 est une chaîne fixe sur 32

7. ls_adresse2 est une chaîne fixe sur 32

8. ls_CP est une chaîne fixe sur 5

9. ls_ville est une chaîne fixe sur 50

10. FIN

11. ls_LigneLue est une chaîne

12. li_fichier est un entier

14. ls_ligne.ls_nomPrenom=""

15. ls_ligne.ls_dateNaissance=""

16. ls_ligne.ls_adresse1=""

17. ls_ligne.ls_adresse2=""

18. ls_ligne.ls_CP=""

19. ls_ligne.ls_ville=""

21. li_fichier= fOuvre(".\File_ClientImport.txt",foLecture)

22. SI li_fichier=-1 ALORS

23. Erreur(ErreurInfo(errComplet))

24. SINON

25. ls_LigneLue=fLitLigne(li_fichier)

26. TANTQUE ls_LigneLue<>EOT

27. ls_ligne=ls_LigneLue

28. 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)

29. ls_LigneLue=fLitLigne(li_fichier)

30. FIN

31. 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

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

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

// 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

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

//----->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

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 :

VI - Remerciements

Remerciements :

- relecture technique : LittleWhite;

- relecture orthographique : ced ;

- vérification avant mise en ligne : djibril & deepin