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

Langage C++ Discussion :

Polymorphisme statique et dynamique


Sujet :

Langage 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 705
    Points
    2 705
    Par défaut Polymorphisme statique et dynamique
    Hello,

    Le polymorphisme dynamique (virtual) est plus gourmand que le polymorphisme statique (CRTP).
    Mais il est également plus lisible.

    Ma question est donc : quand le polymorphisme statique (CRTP) est suffisant, l'utilisez-vous systématiquement ?
    Ou seulement après profiling (théorique ou pratique) ?

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    A mes yeux, ils n'ont surtout pas du tout le même rôle.

    Le crtp est là pour faciliter le partage de code, en conservant une grande précision de typage.
    Le virtual permet au contraire de manipuler ensemble et de la même manière des références vers des types distincts mais liés (cousinage)

    Ils n'interviennent pas au même moment.
    J'aurai tendance à faire intervenir le crtp par un héritage privé ou protégé.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    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 705
    Points
    2 705
    Par défaut
    Citation Envoyé par leternel Voir le message
    A mes yeux, ils n'ont surtout pas du tout le même rôle.
    Je connais bien les cas d'utilisation de chacun, leurs avantages et leurs inconvénients.

    Mais avant que chacun d'entre nous ne découvre le CRTP, nous avons tous utilisé du polymorphisme dynamique là où du statique aurait mieux convenu.
    Et force est de reconnaître que je tombe souvent sur du code fonctionnant sur ce mode, et que je me pose alors la question : dois-je refactorer ?

    Enfin, le code CRTP est moins lisible (on repère moins facilement la notion de virtualité), et donc je me posais la question.

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Pour ta question de lisibilité: mais justement, on ne veut pas proposer de virtualité dans le CRTP.

    Pour la question du réfactor: "ça dépend"

    Ca dépend de si tu y es autorisé.
    Ca dépend aussi de l'avantage que l'application y gagne.
    Le premier problème de la reconstruction, c'est le risque de régression.

    Si tu peux diviser par deux la taille du code, à fonctionnalité égale, et sans passer par des siouxeries, c'est probablement une bonne idée.
    Si tu peux réduire la taille du code utilisateur, quitte a grossir un peu le code interne, pourquoi pas.

    Si tu améliore la maintenabilité en augmentant la clarté, je t'encourage à militer pour ce changement, voire à le faire dans ton coin, et montrer après que c'est clairement mieux.

    Si ca ne change rien: même code d'appel, performance similaire et, surtout, même maintenabilité, ne le fait pas.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  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 705
    Points
    2 705
    Par défaut
    Citation Envoyé par leternel Voir le message
    Pour ta question de lisibilité: mais justement, on ne veut pas proposer de virtualité dans le CRTP.
    Je voulais dire que le mot-clé virtual permettait de rendre visible la redéfinition.

    Je suis assez d'accord sur le reste.

    Autre sujet : parfois, on ne sait pas toujours à l'avance si le polymorphisme aura besoin d'être un jour dynamique.
    Le CRTP peut s'imposer d'évidence quand l'architecture est stabilisée. D'ici là : statique (blindé) ou dynamique (simple à lire et coder) ?

  6. #6
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Je pense que ça dépend de l'usage prévisible.

    Si une variable polymorphique spécifique est amenée à contenir plusieurs valeurs de types différents, le dynamique est de rigueur.
    Si cette variable ne reçoit que des valeurs du même type, c'est du template/CRTP.

    Et je considère la variable au sens de champ d'une instance spécifique de la classe à coder.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

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

    Informations professionnelles :
    Activité : aucun

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

    D'abord, il faut savoir que le polymorphisme par CRTP n'est qu'une possibilité offerte par le paradigme générique alors que le polymorphisme "classique" (qui est en réalité le polymorphisme par inclusion ) est une possibilité du paradigme orienté objet. Autre paradigme, autres moeurs ;-)

    D'une certaine manière, nous pourrions dire que le CRTP permet d'adapter un comportement déterminé à un grand nombre de types différents, alors que polymorphisme d'inclusion permet, au contraire d'obtenir plusieurs comportements "cohérents" pour tout objet qui pourrait être connu comme étant de type identique (ou à défaut compatible).

    Je m'explique:
    Si tu as une classe utilisée pour le CRTP ressemblant à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template <typename T>
    class MyClass{
        public:
            void foo(){ /* ... */}
        protected:
            MyClass();
            ~MyClass();
    };
    tu as la certitude que le comportement sera toujours identique, clairement défini, quel que soit le type réel de T, alors que, en programmation orientée objet, on va plutôt partir du principe qu'une classe de base (Forme) expose un service donné (Draw) qui devra s'adapter au type réel de la donnée maniupulée
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int main(){
        Forme * circle= new Circle(/* ... */);
        Forme * rectangle= new(/* ... */);
        circle->draw(); // "I am a circle"
        rectangle->draw(); // "I am a rectangle"
        delete circle;
        delete rectangle;
        return 0;
    }
    L'énorme avantage du CRTP est qu'il te permet surtout de respecter un des principes de base : Don't Repeat Yourself, en passant par un respect plus stricte d'ISP (principe de ségrégation des interfaces).

    Maintenant que l'on est sur de partir sur une base saine et commune, la question qui fâche : faut il, oui ou non, décider de refactoriser systématiquement tous les projets qui utilisent le paradigme OO alors que le paradigme générique et le CRTP semblent plus intéressants

    Je crois personnellement que la réponse varie entre "oui sauf" et "non, à moins que"... Mais là encore, cela mérite sans doute une explication supplémentaire

    Je dirais que, de toutes façons, ce genre de refactorisation ne doit se faire qu'à l'occasion d'un passage de version majeure, essentiellement pour éviter de briser la compatibilité binaire à l'occasion d'un "bugfix".

    Une fois qu'il est bien établi que cette refactorisation ne doit pas intervenir à tords et à travers, il faut réfléchir à quand elle s'avère utile, intéressante ou nécessaire et quand elle s'avère au contraire totalement inutile.

    Déjà, si les principes OO (LSP en tête) sont parfaitement respectés avec l'approche OO de ton code, je crois que la refactorisation du projet n'aura aucun intérêt autre que purement intellectuel. Autrement dit: fait le si tu as le temps et que tu t'ennuies, mais gardes toujours bien une version fonctionnelle utilisant le paradigme OO... Jusqu'à ce que tu sois en mesure de fournir un version entièrement refactorisée.

    Par contre, si tu te rend réellement compte que l'approche OO ne respecte pas les principes de base de ce paradigme (LSP en tête), il est sans doute très intéressant d'envisager la refactorisation, en gardant en tête que cela risque très certainement d'avoir des conséquences "incontrôlées" dans le sens où la refactorisation a de bonne chances de casser beaucoup plus de code que ce que tu n'aurais pu l'imaginer au départ.

    Et puis, bien sûr, il y a tous les cas qui peuvent prendre place entre les deux, où les principes du paradigme OO sont "dans l'ensemble bien respectés", mais où l'on se rend compte que le DRY est très loin de l'être. Pour tous ces cas "entre deux" (et pour tous les autres, d'ailleurs ), je crois que la décision doit être prise "au cas par cas"

    Mais garde toujours en tête le fait qu'une refactorisation, quelle qu'elle soit, prend souvent beaucoup plus de temps que l'on n'aurait pu l'imaginé au début. Généralement, on se dit que "bah, en deux heures c'est emballé", et on se retrouve, trois jours plus tard, avec quelque chose qui ne compile toujours pas Il arrive parfois que l'on soit surpris à l'inverse, que l'on prévoie trois jour de travail pour se rendre compte qu'il suffit de changer deux lignes de code afin d'apporter l'amélioration souhaitée... Mais c'est quand même beaucoup, beaucoup, beaucoup plus rare
    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

Discussions similaires

  1. Polymorphisme Dynamique et Polymorphisme statique
    Par ABAM3194 dans le forum Visual C++
    Réponses: 9
    Dernier message: 15/11/2013, 19h02
  2. [conception]polymorphisme statique ou dynamique ?
    Par vandamme dans le forum C++
    Réponses: 7
    Dernier message: 15/07/2007, 10h14
  3. Agrégation: statique ou dynamique
    Par icer dans le forum C++
    Réponses: 13
    Dernier message: 04/03/2006, 15h48
  4. char *, string et tableau statique ou dynamique
    Par salseropom dans le forum C
    Réponses: 2
    Dernier message: 05/12/2005, 11h33
  5. Réponses: 2
    Dernier message: 19/08/2005, 16h02

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