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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    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é
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 294
    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.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    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).

  4. #4
    Membre très actif

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

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

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    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
    Membre très actif

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

  7. #7
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 294
    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.

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    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.

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    @rod : admettons que tu stockes toutes tes formes dans un vecteur, mais que tu ne sais pas encore à ce moment là quelle bibliothèque d'affichage tu vas utiliser (cf DP Stratégie). Cela appelle immédiatement au polymorphisme dynamique, avec inclusion de la fonction d 'affichage dans la classe.

    Je n'ai pas le nom du DP en tête, mais en donnant comme membre à la classe un pointeur vers une interface abstraite, et en affectant ce pointeur à une instance concrète déduite via l'utilisation d'une Stratégie, on devrait satisfaire le SRP et lOCP.

  10. #10
    Membre très actif

    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
    Par défaut
    Citation Envoyé par oodini Voir le message
    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.
    D'accord. Mais qu'une des deux méthodes modifient un membre privé utilisé par l'autre n'est pas du tout en contradiction avec SRP et OCP. Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    myRec = new Rectangle();
    //[...] dans une boucle plus loin
    myRec->updatePosition(); //calcul trajectoire et nouvelle position => modifie la pair (x,y) utilisée pour draw
    Window.draw(myRec); //ici, window.draw va appeler le service draw de la classe rectangle
    Dans mon petit exemple, updatePosition à pour seule responsabilité la mise à jour de la position de mon Rectangle, et draw rend le service unique "dessine moi". SRP est respecté, OCP aussi si on imagine draw et updatePosition virtuelles pour permettre l'évolution potentielle de ces dernières.

    Ce n'est pas ce que dit la littérature :
    A class should have one, and only one, reason to change.
    Je t'avoue que je ne comprends pas trop cette formulation :/

    Exact. Mais je n'ai pas encore d'opinion. Je lis, et j'essaye de comprendre.
    Moi aussi

  11. #11
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 294
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par oodini Voir le message
    A class should have one, and only one, reason to change.
    Note l'utilisation de "should" (pas "must").
    Je n'aime pas cette phrase. Elle ne veut rien dire selon moi. Imagine si tu créée une classe Rectangle dont la seule responsabilité est de s'afficher dans un contexte donné. Cet objet a besoin de données pour s'afficher (couleur et position disons). Si on applique cette phrase, alors il faudrait que couleur et position soient deux classes distinctes de Rectangle, et sans agrégation! ça n'a pas de sens.
    Il faut choisir une granularité qui convient au contexte précis du programme. Personne ne va t'insulter si tu as une structure POD de base qui implémente une fonction to_string(). ça ne rentre pas dans les grands principes, mais ça ne change rien à ton programme et il serait ridicule de créer 3 classes supplémentaires bourrées de templates pour gérer la transformation de ton objet en string alors que c'est juste pour le mettre dans ton fichier de log.

  12. #12
    Inactif
    Inscrit en
    Août 2013
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Août 2013
    Messages : 27
    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)

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

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    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.

  14. #14
    Inactif
    Inscrit en
    Août 2013
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Août 2013
    Messages : 27
    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)

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    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

  16. #16
    Membre Expert

    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 : 35
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    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.

+ Répondre à la discussion
Cette discussion est résolue.

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