Déclaration des classes selon la forme de Coplien - C++ - Programmation
Marsh Posté le 29-01-2003 à 15:02:02
je savais pas que ca avait un nom
professionnellement j'i pas d'expérience, mais sans tout ce que tu decrit, je vois pas comment on peut bosser... 1xfois sur 1....0 le compilo génère ca de facon satisfaisante (pour les structures), mais pour le reste.... ca prends pas beaucoup de temps et si tu développes un spécification, tu vas avoir du mal a donner du sens a tes opérations, si la construction, l'affectation, etc ne sont pas définis
Marsh Posté le 29-01-2003 à 15:05:27
++Taz a écrit : je savais pas que ca avait un nom |
+1
Marsh Posté le 29-01-2003 à 15:23:04
+1
Marsh Posté le 29-01-2003 à 15:47:54
Dans le mesure de possible (c'est-à-dire TRèS, TRèS rarement, voir TROP rarement) je respecte la norme ...
Un responsable comme le tient, j'en veux, cela va me changer
Marsh Posté le 29-01-2003 à 16:11:13
Moi aussi au début je respectais cette norme... c'était au temps (pas très lointain) des études. Par la suite, pendant un stage, je n'ai pas forcément respecté la norme tout le temps, car ça n'était pas tout le temps nécessaire d'après moi.
Mais bon, au niveau professionnel, sur des projets importants, je suis pour le respect de la norme, car on a besoin de normes au niveau professionnel... et surtout c'est pas pour le temps que ça prend de la respecter que la rentabilité s'en sentira affectée !
Bon, maintenant que je bosse pour de vrai je fais du C alors...
Marsh Posté le 29-01-2003 à 16:15:20
Tout ce qui peux réduire l'implicite dans un programme est bon à mon sens : l'implicite est une des principales sources de bugs.
Marsh Posté le 29-01-2003 à 16:17:06
heuh non, mine de rien c'est quand meme pas souvent que je m'amuse a faire de la recopie d'objet, alors perdre du tps a faire des operateurs qui servent a rien ....
Marsh Posté le 29-01-2003 à 16:21:43
Moi je vois déja une utilité évidente à cette norme : l'obligation de spécifier un constructeur par défaut !
Indispensable si on souhaite créer un tableau d'objets, étant donné qu'on ne peut pas passer un constructeur à l'opérateur new[]
Marsh Posté le 29-01-2003 à 16:25:39
Harkonnen a écrit : Ma question est : pour ceux parmi vous qui programment professionnellement en C++, déclarez-vous vos classes selon la forme de Coplien ? J'aimerais bien savoir si notre new responsable est un modèle unique ou pas |
non. ça peut arriver que des constructeurs soient private (instanciation factory friend). pour la duplication, les pointeurs sont définis dans un tableau statique (half life, mfc) ... ça permet de prendre en compte les nouvelles références automatiquement.
ensuite, les règles faut voir ... par exemple préfixer les variables membres par un m : membre -> mMembre. très bien, mais
class vector4
{
float mX, mY, mZ, mW;
}
?
PWARK !
bref les règles je suis pour, faut juste voir leur limites et ne pas essayer de tout mettre dans le même sac lorsqu'il n'y en a pas besoin.
Marsh Posté le 29-01-2003 à 16:28:11
j'ai horreur des variables membres préfixées par m, m_ ou _...
Marsh Posté le 29-01-2003 à 16:29:02
lorill a écrit : j'ai horreur des variables membres préfixées par m, m_ ou _... |
moi aussi. mais quand tu es en minorité dans l'équipe, faut bien faire avec.
Marsh Posté le 29-01-2003 à 17:20:50
chrisbk a écrit : heuh non, mine de rien c'est quand meme pas souvent que je m'amuse a faire de la recopie d'objet, alors perdre du tps a faire des operateurs qui servent a rien .... |
t'es pourtant bien content quand de pouvoir faire du passage par valeur...
Marsh Posté le 29-01-2003 à 17:23:08
moi je rajouterais dans la liste la fonction membre swap. ca ne sert pas toujours, mais des fois c'est un gain de performance incroyable. ca coute rien de supplémentaire a ecrire puisque qu'apres operator= devient un swap de this avec une copie passeé en paramètre. que du bon
Marsh Posté le 29-01-2003 à 17:35:12
++Taz a écrit : ca coute rien de supplémentaire a ecrire puisque qu'apres operator= devient un swap de this avec une copie passeé en paramètre. que du bon |
aïe ma tête !
j'ai essayé de comprendre mais j'ai vite abandonné, il est trop tard... je suis le seul à trouver cette phrase un peu confuse ? (je ne conteste pas, j'ai pas compris )
Marsh Posté le 29-01-2003 à 17:37:33
Code :
|
Marsh Posté le 29-01-2003 à 17:44:26
remarquez aussi qu'avec la forme que je présente on laisse toutes les désallocations au destructeur. sans ça, il faut s'en cogner un petit morceaux dans operator, réallouer, recopier, tout à la main, bref c'est lourd et on peut se tromper facilement.
la sémantique de swap est clair et facile à implémentée: pour des variables simples, une petite temporaire et c'est bon, et s'il y a des pointeurs, la c'est tout bonnement le gros lot.
vraiment j'aime cette méthode, elle me simplifie beaucoup la tache
Marsh Posté le 29-01-2003 à 17:53:06
++Taz a écrit : t'es pourtant bien content quand de pouvoir faire du passage par valeur... |
certes, mais je passe rarement mes objets par valeur.
les m_ au début je souffrais, maintenant je m'y suis fait. ca évite les blagues du genre "shadower" une variable membre par une locale....
Marsh Posté le 29-01-2003 à 17:57:42
-Wshadow
sinon il m'arrive je rajoute un joli "my" aux membres
Marsh Posté le 29-01-2003 à 18:27:07
chrisbk a écrit : |
Moi en C++, je n'accède aux champs membres qu'au travers de this ou du nom de la classe (pour les champs statiques). Comme en Java d'ailleurs. Ainsi, on sait toujours d'où vient le symbole dans le corps d'une méthode : champ membre ou variable locale. Et en plus, la plupart des éditeurs modernes le mettent d'autant plus en relief qu'ils colorient le mot-clé "this"...
Et par expérience, le source n'en est pas vraiment alourdi.
Marsh Posté le 29-01-2003 à 19:58:00
Harkonnen a écrit : |
Je suis encore étudiant, mais il est hors de question pour moi de créer un objet qui ne respecte pas l'invariant, pour des raisons de qualité. C'est très courant (quasiment tout le temps) que dans l'invariant il soit interdit d'avoir un pointeur à null, il peut arriver que les int soient interdits d'être à 0 etc. Donc tu fout quoi dans ton constructeur sans argument ? il a quelle utilisation ton objet qui a été construit avec des valeurs par défaut ?
Il est courrant aussi, par ex. qu'il soit intedit de recopier un objet (Singleton, Flyweight) donc pour eux, interdiction de foutre un contructeur par recopie !
Par contre, un mec qui écrit une méthode qui prend un pointeur en paramètre et qui ne vérifie pas que le pointeur n'est pas nul (très souvent c'est une précondition implicite) en assertion, je vais l'engueuler, ça me parraît évident.
Bien sûr, dans l'autre sens, si la présence d'un constructeur par défaut à du sens est nécessaire, il faut le mettre, ça me parraît évident. Le vrai problème est l'appel implicite (et s génération) de ce constructeur dans certaines situations en C++, peut-être faut-il le mettre systématiquement qui lève une exception (genre un {assert false}) afin de virer tous les appels implicites. Mais ceci n'est là que pour palier à une (des) faiblaisse du langage.
Donc non, pas d'écriture systématique de n'importe quoi, par contre écriture de ce qui est nécessaire (sauf bien entendu que y'a toujours une structure à la con qui va appeller un truc qu'il aura générer et pêter ton beau model objet, mais si tu veux de la qualité, tu utilises pas C++).
Marsh Posté le 29-01-2003 à 20:45:13
tiens je connaissais pas le Flyweight pattern, tres interessant
Marsh Posté le 29-01-2003 à 20:59:23
++Taz a écrit : tiens je connaissais pas le Flyweight pattern, tres interessant |
Fais du smalltak.
Faites tous du smalltalk
C'est certes un langage dépassé mais c'est le meilleur pour l'apprentissage, y'a un flyweight direct quand tu arrives (tu peux pas faire un #become: sur les Characters et les SmallIntegers).
Y'a le MVC, y'a des singletons (true, false et nil, au début). Y'a des factories (toutes les classes ne sont en fait que des factories). Y'a des visiteurs (de tête, j'ai que celui qui est dans le compilo mais je suppose qu'il y en a d'autres).
Et y'en a encore une tonne des patterns là-dedans.
Marsh Posté le 29-01-2003 à 21:01:31
moi ce qui m'interesse c'est de les faire moi meme, pas de les utiliser (enfin pas avant d'avoir tout compris).
serait temps que je finisse un livre sur les D.P.
Marsh Posté le 30-01-2003 à 06:10:02
Je ne programme pas professionnellement, mais je l'ouvre quand même.
Harkonnen a écrit : Moi je vois déja une utilité évidente à cette norme : l'obligation de spécifier un constructeur par défaut ! |
Il ne me semble pas que le constructeur par défaut fasse partie de la forme de coplien.
Pendant qu'on y est: La protection contre l'auto-affectation en fait-elle partie ?
En tout cas faut pas l'oublier !
Plutôt que de s'obliger à tout de suite implémenter ces membres de façon triviale...
Plutôt que de les oublier, au risque d'utiliser des versions implicites inadéquates...
...les interdire:
Code :
|
Le compilateur ne manquera pas de signaler si il est temps de les fournir.
Les autres constructeurs, c'est au besoin.
Le destructeur, son besoin est logiquement groupé avec les deux zigotos ci-dessus, mais on peut pas l'interdire (essayez pour voir ) .
Quand aux membres, après bien des hésitations, je suffixe avec "_" les membres privés.
Devant c'est dangereux, car _+Majuscule est réservé au système. Ou minuscule, je sais plus...
Marsh Posté le 30-01-2003 à 09:01:48
Musaran a écrit : Il ne me semble pas que le constructeur par défaut fasse partie de la forme de coplien. |
Si, la forme cannonique de Coplien oblige à avoir au moins 4 méthodes :
- Un constructeur par défaut, avec absence de paramètres ou paramètres ayant une valeur par défaut.
Valable :
Code :
|
Non valable :
Code :
|
- Un constructeur de recopie
- Un destructeur (virtuel ou pas)
- Une surcharge de l'opérateur d'affectation
Marsh Posté le 30-01-2003 à 09:38:02
nraynaud a écrit : |
J'abonde.
Pour apprendre ce que c'est que la programmation objet, rien ne vaut le Smalltalk pour debuter. Et les deux tomes du Lalonde & Pugh (Inside Smalltalk) sont d'une lecture enrichissante.
A+,
Marsh Posté le 30-01-2003 à 10:07:21
J'ai lu très recemment quelques lignes à ce sujet sur ce site (notamment les articles "the law of the big three", "every class should have these methods" et "nice and regular functions" ). A ce propos, je trouve ce site (http://cpptips.hyperformix.com/cpptips.html) très intéressant.
Pour ma part, je ne respecte pas cette forme et ceci pour une raison majeure : je ne l'ai découverte que très recemment. Il est vrai cependant que c'est sûrement une bonne habitude à prendre dans la plupart des cas. Cependant, comme indiqué dans un article cité ci-dessus, un design ne doit pas dicter la réflexion du programmeur.
De plus, il me semble que le C++ (avec la STL) incite à évacuer tout ce qui ressemble de près ou de loin à un pointeur ; donc, dans la plupart des classes, l'affectation par défaut doit être suffisante.
BifaceMcLeOD a écrit : a écrit : ... l'implicite est une des principales sources de bugs. |
Je pense totalement le contraire ! Selon moi, si on est sûr que le comportement implicite est ce que l'on désire, il vaut mieux éviter de le réecrire. Moins il y a de code, moins il y a de bugs !
Harkonnen a écrit : a écrit : ...ce qui a provoqué une scission : les pour et les contre. |
On peut savoir quels sont les arguments des contres (à part la paresse ) ?
Marsh Posté le 30-01-2003 à 10:24:15
gatorette a écrit : On peut savoir quels sont les arguments des contres (à part la paresse ) ? |
Le principal argument a été : "On a tjs réussi à s'en passer, pourquoi se faire ch... maintenant ?"
Ce qui les emmerde le plus : le constructeur de copie et l'opérateur d'affectation. Certains se sont rendus compte qu'ils ne savaient même pas déclarer un constructeur de copie (ils oubliaient de passer une référence à l'objet en argument => boucle infinie !!)
Marsh Posté le 30-01-2003 à 10:41:16
Harkonnen a écrit : Le principal argument a été : "On a tjs réussi à s'en passer, pourquoi se faire ch... maintenant ?" |
on avait dit "à part la paresse" !
>> ils ne savaient même pas déclarer un constructeur de copie
ils ne savent pas faire de copier coller ?
Marsh Posté le 30-01-2003 à 10:54:44
Dans mon expérience, je pense aussi que l'implicite est mal. Je l'évite pour éviter les bugs. Rien n'est plus dangereux que d'assumer qu'un truc va faire ton travail à ta place. Si je veux que mon travail soit bien fait, je le fais moi-même (mouais pas terrible comme réflexion). Comme ça je peux m'en vouloir si j'ai couillonné et non pas en vouloir à la machine
Marsh Posté le 30-01-2003 à 11:25:07
youdontcare a écrit : on avait dit "à part la paresse" ! |
Il ne suffit pas de faire un copier/coller pour déclarer un constructeur de recopie ! Il faut déja lui passer une référence de l'objet à copier en paramètre. Pourquoi ? Pour la simple raison que si tu passes l'objet directement, une copie de cet objet sera créée, et donc appel au constructeur de recopie... celui que tu es en train de définir ! D'ou boucle infinie !
La plupart ne savaient même pas ça...
Marsh Posté le 30-01-2003 à 11:43:00
Harkonnen a écrit : Il ne suffit pas de faire un copier/coller pour déclarer un constructeur de recopie ! |
chez moi si ... "cher chef / cher google, quelle est la syntaxe pour X ?" puis ensuite copier coller. bref, au pire une heure à demander / chercher puis expérimenter avec la chose. si c'est tout ce qu'ils ont comme argument, ils sont plus contreproductifs qu'autre chose.
Marsh Posté le 30-01-2003 à 12:12:16
Ce que j'ai trouvé quand même énorme, c'est le fait que très peu ne mettaient de constructeur par défaut. Je me demande comment ils faisaient pour initialiser leurs variables membres quand ils déclaraient des tableaux d'objets...
Marsh Posté le 30-01-2003 à 14:15:37
Ben justement, voilà un cas d'implicite du langage qui conduit régulièrement à un bug dans la pratique. Et pas toujours simple à débusquer en plus.
Voilà pourquoi je n'aime pas trop C++. La seule manière d'éviter ce bug, comme beaucoup d'autres, est d'appliquer certaines règles strictes de programmation, comme la forme de Coplien (mais pas seulement).
Pourquoi dans ce cas a-t-on rendu le langage aussi permissif ? Ne serait-il pas plus simple que le compilateur impose lui-même le respect de ces règles (et si elles ne sont pas respectées, le programme ne compile pas, tout simplement) ?
Bien sûr, on aurait alors un compilateur beaucoup plus pénible pour les débutants, mais que d'heures gagnées dès que les programmes sont un tant soit peu complexes...
Marsh Posté le 30-01-2003 à 14:44:50
Puisqu'on parle d'implicite, j'aimerais bien arreter de lire d'utiliser la directive using pour utiliser les types d'un namespace (std en l'occurence).
Comme je le disais sur l'autre topic, cette directive est à proscrire absolument !!
Je m'explique : pourquoi a t'on implémenté les namespaces ? En grande partie pour éviter les conflits de noms ! Or, à mon avis, la directive using annule purement et simplement cet avantage.
Démonstration :
Code :
|
Encore un bel exemple d'implicite provoqué par une directive à mon avis faite pour arranger les fainéants.
Si vraiment on doit utiliser cette directive à cause d'un nom de namespace trop long, ne pas oublier qu'il est possible de créer des alias pour les namespace !
Marsh Posté le 31-01-2003 à 04:29:37
gatorette a écrit :
|
Deux excellents arguments parfaitement vrais qui s'opposent, oh le joli débat que voilà.
J'y réfléchis...
BifaceMcLeOD a écrit a écrit : Pourquoi dans ce cas a-t-on rendu le langage aussi permissif ? Ne serait-il pas plus simple que le compilateur impose lui-même le respect de ces règles (et si elles ne sont pas respectées, le programme ne compile pas, tout simplement) ? |
Parce que tu peut toujours avoir des raisons inattendues de faire des choses très tordues.
C++ ne t'empêchera pas de sauter dans le vide... ou de te tirer une balle dan le pied.
On pourrait juste souhaiter que le compilateur reconnaisse ces cas et émette une alerte.
Cependant il est envisagé que le C++ change pour que le destucteur soit automatiquement virtuel dès que quelquechose d'autre l'est dans la classe.
Je suis d'accord qu'un programme complexe en C++ requiert de beaucoup de discipline.
Harkonnen:
'using' permet justement d'échelonner le degré d'implicte voulu dans la recherche des noms:
Code :
|
Et dans les classes, c'est génial pour réactiver les membres masqués des classes de base, ou changer leur restriction d'accès.
Hmmm... l'implicite permet aussi de changer en douce la façon dont quelque chose est implémenté ou rangé.
C'est précieux pour les remaniements transparents de librairies.
Marsh Posté le 31-01-2003 à 10:23:42
Musaran a écrit : Deux excellents arguments parfaitement vrais qui s'opposent, oh le joli débat que voilà. |
En effet, les deux sont vrais. La subtilité vient du fait que j'ai précisé "si on est sûr que le comportement implicite est ce que l'on désire". Et c'est souvent là que le bât blesse.
En effet, j'imagine que des gens qui ne connaissent pas la déclaration du constructeur de recopie n'ont qu'une idée assez vague de son comportement implicite. Et évidemment, dès qu'ils ont une classe nécessitant une implémentation particulière, ils ne le font pas et ça provoque des bugs.
Par contre, j'utilise tous les jours sans m'en préoccuper plus que ça les conversions implicites de int en long (long mylong = 0;) et je ne me souviens pas avoir un jour eu un problème.
edit: couleurs, interversion de long et de int
Marsh Posté le 29-01-2003 à 14:56:55
Quand j'étais en cours, dans une autre vie, on avait abordé la déclaration des classes selon la forme de Coplien : une classe doit impérativement contenir un constructeur par défaut, un constructeur de recopie, un destructeur et une surcharge de l'opérateur d'affectation. A l'époque, on prenait l'habitude d'écrire de la sorte.
Puis, la vie professionnelle arrivant, la rentabilité, le manque de temps, etc... la forme de Coplien est un peu passée à la trappe !!
Or, on a reçu un nouveau responsable qui tient absolument à ce que nos classes respectent la forme de Coplien, ce qui a provoqué une scission : les pour et les contre.
Personnellement, je suis pour. Ne serait-ce que pour le constructeur par défaut, c'est très utile.
Ma question est : pour ceux parmi vous qui programment professionnellement en C++, déclarez-vous vos classes selon la forme de Coplien ? J'aimerais bien savoir si notre new responsable est un modèle unique ou pas
---------------
J'ai un string dans l'array (Paris Hilton)