Activité Introduction aux patrons de conception : patrons de création d'objets (partie 3/3)

Objectifs

À la fin de ce travail, vous devez :

  1. Être capable d’expliquer l’utilité des patrons de conception de création (creational design pattern)
  2. Être capable de décrire et de distinguer les patrons de conception de création d’objets :
    • « Static Factory Method »
    • « Abstract Factory »
    • « Builder »

En plus des objectifs principaux ci-dessus, vous devez :

  1. Connaître le principe de masquage de l’information (information hidding).
  2. Connaître les modificateurs public, private et protected pour les membres (attributs et méthodes) d’une classe.
  3. Être capable d’expliquer pourquoi un constructeur n’est jamais virtuel.

Consigne

Pour ce travail on vous demande de prendre connaissance de la situation et de réaliser les tâches proposées. Si vous ne parvenez pas à terminer le travail en classe, il vous appartient de prendre sur votre temps pour l’achever.

Le travail est individuel. Vous pouvez communiquer en respectant le code d’honneur.

Résultat attendu

  • Un projet Maven contenant les classes décrites
  • Un petit document où vous aurez décrit ce que vous avez fait et les difficultés que vous aurez rencontrées.

Ressources

Logiciel :

  • Machine virtuelle de développement
  • Visual Studio Code

Documents :

Situation

Vous êtes développeur dans un projet de gestion de contacts. Lors d’une revue de code, l’un de vos collègues vous fait part de son sentiment que quelque chose cloche avec le design de la figure 1, mais il n’arrive pas immédiatement à voir ce que c’est.

Fig. 1 – Design
Fig. 1 – Design

Dans un premier temps, il suspecte une violation du principe de ségrégation des interfaces pour le type PersonDataMapperFileBase. En effet, les méthodes findAll et findById d’une part et la méthode readFile d’autre part ne sont jamais utilisées ensemble. Vous défendez votre design en disant que la méthode readFile n’est pas publique et n’est visible que par les classes dérivées. Il vous concède que même s’il s’agit tout de même d’une violation du principe, elle ne suffit pas à justifier un changement. Il n’est toutefois toujours pas convaincu et concentre son attention sur les classes dérivées.

Il commence par se demander s’il n’y aurait pas une violation du principe de responsabilité unique. Selon ce principe, une classe ne devrait avoir qu’une seule raison de changer. Mais cela ne tient pas. En effet, les classes PersonDataMapperCsv et PersonDataMapperXml n’ont qu’une seule raison de changer (une modification du format de fichier). La classe PersonDataMapperFileBase n’a également qu’une seule raison de changer (une modification de l’interface PersonDataMapper). Après un moment de réflexion, votre collègue arrive enfin à mettre le doigt sur ce qui ne va pas. Le problème ne vient pas d’une violation des principes SOLID qui sont globalement respectés, mais d’un principe plus fondamental de la programmation orientée objet qui stipule que le couplage entre les modules doit être aussi faible que possible.

Fig. 2 – Builder Pattern (diagramme de classes)
Fig. 2 – Builder Pattern (diagramme de classes)
Fig. 3 – Builder Pattern (diagramme de séquence)
Fig. 3 – Builder Pattern (diagramme de séquence)

Il vous fait remarquer que les classes PersonDataMapperCsv et PersonDataMapperXml n’implémentent que la logique de lecture du contenu des fichiers (parser). Il apparaît donc que la relation de spécialisation/généralisation ne sert qu’à lier le parser au data mapper. Toutefois, avec ce type de relation, la classe de base et les classes dérivées sont très fortement couplées ce qui, dans ce cas, n’est pas souhaitable. Votre collègue vous suggère alors d’utiliser le patron de conception « Builder ».

Fig. 4 – Builder pattern (ConcreteBuilder & Product)
Fig. 4 – Builder pattern (ConcreteBuilder & Product)
Fig. 5 – Builder pattern (Director)
Fig. 5 – Builder pattern (Director)

La figure 6 présente une vue d’ensemble de la version finale du design. Le diagramme de séquence de la figure 7 illustre la création d’un data mapper avec un fichier CSV. Pour du XML, on utilise une instance de la classe PersonListBuilderXml au lieu d’une instance de PersonListBuilderCsv.

Fig. 6 – Vue d'ensemble (diagramme de classes)
Fig. 6 – Vue d'ensemble (diagramme de classes)
Fig. 7 – Vue d'ensemble (diagramme de séquence)
Fig. 7 – Vue d'ensemble (diagramme de séquence)

Mise en route

Faites une copie du projet de l’activité précédente.

Lancez la machine virtuelle de développement avec Vagrant. Lancez Visual Studio Code, connectez-vous à la machine virtuelle et ouvrez la fenêtre de terminal intégré.

Rendez-vous dans le répertoire de projets (~/projects), puis dans le répertoire de votre nouveau projet et lancer la commande code -r . pour l’ouvrir.

Tâches

  1. Modifiez votre code de telle sorte qu’il corresponde aux diagrammes des figures 4 et 5.