IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

C++ Discussion :

SRP vs OCP - fondamentaux peu solides


Sujet :

C++

  1. #1
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut SRP vs OCP - fondamentaux peu solides
    Hello,

    J'ai un petit souci avec lesprincipes suivants de SOLID :

    • SRP (Single Responsability Principle)
    • OCP (Open Closed Principle)


    Si je prends une classe rectangle, et que je veux pouvoir dessiner le rectangle et calculer sa surface :

    • SRP me dit que ces deux fonctionnalités doivent être sorties de la classe (car après tout, il y a 2 fonctionnalités)
    • OCP me dit de les mettre dedans (voir par exemple ce lien)


    Du coup, je ne sais plus où donner de la tête.

  2. #2
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    De la façon dont j'ai compris SRP, ce n'est pas parce que ton rectangle doit pouvoir faire deux choses différentes (s'afficher et calculer sa surface) qu'il doit être séparé en deux objets distincts. L'unicité de responsabilité s'applique aux atomes sémantiques, c'est à dire aux fonctions, pas aux objets. Il est normal qu'un objet fournisse plusieurs services, c'est même, à mon avis, le principe de la poo. Sinon on ferait du fonctionnel.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  3. #3
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    SRP pour Property.

    Je ne comprends pas du tout ton raisonnement, OCP ne veut pas dire du tout qu'il faille mettre deux méthodes à responsabilité distincte dans le même sac :/

    Et d'ailleurs SRP ne dis pas non plus que parce que ta classe doit fournir deux services il faut faire deux classes :/

    Si nos experts reconnus fatiguent on est mal barrés les gars
    Nullius in verba

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Citation Envoyé par r0d Voir le message
    De la façon dont j'ai compris SRP, ce n'est pas parce que ton rectangle doit pouvoir faire deux choses différentes (s'afficher et calculer sa surface) qu'il doit être séparé en deux objets distincts. L'unicité de responsabilité s'applique aux atomes sémantiques, c'est à dire aux fonctions, pas aux objets. Il est normal qu'un objet fournisse plusieurs services, c'est même, à mon avis, le principe de la poo. Sinon on ferait du fonctionnel.
    On pourrait dessiner avec 2 bibliothèques différentes.
    On pourrait calculer la surface selon deux projections géodésiques différentes.
    Il y a donc plus d'1 raison de changer la classe -> scission (d'après ce que j'ai compris du SRP).

  5. #5
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Citation Envoyé par Kaamui Voir le message
    Je ne comprends pas du tout ton raisonnement, OCP ne veut pas dire du tout qu'il faille mettre deux méthodes à responsabilité distincte dans le même sac :/
    Si tu veux dessiner une liste de formes géométriques, il semble opportun d'avoir disons un vecteur d'une classe parente, et d'appeler une méthode polymorphique de dessin sur chaque objet.
    Si tu veux effectuer une transformation sur une liste de formes géométriques, il ne semble pas déraisonnable de suivre la même chose. Or, l'affichage et les transformations géométriques sont deux responsabilités différentes, non ?

  6. #6
    Inactif
    Inscrit en
    Août 2013
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Août 2013
    Messages : 27
    Points : 52
    Points
    52
    Par défaut
    Citation Envoyé par Kaamui Voir le message
    SRP pour Property.
    Non, c'est bien principe.

    @oodini
    C'est une question de choix personnel et de limite où tu veux aller dans ton design.

    Si tu considères que ton élément Rectangle n'évoluera pas, alors tu peux donner la responsabilité unique "représenter le concept rectangle" à ta classe Rectangle et les RU "calculer la surface" et "dessiner un rectangle" à tes fonctions surface() et draw().

    Par contre, tu peux aussi considérer que Rectangle entre dans un ensemble plus large, par exemple des polygones. Alors, ta classes Rectangle aura déjà beaucoup à faire avec la gestion des points (qui peuvent être à N dimensions), vérifier que le polygone est bien un rectangle (largeur et hauteur identique, angle droit, dans un même plan, etc). Dans ce cas, tu peux décider que la responsabilité du rendu du rectangle doit être pris en charge par une classe dédiée, qui aura beaucoup à faire aussi (gérer la projection en 2D à partir de ND, vérifier que le contexte de rendu est valide, optimiser le rendu, etc)

    Et tu pourrais ainsi augmenter le nombre de classes (et donc séparer les responsabilités) selon la "précision" que tu veux avoir. Voir par exemple Boost.Geometry qui défini des classes pour les systèmes de coordonnées, pour les polygones, pour les algos, etc

    Bref, c'est qu'une question de choix "statégiques". Le principal est surtout de savoir pourquoi ces principes existent, savoir les problèmatiques qu'ils permettent à éviter et savoir quand on choisit un design les conséquences de son choix (bons ou mauvais : temps de dev, complexité de dev, évolutivité, maintenabilité, etc)

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    C'est un peu la réponse que je souhaitais avoir.

    J'ai l'impression que les principes SOLID, comme les design patterns, sont des choses à toujours avoir à l'esprit, qui nous accompagnent dans nos choix architecturaux, mais à ne pas appliquer systématiquement.

  8. #8
    Inactif
    Inscrit en
    Août 2013
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Août 2013
    Messages : 27
    Points : 52
    Points
    52
    Par défaut
    Oui, c'est ce que j'ai ajouté dans mon EDIT (mais tu as répondu plus vite que moi)

    Bref, c'est qu'une question de choix "statégiques". Le principal est surtout de savoir pourquoi ces principes existent, savoir les problèmatiques qu'ils permettent à éviter et savoir quand on choisit un design les conséquences de son choix (bons ou mauvais : temps de dev, complexité de dev, évolutivité, maintenabilité, etc)
    Par contre, comme toute les règles, les principes de POO doivent être respecter scrupuleusement...
    Et comme toutes les règles, elles peuvent être enfrein
    (plus précisement, on voit souvent des débutants ne pas maîtriser une règle, mais ne pas l'appliquer suite à la lecture d'un article disant que l'on pouvait ne pas respecter cette règle. C'est une erreur : on peut se permettre de ne pas respecter une règle quand on maîtrise les conséquences du non-respect de cette règle. Valable aussi pour les design pattern)

  9. #9
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Bonjour,

    Pourquoi ces fonctions devraient être membre ? Il n'y a aucune raison pour ça.

    Surtout pour ces fonctions là, elles doivent pouvoir être libre non amies sans vraiment de problème, ou alors c'est qu'il manque des services vraiment basiques à ta classe, AMA.

  10. #10
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,

    Il faut déjà bien comprendre les principes, et se rappeler que SRP a un champs d'action finalement fort étendu:
    1. au niveau de la fonction tout d'abord: chaque fonction ne doit faire qu'une chose mais doit veiller à la faire correctement (la fonction permettant de calculer la surface d'un rectangle ne doit faire que ça, de même que celle permettant de tracer le rectangle).
    2. Au niveau de la classe ensuite, où chaque type concret (rectangle, par exemple) hérite de la responsabilité de l'abstraction dont il hérite (Forme, par exemple)
    3. Au niveau du module enfin, car le module qui s'occupe de l'affichage du rectangle n'a, a priori, aucune raison de se charger également de la transmission (ou de la récupération) des données sur le net (qu'il soit publique ou privé... Ce serait, typiquement, la responsabilité d'un module séparé.

    Pour pouvoir appliquer correctement l'OCP, tu dois également appliquer correctement les autres principes de SOLID, dont, essentiellement, le I (Interface Segregation Principle) et le D (Dependancy Inversion Principle)

    Je m'explique : A priori, la manière dont la surface d'un rectangle est calculée est ferme et définitive : quel que soit le contexte dans lequel tu travailles, le résultat sera toujours obtenu par la multiplication de la longueur par la largeur (ou de la largeur par la longueur, ne soyons pas sectaires )

    Mais cette possibilité (je parle de celle qui consiste à calculer la superficie de "n'importe quoi") représente, quelque part, un concept que l'on pourrait appeler "Surfacable".

    Ce concept pourrait parfaitement être utilisé lorsqu'il s'agit, par exemple, de calculer la superficie total d'un corps quelconque (de la jolie vasque romaine contournée au corps d'une pin-up) que l'on aurait subdivisé en différentes formes de base.

    De même, la possibilité d'afficher une forme correspond à un concept beaucoup plus général que l'on pourrait appeler "Drawable" car on pourrait parfaitement considérer que "n'importe quel corps" subdivisé en différentes formes géométrique est, lui aussi, affichable si l'on décide d'afficher toutes les formes qui le composent.

    Tu remarqueras tout de suite que ton abstraction Forme (car ce qui est vrai pour le rectangle l'est également pour le disque ou pour le triangle) exposent, en définitive, une interface qui correspond à ces deux concepts, parce qu'on peut effectivement vouloir afficher ou calculer la superficie de n'importe quelle forme.

    Par contre, on pourrait parfaitement envisager d'avoir deux abstractions totalement distinctes pour les formes :
    SurfacableForm lorsque tu as besoin d'être en mesure de calculer la surface (car tu auras alors rarement besoin d'afficher ta forme) et DrawableForm, lorsque tu as besoin de l'afficher et qui n'a rien à voir avec SurfacableForm (parce que tu n'as aucun besoin d'être en mesure de calculer la surface d'une forme pour pouvoir l'afficher).

    Le fait de séparer les différents concepts sous la forme d'interfaces simples (quelques fonctions au maximum), dans le respect de l'ISP, te permet donc une flexibilité beaucoup plus grande

    Mais revenons à OCP...

    Ce principe te dit, simplement, que tu ne devrais idéalement pas te retrouver dans une situation dans laquelle tu serait obligé de modifier le code existant (et validé !!!) afin d'être en mesure d'intégrer des évolutions.

    Le meilleur moyen pour y parvenir est, très certainement, de travailler sur des abstractions.

    Par exemple, si tu as une classe Render qui est correspond à l'abstraction dont le rôle est d'afficher tes données métiers (quelle que soit la manière dont les données métiers sont représentée), tu pourrais déjà prévoir une fonction propre destinée à afficher les différentes données métiers sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /* Abstraction de base propre à tout système d'affichage */
    class Render{
        public:
            virtual void draw(Rectangle const &) = 0;
            virtual void draw(Circle const & ) = 0;
            virtual void draw(Triangle const &) = 0;
            virtual void draw(Vasque const &) = 0;
            virtual void draw(PinUp const &) = 0;
    };
    et, pour chaque donnée métier que tu manipule, tu pourrait parfaitement envisager de dériver une classe du concept Drawable qui fonctionnerait sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class Drawable{
        public:
            virtual void drawMe(Render & render) const = 0;
    };
    /* l'abstraction propre aux formes, à spécialiser pour les formes 
     *  que tu utilises
     */
    class DrawableForm : public Drawable {
     
    };
    /* la classe spécifique au rectangle */
    class DrawableRectangle : public DrawableForm {
       public:
           DrawableRectangle(Rectangle const & rect):rect_(rect){}
           void drawMe(Render & render) const{
               render.draw(rect_);
           }
    };
    Un tel code respectera l'OCP (enfin, jusqu'à un certain point) parce que, si tu décides d'utiliser une autre bibliothèque pour l'affichage, il te "suffira" de créer une classe dérivée de Render, adaptée à la bibliothèque que tu utilises, pour rajouter le support de la bibliothèque en question, sans avoir à t'inquiéter de modifier le code que tu as déjà écrit.

    Il aura par contre un certain mal à le respecter si tu décide d'ajouter le support du dodécagone (même si le problème se présentera plutôt si tu as de nombreux type dérivés de Render à maintenir en état de fonctionnement).

    Par contre, un code qui ne respecterait pas l'OCP serait sans doute proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    void foo( UnType & data){
        /* la fonction type renvoie une valeur énumérée correspondant
         * au type réel dérivé de UnType
         */
        switch(type()){
            case typeUn : 
                static_cast<TypeOne &>(data).someStuff();
                break;
             case typeDeux:
                static_cast<TypeTwo &>(data).otherStuff();
                break;
            /* ... */
             case typeN:
                static_cast<TypeN &>(data).oneMoreDifferentStuff();
                break;
        }
    }
    car tu ne pourras pas rajouter un nouveau type dérivé de UnType sans passer par tous les endroits où une telle logique serait mise en place.

    J'avais, il y a quelques mois, commencé un article qui traitait, entre autres, de SOLID.

    Cet article présente le problème d'un jeu d'échec complet comme étude de cas, et propose une solution élégante au problème car il faut aussi penser au fait que l'interface publique de l'abstraction Render doit rester la plus stable possible dans le temps.

    Si le nombre de données métier est relativement stable pour un jeu d'échecs, il risque en revanche de l'être beaucoup moins dés qu'il s'agit de tracer des formes, étant donné que tu es toujours susceptible de vouloir rajouter la forme composées de N+1 cotés égaux.

    Mais, chemin faisant, je me suis retrouvé avec un truc de près de 200 pages au format A4, ce qui est un peu gros pour un article, et j'ai trouvé un éditeur qui va en faire un livre... Et comme je ne voudrais pas éventer le sujet, je n'en parlerai pas trop ici

    La sortie de ce bouquin est prévue pour la mi novembre, environ, je ne manquerai pas de la signaler
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  11. #11
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Tu établis de manière plus formelle ce que je croyais comprendre, et je t'en remercie.

    Pour ton bouquin, je serai intéressé.

    J'espère que tu fondes toutes les principes sur un seul exemple d'application (jeu d'échec), ainsi que les mauvaises méthodes qui viennent initialement à l'esprit (le coup du switch, en revanche, me semble vraiment trop mauvais pour être crédible ).

  12. #12
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Citation Envoyé par oodini Voir le message
    J'espère que tu fondes toutes les principes sur un seul exemple d'application (jeu d'échec), ainsi que les mauvaises méthodes qui viennent initialement à l'esprit (le coup du switch, en revanche, me semble vraiment trop mauvais pour être crédible ).
    Détrompe-toi, c’est très utilisé le switch. Et quand tu sais que ton ensemble de type est fini et qu’il n’évoluera pas (typiquement, types primitifs d’un interpréteur), c’est une solution tout à fait acceptable.

  13. #13
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Switcher sur les types, ça amène toujours à faire des choses peu élégantes (traits, etc.), et j'arrive toujours à trouver moyen de l'éviter (via le polymorphisme, par exemple).

  14. #14
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par oodini Voir le message
    Tu établis de manière plus formelle ce que je croyais comprendre, et je t'en remercie.
    C'était avec plaisir
    Pour ton bouquin, je serai intéressé.
    Je verrai "avec la direction" (de dvp) si on peut faire une annonce ou pas
    J'espère que tu fondes toutes les principes sur un seul exemple d'application (jeu d'échec), ainsi que les mauvaises méthodes qui viennent initialement à l'esprit
    A vrai dire, il est divisé en deux grandes parties : ce que je pense ce certaines pratiques, pourquoi et comment les éviter, avec des exemples simples, et le cas d'étude complet, qui est un jeu d'échec, pour lequel j'essaye chacune des décision prise

    Le tout, dans mon "style de plume" habituel
    (le coup du switch, en revanche, me semble vraiment trop mauvais pour être crédible ).
    Je peux pourtant t'assurer avoir déjà croisé ce genre de code, dans un projet professionnel, en production, avec un nombre de types qui n'étaient ni des primitifs ni fini, mais bien toute une hiérarchie de classes ayant sémantique d'entité.

    Le résultat des courses était que ce code fourmillait littéralement de switch dans tous les sens
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  15. #15
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    Détrompe-toi, c’est très utilisé le switch. Et quand tu sais que ton ensemble de type est fini et qu’il n’évoluera pas (typiquement, types primitifs d’un interpréteur), c’est une solution tout à fait acceptable.
    Acceptable certes, mais très certainement évitable et à éviter autant que possible

    Mais c'est vrai que c'est une technique très (trop) utilisée
    Citation Envoyé par oodini Voir le message
    Switcher sur les types, ça amène toujours à faire des choses peu élégantes (traits, etc.), et j'arrive toujours à trouver moyen de l'éviter (via le polymorphisme, par exemple).
    Et encore, quand tu as la chance que ce soit fait avec des traits...

    Mais je peux t'assurer que ce n'est pas parce que TU évites cette technique (et je te félicite de le faire ) ou parce que TU ne as la chance de ne l'avoir encore jamais croisée que l'exemple devient peu crédible, je peux te l'assurer... malheureusement
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  16. #16
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Mais je peux t'assurer que ce n'est pas parce que TU évites cette technique (et je te félicite de le faire ) ou parce que TU ne as la chance de ne l'avoir encore jamais croisée que l'exemple devient peu crédible, je peux te l'assurer... malheureusement
    Si si, je te rassure, je le croise... J'ai aussi 95 dynamic_cast (je viens de faire une recherche) sur le code que j'ai récupéré... Et certains sont conjugués avec un switch et un typeid.

    Je me disais plutôt que le gars qui va acheter un bouquin sur SOLID a peu de chances de coder ce genre d'abominations.

  17. #17
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par oodini Voir le message
    Si si, je te rassure, je le croise... J'ai aussi 95 dynamic_cast (je viens de faire une recherche) sur le code que j'ai récupéré... Et certains sont conjugués avec un switch et un typeid.
    Ca fait peur, hein
    Je me disais plutôt que le gars qui va acheter un bouquin sur SOLID a peu de chances de coder ce genre d'abominations.
    Sur SOLID, entre autres

    Ben, disons que j'espère convaincre ceux qui le liront qu'il y a moyen de faire autrement et surtout ... proprement
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  18. #18
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Citation Envoyé par oodini Voir le message
    Si tu veux dessiner une liste de formes géométriques, il semble opportun d'avoir disons un vecteur d'une classe parente, et d'appeler une méthode polymorphique de dessin sur chaque objet.
    Si tu veux effectuer une transformation sur une liste de formes géométriques, il ne semble pas déraisonnable de suivre la même chose. Or, l'affichage et les transformations géométriques sont deux responsabilités différentes, non ?
    Non c'est que j'ai l'impression que tu veux faire de deux fonctions (polymorphiques ou non - ce que tu proposes das ton exemple est une bonne idée) à responsabilité distincte une seule et même fonction, pour respecter l'OCP, mais je ne vois pas pourquoi, au contraire, si tu fais ça tu ne respecte pas le SRP, et par conséquent l'OCP aura du mal à être respecté puisqu'à la seconde ou tu voudra respecter le SRP, tu devra modifier le code existant, en tout cas d'après ce que j'en avais compris.

    Mais je penses que white_tentacle avait visé juste sur ce qui te chagrinait, et que ce principe du SRP s'appliquait à l'échelle des méthodes pas des classes (en tout cas pour les question de service à fournir (dessin et calcul), car on peut facilement avoir envie de considérer comme cela a été dit que ta classe à la responsabilité unique de représenter "un rectangle" par exemple, mais ce n'est pas une responsabilité atomique en terme de comportement logiciel, donc bon...).

    Tu parles d'appliquer SOLID à une classe (de manière englobante, comme si c'était une boite noire) <= mon ressenti, d'où mon incompréhension sur ta conception de ces principes
    Nullius in verba

  19. #19
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Je réfléchis à cette question depuis quelques jours. J'ai un problème un peut comparable sur un projet perso. Du coup j'ai repris la lecture de Modern C++ Design, en espérant trouver LA réponse.

    En fait, ce que me gène dans la présente discussion, c'est que tu veux avoir un objet qui peut être manipulé (affiché) par plusieurs bibliothèques. Dit comme ça, la responsabilité de l'affichage ne doit pas incomber à l'objet, mais à la bibliothèque. Non?

    En fait, je pense que le problème n'est pas là. Le problème c'est d'avoir une bibliothèque suffisamment générique pour permettre au même objet de s'afficher différemment. Si le problème est bien là, alors les templates et la notion de Policy doit répondre à cette question je pense.

    Je ne développe pas plus car je ne suis pas certain d'avoir parfaitement cerné l'interrogation du PO.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  20. #20
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 704
    Points
    2 704
    Par défaut
    Citation Envoyé par Kaamui Voir le message
    Non c'est que j'ai l'impression que tu veux faire de deux fonctions (polymorphiques ou non - ce que tu proposes das ton exemple est une bonne idée) à responsabilité distincte une seule et même fonction
    Non. Je m'interrogeais sur le fait de les mettre dans la même classe.
    Après tout, une des fonctions pourrait très bien modifier un membre privé utilisé par l'autre fonction.

    Citation Envoyé par Kaamui Voir le message
    Mais je penses que white_tentacle avait visé juste sur ce qui te chagrinait, et que ce principe du SRP s'appliquait à l'échelle des méthodes pas des classes
    Ce n'est pas ce que dit la littérature :
    A class should have one, and only one, reason to change.

    Citation Envoyé par Kaamui Voir le message
    Tu parles d'appliquer SOLID à une classe (de manière englobante, comme si c'était une boite noire)
    Exact. Mais je n'ai pas encore d'opinion. Je lis, et j'essaye de comprendre.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [XSL-DELPHI] Peu orthodoxe... Mais ça marche : )
    Par stailer dans le forum Bases de données
    Réponses: 6
    Dernier message: 09/12/2003, 23h18
  2. je m'y perd un peu dans tous ces plugin
    Par Stessy dans le forum Eclipse Java
    Réponses: 7
    Dernier message: 30/09/2003, 23h33
  3. RTL60 ( la jsuis un peu confused)
    Par magdoz dans le forum Outils
    Réponses: 7
    Dernier message: 23/07/2002, 11h20
  4. DirectX 6, un peu en retard ... :\
    Par multani dans le forum DirectX
    Réponses: 3
    Dernier message: 28/05/2002, 19h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo