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 :

Implémentation dans les fichiers d'entêtes [Débat]


Sujet :

C++

  1. #1
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut Implémentation dans les fichiers d'entêtes
    Bonjour tout le monde,
    Je cherche des arguments pour convaincre mon "client" qu'il ne faut pas coder les implémentations des classes/méthodes... à l'intérieur même des fichiers d'entêtes.
    Le seule argument que j'ai (et que je trouve important) est la clarté de la définition de la classe et des méthodes.
    Mon "client" me dit que pour certains cas c'est pour permettre aux utilisateurs (n'ayant pas l'implémentation) de modifier certaines parties du code...

    Avez-vous d'autres arguments pour définitivement convaincre les personnes qui "fourre tout" dans un même fichier?

    Merci d'avance

  2. #2
    Expert confirmé Avatar de fregolo52
    Homme Profil pro
    Développeur C
    Inscrit en
    Août 2004
    Messages
    2 364
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Août 2004
    Messages : 2 364
    Points : 5 378
    Points
    5 378
    Par défaut
    A part les templates, il ne doit quasiment pas y avoir d'implémentation dans les headers.
    Ton client n'a pas la culture du C/C++, c'est pas possible !!!
    Mon "client" me dit que pour certains cas c'est pour permettre aux utilisateurs(n'ayant pas l'implémentation) de modifier certaines parties du code...
    Ton client veut un truc open bar ? Chacun fait ce qu'il veut avec son source.
    Argument :
    - Ce n'est pas maintenable !!! chacun va modifier le code dans son coin.
    - C'est du travail de porc. (ah non, ça, tu ne peux pas dire cette vérité)

    Vu qu'on ne connait pas le projet, c'est difficile de se faire une idée de ce que peut être "public" ou "caché"

  3. #3
    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,

    Le principal argument que je donnerais, c'est que le C++ est prévu pour permettre la séparation de l'implémentation, et que cela augmente fortement le respect de l'OCP (Open Close Principle : une classe doit etre ouverte aux évolution, mais fermée aux modifications).

    Sauf quelques exceptions bien précises, il n'y a strictement aucune raison pour placer l'implémentation dans les fichiers headers.

    L'argument de ton "client" de permettre aux utilisateurs(n'ayant pas l'implémentation) de modifier certaines parties du code est, justement, quelque chose qu'il faut éviter à tout prix : si n'importe qui commence à modifier n'importe quoi dans le code, on court le risque qu'une modification soit apportée alors que celui qui l'apporte n'a pas compris l'ensemble du problème!!!

    Même dans le cas de projets open source, il suffira, pour permettre "à tout le monde" d'apporter des amélioration, de fournir les fichiers d'implémentation.

    De plus, les C++istes ont de toutes manières l'habitude de travailler avec une séparation des en-têtes et des implémentation.

    C'est au contraire le fait de travailler différemment qui aurait de quoi en surprendre plus d'un
    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

  4. #4
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    code dans les .h = couplage fort, recompilation a tors la rigot, temps de compil qui explose etc ...

  5. #5
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Bonsoir.
    J'ai appris (le C et) le C++ en séparant systématiquement les déclarations et l'implémentation.
    Mais depuis la découverte des fonctions « inline » (non template), je ne sais plus sur quel pied danser...

    D'un point de vue purement théorique, je conçois tout à fait qu'il faut séparer déclaration et implémentation (ou alors je ne conçois pas le contraire ? )
    Mais en pratique, je ne suis plus très sûr...

    Pourquoi a-t-on créé les fonctions inline, au fait ?
    Tout du moins, pourquoi a-t-on autorisé de les utiliser quand elles ne sont pas template ?

  6. #6
    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
    Citation Envoyé par Steph_ng8 Voir le message
    Bonsoir.
    J'ai appris (le C et) le C++ en séparant systématiquement les déclarations et l'implémentation.
    Mais depuis la découverte des fonctions « inline » (non template), je ne sais plus sur quel pied danser...

    D'un point de vue purement théorique, je conçois tout à fait qu'il faut séparer déclaration et implémentation (ou alors je ne conçois pas le contraire ? )
    Mais en pratique, je ne suis plus très sûr...

    Pourquoi a-t-on créé les fonctions inline, au fait ?
    Tout du moins, pourquoi a-t-on autorisé de les utiliser quand elles ne sont pas template ?
    il faut savoir que le fait de déclarer une fonction inline ne fait que demander au compilateur de remplacer l'appel de la fonction par le code de son implémentation.

    il faut déclarer les fonctions template (ou les fonctions membres de classes template) inline pour éviter le problème de la définition multiple des symboles

    Pour les fonction non template (ou non membre de classes template), l'idéal est de ne déclarer inline que les fonctions courtes (accesseurs, mutateurs, opérateurs de comparaison)

    Toute fonction contenant des boucle, des tests ou devant appeler d'autres fonctions (autres que les accesseurs, mutateurs et opérateurs de comparaison) ne devrait jamais etre inline

    Les fonctions virtuelles ne devraient pas l'être, car, meme s'il est possible de déclarer une fonction virtuelle inline, il y a quelque part une incohérence fonctionnelle à l'existence d'une telle fonction, étant donné que les fonctions virtuelles sont reprises dans une table qui permet de déterminer quelle version de la fonction utiliser.

    De manière générale, il faut se dire que la déclaration d'une fonction inline ne participe bien souvent que de la micro optimisation.

    L'idéal serait, une fois que toutes les possibilités d'amélioration de performance au niveau de l'algorithme ont été apportées, de ne décider de rendre inline que les petites fonctions dont un profiling avancé aura montré qu'il est intéressant de les inliner...
    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

  7. #7
    Membre averti Avatar de Nogane
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    241
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 241
    Points : 323
    Points
    323
    Par défaut
    Citation Envoyé par darkman19320 Voir le message
    Mon "client" me dit que pour certains cas c'est pour permettre aux utilisateurs (n'ayant pas l'implémentation) de modifier certaines parties du code...

    Avez-vous d'autres arguments pour définitivement convaincre les personnes qui "fourre tout" dans un même fichier?
    Bonjour,
    Si votre client a de bonnes raisons de rendre certaine partie de code modifiable par l'utilisateur de ça library, l'utilisation du design pattern stratégie(ou d'un langage de script), pourrait peut-être être un compromis acceptable?

  8. #8
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Merci à tous pour vos réponses!
    Le vrai problème c'est que mon client n'a pas eu de formation d'informatique ni de programmation (c'est un "matheux").

    Comme tu dis Nogane, pour remplacer certaines partie du code, je vais voir pour le design pattern stratégie.

    Je pense qu'avec tous ces arguments je devrais pouvoir le convaincre!!

    Encore merci!

  9. #9
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Si le client veut modifier le code, la solution adoptée est mauvaise. Livrez/vendez lui les sources tout simplement. Ou choisissez une licence qui va bien, GPL, etc. S'il peut modifier les .h, pourquoi ne pourrait-il pas modifier les .cpp ? L'argument n'a strictement aucun sens. Pire, si vous fournissez quelques .cpp déjà compilés (ce qui ne semble pas être le cas), et que le client s'amuse à rajouter des données membres dans des classes pour profiter de ses modifications d'algo, kaboom!

    En gros argument contre, je suis comme Joel: trop de couplage qui explosent les temps de (re)compilation.

    En arguments pour, et oui il y en a :
    - vérification des contrats par assertion via le pattern NVI où je mets les assert dans la partie publique qui sera dans le .h
    - divers accesseurs et autres endroits où je sais que le compilo peut inliner à coups sûrs pour moi.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  10. #10
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Ok, je vois.


    Citation Envoyé par koala01 Voir le message
    Toute fonction (...) devant appeler d'autres fonctions (autres que les accesseurs, mutateurs et opérateurs de comparaison) ne devrait jamais etre inline
    Et pour les fonctions dont l'unique but est de servir de raccourci à une autre fonction ?
    Comme le dit Joel F, ça crée un couplage fort.
    Mais en même temps, c'est le rôle de la fonction...


    Citation Envoyé par koala01 Voir le message
    Les fonctions virtuelles ne devraient pas l'être (...)
    D'accord, je comprends.
    Mais pour les fonctions virtuelles qui ne font rien, ou juste un return (comportement par défaut...) ?
    Dans ces cas-là, j'ai l'habitude d'écrire l'implémentation directement dans la définition de la classe.
    Ça évite de la réécrire juste pour définir un corps vide...
    Flemmardise mal placée, ou simplification compréhensible ?

    De manière générale, pour toutes les fonctions qui ne font rien (constructeurs dont la liste d'initialisation suffit, destructeur vide, fontions membres virtuelles « par défaut ») ou dont la seule instruction est l'appel à une autre fonction (raccourci) et/ou un return, j'écris leur implémentation directement dans le corps de la classe.
    Ça permet d'avoir leur sémantique directement à la déclaration.
    Mauvaise idée ?


    Dernière question à la limite du hors-sujet.
    Ça a du sens d'écrire template <...> inline (...), ou, puisqu'elle est template, la fonction est forcément inline ?

  11. #11
    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
    Citation Envoyé par Steph_ng8 Voir le message
    Ok, je vois.
    Et pour les fonctions dont l'unique but est de servir de raccourci à une autre fonction ?
    éventuellement... si c'est juste un raccourci sur la fonction membre d'un membre
    Comme le dit Joel F, ça crée un couplage fort.
    Mais en même temps, c'est le rôle de la fonction...
    Le fait est que ca crée un couplage fort avec de nombreuses unités de compilation...
    D'accord, je comprends.
    Mais pour les fonctions virtuelles qui ne font rien, ou juste un return (comportement par défaut...) ?
    Dans ces cas-là, j'ai l'habitude d'écrire l'implémentation directement dans la définition de la classe.
    Ça évite de la réécrire juste pour définir un corps vide...
    Flemmardise mal placée, ou simplification compréhensible ?
    A mon sens, ce serait de la flemmardise mal placée car inline est incompatible à mon sens avec les vtbl... mais bon, je n'ai aucun argument à avancer :p
    De manière générale, pour toutes les fonctions qui ne font rien (constructeurs dont la liste d'initialisation suffit, destructeur vide, fontions membres virtuelles « par défaut ») ou dont la seule instruction est l'appel à une autre fonction (raccourci) et/ou un return, j'écris leur implémentation directement dans le corps de la classe.
    Ça permet d'avoir leur sémantique directement à la déclaration.
    Mauvaise idée ?
    Ce n'est pas forcément mauvaise idée, mais bon, normalement, le nom de la fonction devrait suffir :p
    Dernière question à la limite du hors-sujet.
    Ça a du sens d'écrire template <...> inline (...), ou, puisqu'elle est template, la fonction est forcément inline ?
    C'est obligatoire : l'utilisation de template ne définit absolument pas inline de manière implicite (c'est d'ailleurs peut etre dommage )
    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

  12. #12
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par darkman19320 Voir le message
    Mon "client" me dit que pour certains cas c'est pour permettre aux utilisateurs (n'ayant pas l'implémentation) de modifier certaines parties du code...
    Salut,
    Une petite relecture du OCP ?

  13. #13
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Merci pour ta réponse 3DArchi.
    Une grande partie du code peut se comporter comme ceux-ci mais comme je l'ai expliqué dans un autre sujet (ici), pour certains cas, je ne pense pas que l'on puisse utiliser ce principe.

    Voici un exemple: une classe A (abstraite) qui est héritée par plusieurs classes filles B,C,D. Chacune de ces filles font références à une bibliothèque (libre ou non et statique ou dynamique).
    Nous devons produire une seule bibliothèque statique et livrer seulement celle-ci (ainsi que les fichiers d'entêtes) aux utilisateurs. L'utilisateur n'a pas accès aux sources et donc ne pourra pas la re-compiler.
    Seulement, si un utilisateur n'a pas toutes les bibliothèques tierces utilisées par les classes filles alors la compilation ne pourra pas se faire (problème d'"Undifined Reference").

    Pour résoudre un problème tels que celui-ci, j'ai plusieurs idées comme expliquée dans le sujet précédent.
    Seulement, si l'on veut rester avec une seule bibliothèque statique, je ne vois pas d'autre moyen que d'insérer le code des classes B,C,D dans le .hpp et lors de la compilation d'une application utilisateurs, ces classes filles sont compilées en fonction de la présence ou non des bibliothèques tierces.
    Par conséquent nous n'aurons qu'une seule bibliothèque et une application qui contiendra les fichiers objets des classes B, C, D en plus de ceux de l'application.

    Pensez-vous que l'on peut éviter ce comportement si l'on ne veut qu'une seule bibliothèque statique?

  14. #14
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2008
    Messages : 87
    Points : 111
    Points
    111
    Par défaut
    ca m'a l'air de répondre au concept de modules. tu as des fonctionalités facultatives, donc pour se faire il devrait y avoir quelque chose de branchable.
    ici, c'est la compilation qui est branchable. comme des defines preprocesseur qui enleverais/rajouterais du code pour configurer un projet.
    une manière plus flexible consisterai a linker en dynamique et charger les méthodes dynamiquement les classes filles qui elles meme dépendent de toutes ces fameuses biblio tierces. non ?

    sinon, pour l'implémentation dans les headers, il faut avouer que dans certains cas c'est très pratique: voir la plupart de boost, ou glm. il y a plusieurs biblio dite "header only" et franchement, ca simplifie le travail car il n'y a pas d'ABI en C++ donc linker dépend toujours du vendeur du compilateur et même sans ca, c'est toujours chiant de configurer les CMakeLists ou makefile ou projets pour linker avec 400 trucs qui se règlent pas pareil selon l'OS raaah...

    par contre oui, comme dit Joel, aie aie les temps de build, dès qu'on inclue boost c'est la misère et plus on a de biblio comme ca plus c'est long.

  15. #15
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Merci Lightness.
    Mais comme je l'ai écris le problème c'est que l'utilisateur final ne pouvait pas compiler la bibliothèque. Il n'avait accès qu'au binaire.

    J'ai résolu mon problème de la manière suivante: j'ai externalisé la création de mes objets dans une fabrique qui contient toutes les créations vers les objets des bibliothèques tierces et je fournis seulement ce code source sans que le reste soit diffusés.
    C'est sans doute une solution de facilité mais elle fonctionne et n'est pas contraignant vis-à-vis de la diffusion du code puisqu'une fabrique n'a rien d'exceptionnelle en soit.

    Conclusion même pas à coder dans les .h!!

  16. #16
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Citation Envoyé par darkman19320 Voir le message
    C'est sans doute une solution de facilité mais elle fonctionne et n'est pas contraignant vis-à-vis de la diffusion du code puisqu'une fabrique n'a rien d'exceptionnelle en soit.
    Non. je pense que ce n'est pas la solution de facilité mais bel et bien le premier pas vers la bonne solution.
    L'idée est de bien séparer l'instanciation des objets (notamment ceux conçus pour être spécialisés) et de les injecter dans ta bibliothèque.
    C'est bien le rôle de tes utilisateurs de créer les instances concrètes - éventuellement de classes dérivées s'ils veulent modifier certains comportements - et d'injecter ces instances concrètes dans ta bibliothèque.

    Tu dois donc probablement fournir aux utilisateurs de quoi construire des instances dérivées des différents objets qu'ils peuvent spécialiser puis d'injecter ces instances dans ta bibliothèque.

    (fortement inspiré de l'injection de dépendance).

Discussions similaires

  1. Entête des tableaux dans les fichiers de sortie
    Par roro8 dans le forum Développement de jobs
    Réponses: 1
    Dernier message: 29/12/2009, 10h35
  2. Réponses: 3
    Dernier message: 11/06/2009, 17h49
  3. Réponses: 8
    Dernier message: 18/07/2005, 14h04
  4. Réponses: 3
    Dernier message: 29/12/2004, 17h10

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