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)▲
2.
3.
ac_importClient est
une
Classe
,
abstraite
lt_LstClient est
un
tableau
dynamique
FIN
Avec les fonctions suivantes :
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()
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 :
2.
3.
pc_ImportClient_Txt est
une
Classe
hérite
de
ac_importClient
FIN
Le constructeur alloue le tableau stockant le contenu du fichier
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.
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.
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.
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.
// 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.
//----->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 :
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 : djibrildjibril & deepindeepin