Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Design Patterns Discussion :

Question Basic: FACTORY


Sujet :

Design Patterns

  1. #1
    Futur Membre du Club
    Question Basic: FACTORY
    Hello à tous,

    Ma question est la suivante:


    J'ai ma classe Abstraite AAA qui est la Class Mère des Class BBB et CCC.


    - La classe AAA possède sa 1 méthode abstraite de création d'instance.

    - La classe BBB possède 50 méthodes + 1 méthode héritée de AAA.

    - La classe CCC possède 70 méthodes + 1 méthode héritée de AAA.


    Ensuite:

    - La classe BBB est instancié et est de type AAA.

    - La classe CCC est instancié et est de type AAA.



    QUESTION:


    Comment faire pour utiliser les méthodes de la Class BBB et de CCC sachant que ces dernières, sont toutes deux, de type de AAA et sans être contraint de créer 120 méthodes abstraites (50 de BBB + 70 de CCC) dans la classe Mère et les redéfinir dans les class filles pour les réutiliser...


    Merci à tous.
    Cdlt.

  2. #2
    Membre émérite
    Bonjour,

    Conceptuellement, une classe abstraite représente un contrat minimum que toutes ses classes dérivées doivent honorer (implémenter). Si du code client a une référence à un objet du type abstrait A, ce code ignore totalement s'il s'agit d'un B ou d'un C en réalité. Il ne peut compter que sur ce qui est fourni par le contrat de A.

    C'est la définition même de l'abstraction et ce qui fait tout l'intérêt de la chose : on se débarrasse des détails d'implémentation non pertinents pour ne manipuler que l'essentiel, le concept. Dans ce cadre, les 50 méthodes spécifiques à B et les 70 méthodes spécifiques à C sont tout simplement hors-sujet puisqu'elles ne font pas partie du contrat exposé par un A.

  3. #3
    Futur Membre du Club
    Citation Envoyé par Luckyluke34 Voir le message
    Bonjour,

    Dans ce cadre, les 50 méthodes spécifiques à B et les 70 méthodes spécifiques à C sont tout simplement hors-sujet puisqu'elles ne font pas partie du contrat exposé par un A.
    Bonjour Lucky,

    Merci pour cette réponse... 'folklorique'. En faite, l'implémentation ne concerne pas simplement A,B et C mais une cinquantaine de classe au travers d'une centaine de programmes pour un projet d'implementation...

    Mais, je ne manquerais de signaler au Responsable de projet lors du prochain atelier de conception, que les futurs méthodes de ces classes sont... hmm... tout simplement "Hors-Sujettes du contrat exposé par A"...

    Cdlt.

  4. #4
    Modérateur

    Bonsoir,

    'folklorique'... mais non moins tout à fait juste.

    Si les 50 méthodes spécifiques à B, 70 méthodes spécifiques à C, et ainsi de suite pour les autres classes n'ont absolument rien en commun, est-il vraiment justifié de vouloir réunir toutes ces classes au sein d'une même base ?
    À vouloir faire cela, on s'attendrait à ce que toutes ces classes dérivées fournissent un minimum de services communs, services qu'exposerait alors la classe A de base; et non des services totalement différents les uns des autres.

    Selon ce que tu souhaites faire, je pense que tu pourrais fournir un petit nombre de méthodes communes de base qui seraient surchargées dans tes classes dérivées pour utiliser les services spécifiques.

    Mais la première question à se poser est de savoir quel services communs doivent rendrent chacune de ces classes ? Si la réponse est "aucun", alors l'héritage n'a aucune raison d'être.
    Avant de poser votre question : FAQ, Tutoriels et recherche sur le forum
    Une erreur ? Messages d'erreur et avertissements
    "Ça ne marche pas" n'apporte aucune information utile permettant de vous aider. Expliquez clairement votre problème (erreurs entières, résultat souhaité vs obtenu...).
    En essayant continuellement on finit par réussir. Donc: plus ça rate, plus on a de chance que ça marche. - Jacques Rouxel
    L'expérience, c'est le nom que chacun donne à ses erreurs - Oscar Wilde
    Mes extensions FireDVP (Firefox), ChroDVP (Chrome) : suivi des nouveaux messages, boutons/raccourcis et bien plus !

  5. #5
    Futur Membre du Club
    Bonjour,

    Si les 50 méthodes spécifiques à B, 70 méthodes spécifiques à C, et ainsi de suite pour les autres classes n'ont absolument rien en commun, est-il vraiment justifié de vouloir réunir toutes ces classes au sein d'une même base ?
    En faite, le but de la Factory est de centraliser le processus d'instanciation en un seul endroit. Donc, je pars du principe que ce processus est indépendant de l'utilisation à venir des classes (point commun, regroupage de méthodes etc.). La Factory n'est pas concerné et n'a pas à se soucier de "comment seront utiliser les instances et leurs liens entre elles".

    PRINCIPE: "Je lui demande de m'instancier une classe, elle s'exécute et instancie. Point".

    C'est le principe des Pattern Créationnel si l'on veut respecter le Single Responsibility Principle (SRP). Ce que nous nous efforçons d'appliquer malgré les difficultés de conception.


    Mais la première question à se poser est de savoir quel services communs doivent rendrent chacune de ces classes ?
    Comme expliqué précédemment et dis-moi si je me trompe, le Pattern Factory n'a pas cette vocation à se poser cette question. Lui, il ne s'occupe que de renvoyer ce qu'on lui demande.

    Finalement,
    en ce qui concerne mon besoin, j'ai l'impression que ma question reste ... extraordinaire un genre de 'jamais-vu' ...

    Pourtant, si l'on part du principe SRP en ce qui concerne le Factory en mode Production avec la volonté de centraliser la globalité des instanciations, je ne vois rien de déconnant. Ma Factory doit être capable de m'instancier n'importe quelle Classe demandée de type implicite Mère et de méthodes explicite Fille. Sinon, toutes les filles auront dans leurs appels, toutes les mêmes méthodes accessibles ... Ce n'est pas envisageable.

    SOLUTION(à moi ) :

    Pour faire fonctionner ce principe, je suis passé par un Adaptateur d'Interfaces. qui me permet de faire appels aux méthodes d'une Classe spécifique alors que son type ne le permettrait d'apparence pas.


    Etant donné le peu de réponse à ce sujet, je ne peux malheureusement pas confronter ma solution aux autres alternatives des autres développeurs...

    Mais si vous avez des remarques sur le principe, n'hésitez surtout pas.

    Bonne journée.
    R.

  6. #6
    Membre émérite
    Citation Envoyé par Letranger31 Voir le message
    Donc, je pars du principe que ce processus est indépendant de l'utilisation à venir des classes (point commun, regroupage de méthodes etc.). La Factory n'est pas concerné et n'a pas à se soucier de "comment seront utiliser les instances et leurs liens entre elles".
    Tu peux détailler un peu plus précisément la forme que prend ta Factory et par qui elle est utilisée ? Est-ce une Factory simple ? Une Abstract Factory ? Une Factory Method ? Si tu relis ton premier post, la présence d'une Factory n'est pas évoquée ailleurs que dans le titre, ce qui ne facilite pas la compréhension du problème.

    Citation Envoyé par Letranger31 Voir le message
    C'est le principe des Pattern Créationnel si l'on veut respecter le Single Responsibility Principle (SRP). Ce que nous nous efforçons d'appliquer malgré les difficultés de conception.
    Des classes comportant 50 ou 70 méthodes publiques, un arbre d'héritage d'une cinquantaine de classes... Sans avoir vu le code réel je peux me tromper, mais a priori la modélisation actuelle n'est déjà pas la meilleure façon de respecter SRP C'est bien de vouloir découpler la création d'un objet de l'objet lui-même, surtout si elle est complexe, mais il y a d'autres responsabilités à séparer avant.

    Citation Envoyé par Letranger31 Voir le message
    en ce qui concerne mon besoin, j'ai l'impression que ma question reste ... extraordinaire un genre de 'jamais-vu' ...
    Jamais vu ou tout simplement n'ayant pas de sens dans la cadre de la technique de développement évoquée... Il est difficile d'y répondre car c'est comme si tu nous demandais quelle est la bonne manière d'enfoncer un clou à l'aide d'une tronçonneuse. Une Factory n'a jamais été faite pour l'utilisation que tu évoques.

    Citation Envoyé par Letranger31 Voir le message
    Ma Factory doit être capable de m'instancier n'importe quelle Classe demandée de type implicite Mère et de méthodes explicite Fille. Sinon, toutes les filles auront dans leurs appels, toutes les mêmes méthodes accessibles ... Ce n'est pas envisageable.
    Non. Encore une fois, dans les langages à typage statique il n'est simplement pas possible de voir une instance d'une superclasse comme une instance de sa sous-classe, à moins de la caster ce qui n'est en général pas une très bonne idée. Ce n'est pas et n'a jamais été le but d'une (Abstract) Factory de créer un objet d'un type abstrait et de pouvoir ensuite magiquement connaitre et utiliser des fonctionnalités spécifiques à son type concret réel. Si un code client veut utiliser des méthodes présentes uniquement dans X, il doit avoir une référence à un objet de type X, point-barre.

    Maintenant, si tu décris ton contexte un peu plus précisément, avec des exemples concrets de ce que tu souhaites faire, il y a sûrement un autre prisme par lequel on peut aborder le problème qui serait plus pertinent que cette hiérarchie de classes visiblement mal adaptée à l'utilisation voulue.

  7. #7
    Futur Membre du Club
    Bonjour Messieurs,

    Pour faire suite:


    Maintenant, si tu décris ton contexte un peu plus précisément, avec des exemples concrets de ce que tu souhaites faire, il y a sûrement un autre prisme par lequel on peut aborder le problème qui serait plus pertinent que cette hiérarchie de classes visiblement mal adaptée à l'utilisation voulue.
    voilà en somme, la vulgarisation du Landscape de l'implémentation que j'essaie de mettre en place. Les programmes sont totalement indépendants les uns des autres, sans aucune relation entre eux. Le seul lien implicite serait la Factory commune à toute la suite de programme de la même manière que l'est, la Base de données pour les programmes.


    C'est dans ce cadre, que j'aimerais centraliser/globaliser la création d'instance dans tous le package du projet. Une seule Factory pour l'ensemble de TOUS les programmes.

    Cdlt.
    R.

  8. #8
    Membre émérite
    Citation Envoyé par Letranger31 Voir le message
    Le seul lien implicite serait la Factory commune à toute la suite de programme
    Et, très concrètement, que fait cette Factory ?

    En général quand on crée une couche transversale comme celle-là (a fortiori mutualisée entre plusieurs applications), c'est pour factoriser, en un point central, du code qui aurait été dupliqué dans chacune des applications sinon. Quel est ce code ?

  9. #9
    Futur Membre du Club
    Citation Envoyé par Luckyluke34 Voir le message
    Et, très concrètement, que fait cette Factory ?
    Elle instancie.

    Citation Envoyé par Luckyluke34 Voir le message

    En général quand on crée une couche transversale comme celle-là (a fortiori mutualisée entre plusieurs applications), c'est pour factoriser, en un point central, du code qui aurait été dupliqué dans chacune des applications sinon. Quel est ce code ?
    Exactement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      FIELD-SYMBOLS <fs_ofactory> TYPE any.
    
      ASSIGN (classname)          TO   <fs_ofactory>  .
      CHECK  <fs_ofactory>        IS    ASSIGNED      .
      CREATE OBJECT object TYPE (classname)           .
    Bonne journée.
    Cdlt.

    R.

  10. #10
    Membre émérite
    Honnêtement, je ne vois pas la plus-value de la Factory pour ça. Je ne lis pas ce langage (ABAP ?) couramment mais il me semble que classname va changer selon les cas. Il n'y a pas de factorisation ici.

    Pourquoi ne pas instancier directement un objet du bon type ? Ca revient à utiliser juste la ligne 5 : CREATE OBJECT object TYPE <le_type_dont_on_a_besoin> au lieu de s'arracher les cheveux avec une Factory qui retourne un objet d'un type trop générique...

  11. #11
    Futur Membre du Club
    Citation Envoyé par Luckyluke34 Voir le message

    Pourquoi ne pas instancier directement un objet du bon type ? Ca revient à utiliser juste la ligne 5 : CREATE OBJECT object TYPE <le_type_dont_on_a_besoin> au lieu de s'arracher les cheveux avec une Factory qui retourne un objet d'un type trop générique...
    En faite, le coeur de La Factory en JAVA est de cette forme:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    switch (typeProduit) {
               case TYPE_PRODUITA1:
                        produitA = new ProduitA1();
                        break;
               case TYPE_PRODUITA2:
                        produitA = new ProduitA2();
                        break;
               default:
    throw new IllegalArgumentException("Type de produit inconnu");
    }
    Si tu as 50 Classes, en JAVA tu auras 50 Case. En ABAP, il te le fait en une ligne par référence ...

    Citation Envoyé par Luckyluke34 Voir le message
    Honnêtement, je ne vois pas la plus-value de la Factory pour ça. Je ne lis pas ce langage (ABAP ?) couramment mais il me semble que classname va changer selon les cas. Il n'y a pas de factorisation ici.

    Pas faux...

    Mais dans ce cas là, d'ordre général on peut en dire autant de la Factory. Cela sert à quoi de centraliser les instanciations au travers d'une Factory alors que la création d'une instance ne prend que 2 ou 3 lignes ?

    Et cela sert à quoi aussi, d'implémenter une MVC et faire que l'IHM passe par le Controler, qui lui appel la DAO qui elle requête en Base et qui renvoie l'info à la DAO qui remonte l'info pour le Controler qui lui renvoie l'info à l'IHM ? alors que l'on peut tout simplement requêter directement dans en base en Direct oneShot ?



    Citation Envoyé par Luckyluke34 Voir le message
    ...ce langage (ABAP ?)
    oui.

  12. #12
    Membre émérite
    Citation Envoyé par Letranger31 Voir le message
    Mais dans ce cas là, d'ordre général on peut en dire autant de la Factory. Cela sert à quoi de centraliser les instanciations au travers d'une Factory alors que la création d'une instance ne prend que 2 ou 3 lignes ?
    1/ Le pattern Factory (issu de Domain Driven Design, et son proche équivalent le pattern Builder) permet d'encapsuler la logique complexe de création d'un objet, souvent quand il faut faire de l'assemblage à partir de multiples valeurs ou qu'il y a de la logique de validation lors de la création. Ce pattern est utile à partir d'un certain seuil de complexité d'instanciation d'un objet, en-dessous de ce seuil, et c'est très courant, on ne considère pas qu'instancier cet objet est une responsabilité suffisante pour l'extraire dans une classe séparée - un simple constructeur dans la classe en question fait parfaitement l'affaire.

    2/ Les patterns Abstract Factory et Factory Method, sont comme je le disais des patterns d'abstraction. Je ne crée plus l'objet X, quelqu'un d'autre le crée pour moi, et je ne connais même pas son sous-type réel.

    Exemple très pratique : une factory de formes géométriques. L'objet Pointeur (dans un logiciel de dessin par exemple) a une référence à une ShapeFactory abstraite, et au runtime on (un autre objet) va lui passer alternativement une CircleFactory, une RectangleFactory, etc. selon ce qui a été sélectionné dans la boite à outils par l'utilisateur. A chaque fois que l'utilisateur clique dans le canevas, le Pointeur va demander à la factory d'instancier une nouvelle forme géométrique, en passant en paramètre la position actuelle du pointeur. Puis il pourra par exemple demander à cette forme de se dessiner en appelant sa méthode Draw() partagée par toutes les formes. A aucun moment l'objet Pointeur n'a de connaissance ni du type concret de la Factory, ni du type de Forme concret qu'elle génère pour lui et sur lequel il agit.

    Bénéfices :
    • On peut ajouter un nouveau type de forme au programme sans toucher à la classe Pointeur
    • Les responsabilités sont découplées et plus claires, le code est plus lisible et la source d'éventuels bugs plus facilement identifiable
    • L'ensemble est plus facilement testable, par exemple en substituant une fausse Factory à la ShapeFactory lors des tests


    Néanmoins ces patterns ajoutent de la complexité, on le voit bien avec l'arborescence de classes qui te pose problème. On ne les utilise pas "parce que c'est cool" ou "parce que c'est comme ça qu'on fait", mais pour améliorer la maintenabilité du code quand c'est réellement nécessaire. Dans ton cas, je vois zéro amélioration de maintenabilité apporté par la factory, au contraire, ça amène de la complexité inutile en faisant fabriquer dans le même moule des objets qui n'ont que peu de rapport entre eux et seront manipulés totalement différemment par leurs consommateurs.

  13. #13
    Futur Membre du Club
    Merci pour tes recommandations et l'extrait d'article.

    La solution d'une Factory avec couche d'abstraction a été validé par l'architecte.

    Bonne journée.
    Cdlt.
    R.