Développer une application peut rapidement devenir un enfer si vous n'avez pas anticipé certaines difficultés et fait les bons choix au moment de sa conception. Ce livre vous aidera à vous poser les bonnes questions et à tirer le meilleur parti de la programmation objet, en particulier en C++, sans tomber dans les pièges les plus fréquents. Il clarifie certains concepts délicats et passe en revue un ensemble de bonnes pratiques, qui rendront vos projets plus évolutifs et plus faciles à maintenir.
Organisé en quatre parties, ce livre traite successivement des principes de base, des fondements de la programmation orientée objet et des spécificités du C++ pour finir sur une étude de cas complète (création d'un jeu d'échecs en 3000 lignes) qui montre comment les mettre en œuvre dans la pratique.
L'auteur insiste sur la nécessité d'anticiper les évolutions sans tomber dans l'écueil de l'over-engineering, il met en relief des erreurs courantes comme le fait de tester, d'une manière ou d'une autre, le type dynamique (réel) d'un des objets qu'on ne connaît que sous la forme de leur type de base pour décider de l'utilisation qu'on en fera. Il fournit ensuite un exemple illustrant le risque encouru. Plus spécifiquement sur le C++, il invite à renoncer définitivement à certaines habitudes du C totalement injustifiées en C++, il clarifie l'emploi des pointeurs et des références, il encourage à recourir à la constance, il montre comment tirer parti de la forme canonique de Coplien (constructeur par défaut, constructeur par copie, operateur d'affectation et destructeur virtuel ou non), etc. L'étude de cas vise avant tout à illustrer plus concrètement comment mettre en pratique, avec pragmatisme, ses recommandations.
Ce livre n'est pas un manuel d'apprentissage du C++. Un autre ouvrage du même auteur dédié au C++14 est en cours de rédaction.
Tous les exemples sont en C++11. En présentation, la situation où l'on souhaite une valeur numérique constante. Il y a plusieurs manières de les déclarer.
- À l'aide du préprocesseur. Mais il n'y a aucun contrôle sur le type de données.
#define FIRST 1
#define SECOND 2
#define LAST 0xFF
- À l'aide de constantes statiques. Cette méthode corrige le problème du type de données. Néanmoins, le fait d'énumérer correctement tous les cas dans un test reste le problème du programmeur.
static const unsigned int first = 1;
static const unsigned int second = 2;
static const unsigned int last = 0xFF;
- Le cas d'une énumération, en bonne et due forme, règle pas mal de ces problèmes.
enum MyEnum{
first = 1;
second = 2;
last = 0xFF
}
Il s'en suit alors quelques pages présentant les nouveautés et les bons usages du C++11 sur les énumérations.
L'auteur Philippe Dunski est expert en C++/Qt/boost et il intervient régulièrement sur developpez.com pour aider les autres membres. Il écrit de manière très personnelle et vivante, ce qui rend la lecture du livre très agréable, même sur les aspects les plus pointus.
Aller plus loin
- Présentation du livre sur le site de l'éditeur (1636 clics)
- Entretien avec l'auteur (289 clics)
- Sommaire détaillé (747 clics)
- Présentation de l'éditeur D-BookeR sur LinuxFr.org (243 clics)
# Ca a l'air intéressant comme bouquin
Posté par fox . Évalué à 5. Dernière modification le 14 avril 2014 à 22:10.
Ce livre ne se rapprocherait-il pas du même genre que "Coder proprement" ("Clean Code" en VO) qui est orienté plutôt Java ?
[^] # Re: Ca a l'air intéressant comme bouquin
Posté par xules . Évalué à 3.
Sans avoir lu celui-ci, il annonce au moins la couleur en précisant "en C++", contrairement a "Coder proprement" qui est "plutôt beaucoup" orienté java alors que rien ne l'indique explicitement
[^] # Re: Ca a l'air intéressant comme bouquin
Posté par vieuxshell (site web personnel) . Évalué à 4.
Clean Code n'est pas orienté java. C'est applicable à n'importe quelle langage, avec un net tropisme autour des langages objets néanmoins.
[^] # Re: Ca a l'air intéressant comme bouquin
Posté par arnaudus . Évalué à 4.
Franchement, j'ai un peu de mal avec la notion de coder proprement sans faire référence au langage. À part des généralités triviales (commenter son code, donner des noms de variables signifiants, nommer les constantes, etc) qui prennent 2 ou 3 pages à énoncer, on rentre forcément dans les bonnes pratiques du langage. Comment parler des constantes sans parler de #define ou des enum? Comment définir un bon découpage des fichiers sans faire référence au langage? Je pense qu'un bouquin qui ne fait pas référence au langage sur sa couverture a de fortes chances d'être totalement inutile : soit trompeur (il porte sur un seul langage, avec très peu de chances que ça corresponde aux besoins du lecteur), soit trivial.
[^] # Re: Ca a l'air intéressant comme bouquin
Posté par barmic . Évalué à 9.
« Design Patterns – Elements of Reusable Object-Oriented Software » fait environ 500 pages, il est utile pour n'importe quel langage orienté objet à classe (il est moins utile pour les langages à typage dynamiques comme python ou ruby c'est vrai). Il est utile pour n'importe quel programme C++, C#, Java, Objective-C, probablement ADA récent et pour un tas d'autres langages.
On doit pouvoir sortir un livre en retirant les recettes du livre « The Art of Computer Programming ».
Même si se baser sur un langage est pratique et permet d'aller plus en profondeur, il y a tout de même un paquet de choses qui sont assez génériques.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: Ca a l'air intéressant comme bouquin
Posté par arnaudus . Évalué à 3.
Bah, on ne parle pas de la même chose. Les designs patterns sont des abstractions de la structure d'un programme OO, le bouquin n'a pas la prétention d'expliquer comment on code proprement. Il s'agit de choses qu'on peut traiter en pseudocode par exemple, ça serait la même chose avec un bouquin sur la programmation fonctionnelle ou les algorithmes de tri…
Par ailleurs, la programmation object n'est pas un truc monolithique. La plupart des langages implémentent au moins des pseudo-classes (voire de simples listes) qui peuvent être utilisées pour mimer de la programmation objet, mais certains patterns nécessitent par exemple de l'héritage multiple ou des classes virtuelles, et là, on tombe tout de suite sur une poignée de langages.
Pour revenir au sujet du bouquin, les pires conseils que je n'ai jamais lus sur comment écrire du code propre venait de gens qui appliquaient des recettes qu'ils connaissaient sur leur langage de prédilection sur un autre langage: indenter du C++ comme on le fait en python, mettre une fonction par fichier en perl, terminer les lignes par un point-virgule alors que c'est optionnel dans le langage, etc.
[^] # Re: Ca a l'air intéressant comme bouquin
Posté par lolop (site web personnel) . Évalué à 4.
Kerzut, c'est mon cas. Sauf que j'ai commencé à faire comme cela en codant en C/C++, avant même de connaître Python, en mettant les accolades au niveau du bloc qu'elles encadrent - la recherche de l'accolade correspondante et la visualisation du bloc de code concerné sont immédiats.
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Ca a l'air intéressant comme bouquin
Posté par arnaudus . Évalué à 2.
Mouais, c'est difficile de dire que c'est le mal absolu, mais le principe des conventions, en général, c'est que ça simplifie la vie de tout le monde quand elles sont respectées. Si dans ta fonction x c'est l'ordonnée et y c'est l'abscisse, il n'y a pas vraiment de faute de programmation, mais ça pourrit quand même la vie des autres.
[^] # Re: Ca a l'air intéressant comme bouquin
Posté par lolop (site web personnel) . Évalué à 2.
Tu indenterais comment les déclarations de paramètres ?
(note: si je tombe sur un code d'un projet qui a déjà défini ses conventions, il va de soit que je les reprend - mais pour un code privé perso…)
Votez les 30 juin et 7 juillet, en connaissance de cause. http://www.pointal.net/VotesDeputesRN
[^] # Re: Ca a l'air intéressant comme bouquin
Posté par lmg HS (site web personnel) . Évalué à 2.
C'est le style Whitesmiths. J'ai un mal de chien avec ce truc sur les projets qui l'exigent. J'oscille entre le style Allman et K&R/Stroustrup quand j'ai le choix.
Plus d'infos là: http://en.wikipedia.org/wiki/Indent_style
[^] # Re: Ca a l'air intéressant comme bouquin
Posté par lmg HS (site web personnel) . Évalué à 6.
Il ne faut pas se leurrer, il y a beaucoup de concepts qui transcendent les langages. Toute la partie OO sur SOLID et Déméter est applicable à tous les langages OO mainstream. Et ce n'est pas parce que c'est indépendant du langage qu'il ne faut pas les traiter!
Après, il ne faut pas s'inquiéter, le livre est définitivement orienté C++. Quand Philippe/koala aborde des principes comme l'ISP, il le fait selon un angle C++.
(Et vous pouvez rajouter toutes les spécificités du C++ en plus: RAII, valeur vs entité, …)
[^] # Re: Ca a l'air intéressant comme bouquin
Posté par CrEv (site web personnel) . Évalué à 4.
Et ben je ne pense pas.
Par exemple un bouquin que j'ai vraiment apprécié est Tout sur le code (ou Code complete pour la version anglaise). Ce bouquin ne s'adresse pas à un langage précisément mais utilise des exemples dans plusieurs langages pour illustrer ses propos. Et le résultat est plutôt intéressant.
C'est justement un bouquin que j'aime bien parce qu'il ne cible pas un langage. Ce qui fait qu'il peut être lu par n'importe quel développeur. Et il ne tombe pas dans le côté trivial.
# C'est pourtant évident.
Posté par Enj0lras . Évalué à 5.
La liste des erreurs à éviter tient en une ligne :
[^] # Re: C'est pourtant évident.
Posté par lecteur . Évalué à 2.
Record battu !!
http://linuxfr.org/nodes/101384/comments/1525023
[^] # Re: C'est pourtant évident.
Posté par Enj0lras . Évalué à 0.
En fait le nouvel affichage est beaucoup plus utile pour detecter les trolls. Un moyen pour filtrer les commentaires en prenant compte le fait qu'il y a beaucoup de votes en plus de la note, ça peut permettre aux gens qui ont envie de filtrer plus simplement le contenu.
[^] # Re: C'est pourtant évident.
Posté par barmic . Évalué à 1.
Ce n'est pas tant le nombre que l'équilibre entre « pertinent » et « inutile » quelque chose du genre :
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
[^] # Re: C'est pourtant évident.
Posté par Pascal Obry (site web personnel) . Évalué à -5. Dernière modification le 17 avril 2014 à 11:02.
100% d'accord. Le C++ est un langage trop complexe et dangereux, il ne devrait certainement pas être utilisé dans des codes ou la fiabilité est critique. Malheureusement c'est encore le cas!
Un bon langage ne devrait pas avoir besoin de ce type de livre pour éviter les erreurs. Elles devraient être éviter autant que possible lors de la conception. Evidemment c'est plus facile à dire qu'à faire et même si c'est un but il est difficilement atteignable. Il a cependant différents langages sur le marché et il faut bien avouer que le C++ n'est pas dans le top des langages fiables, compréhensibles et maintenables.
[^] # Re: C'est pourtant évident.
Posté par lmg HS (site web personnel) . Évalué à 4.
Ce type de bouquin est loin de traiter des choses qui sont spécifiques au C++. C'est d'ailleurs le sens que j'avais voulu donner dans la préface : dans les difficultés du C++, il y a celles du génie logiciel, celles du monde OO, celles du métier à traduire, etc. Plus celles spécifiques au C++.
Et ces dernières sont des difficultés essentiellement parce que les développeurs sont restés avec leur idées préconçues d'un C avec classes où la mémoire se gère à la main, et où les erreurs se remontent à la main. C'est sûr que ça ne scale pas et que ce type de programmation ne peut que nous exploser à la figure. Je traduis cela comme un problème de formation. D'où ce type de livre (celui dont on parle, mais aussi les XC++ de Sutter, le C++ Coding Standards de Sutter & Alexandrescu, etc. qui vont tous traiter du RAII).
Et BTW, j'attends toujours de voir le langage maintenable (et donc à la philosophie compréhensible par tout le monde, ce qui tend à exclure les langages fonctionnels qui ne sont pas dans les moeurs), sécurisé, et tout et tout.
[^] # Re: C'est pourtant évident.
Posté par Pascal Obry (site web personnel) . Évalué à 3.
Pour les langages, rien de parfait mais je trouve qu'Ada va dans le bon sens et aide énormément à la construction de projets larges et fiables. J'ai aussi assez été bluffé par le langage Eiffel mais qui malheureusement semble s'évanouir progressivement.
[^] # Re: C'est pourtant évident.
Posté par Diagonale de Cantor (site web personnel) . Évalué à 7. Dernière modification le 17 avril 2014 à 13:52.
Ben forcément si tu refuses la réponse par principe…
La programmation fonctionnel à l’immense avantage :
— d’avoir un système de type excellent : en Caml ou Haskell, si ça compile c’est qu’à priori il n’y a pas de bug (évidemment il peut rester des bugs, mais le gros des bugs ne passe pas la compilation) ; par contre erlang est moyen de ce côté là
— d’avoir une gestion de la mémoire facile et locale : la seule subtilité c’est la récursion terminale, mais c’est pas non plus compliqué à comprendre et ça ne concerne à chaque fois qu’une fonction. Locale parce que si aucune fonction n’as de fuite mémoire (comprendre récursion non terminal) tu sais que ton code entier n’as pas de fuite.
— gère le multi threading de manière naturelle (cf Erlang)
Je ne dis pas que c’est l’alpha et l’omega et que tout est parfait. Mais si tu veux un langages maintenable la solution consiste peut-être à changer de paradigme ! C’est justement la raison qui à pousser Erlang à ne pas être objet ; cf un article du fondateur du langage : http://harmful.cat-v.org/software/OO_programming/why_oo_sucks
Je programme trop peu pour dire que l’objet pue et que le fonctionnel déchire ; mais si tu ne trouve aucun langage objet/impératif maintenable, peut-être que le problème c’est l’objet/impératif et c’est idiot de refuser par principe d’autre paradigme.
[^] # Re: C'est pourtant évident.
Posté par lmg HS (site web personnel) . Évalué à 2.
Je réfute le fonctionnel en production car la logique de pensée n'est pas compatible avec l'immense majorité des développeurs sur le marché. Ce n'est pas "par principe". Loin de là.
Je reconnais volontiers les qualités des langages que tu cites, mais fait voir les réactions quand on commence à suggérer OCaml en place de Python (par exemple).
Parenthèse. Sur les critiques de l'objet, Stepanov avait donné une conférence très intéressante où il parlait, entre autres, du pourquoi la STL (une des grosses parties de la bibliothèque standard du C++) n'est pas OO. (là, à priori: http://video.google.com/videoplay?docid=-7867514878945314586)
[^] # Re: C'est pourtant évident.
Posté par Diagonale de Cantor (site web personnel) . Évalué à 3.
Je comprend ton point de vu mais je trouve dommage que l’immense majorité des développeurs ne peuvent pas apprendre un nouveau paradigme. D’autant plus si celui ci permet d’écrire des programme plus concis, moins buggés, d’avantage maintenable…
Pour ta vidéo, tu aurais un lien sans erreur 404, ça m’intéresse.
[^] # Re: C'est pourtant évident.
Posté par lmg HS (site web personnel) . Évalué à 1.
Désolé. Avec les proxys je ne pouvais pas vérifier. Il ne me reste que le titre: Donc, une conf d'Alexander Stepanov: "STL and Its Design Principles" (2002)
[^] # Re: C'est pourtant évident.
Posté par Ignatz Ledebur . Évalué à 10. Dernière modification le 20 avril 2014 à 20:12.
Ça me rappelle un entretien accordé par Brian Kernighan :
Personnellement, j'ai naguère essayé de me mettre à Ocaml, malheureusement tous les tutos que j'ai alors trouvés étaient effectivement très orientés "matheux" ; le genre plein de formules incompréhensibles pour moi et se paluchant longuement sur les suites de Fibonacci, sans jamais expliquer comment simplement récupérer/reverser les données dans un fichier (le B-A-BA du truc utile, quoi).
[^] # Re: C'est pourtant évident.
Posté par Enj0lras . Évalué à 4.
J'ai des amies qui font des études de langues, et qu'on n'ont aucune formation mathématique ni informatormatique derrière. Il semble bien que ocaml ne soit pas beaucoup plus compliqué à apprendre que java ou python (il y a les 3 dans la licence).
Je pense que ton point de vu est biaisé. Parce qu'un langage fonctionnel est compliqué à apprendre pour quelqu'un qui a été formé à pensé avec des des langages objets et impératifs, tu en déduis qu'il est nécessairement plus compliqué pour des néophytes totals d'apprendre les langages fonctionnels. Hors, justement, ça ne l'est pas. Tu réproduits des schémas qui s'appliquent à ton cas (enfin, ne prends rien personnellement). Hors, dans le cas ou tu maitrises déjà C++/autre, il ne te faut pas simplement apprendre, il te faut aussi et surtout désapprendre avant de pouvoir ré-apprendre. Ce qui induit une complexité qui n'est pas du tout présente pour les gens qui n'ont rien à désapprendre du tout.
j'ai moi même commencé avec un langage fonctionnel et je trouve au contraire extremement compliqué d'apprendre des langages objets/impératifs qui dépassent la simplicité du C. (simplicité au sens des concepts mis en jeux).
[^] # Re: C'est pourtant évident.
Posté par Anthony Jaguenaud . Évalué à 3.
J'ai regardé haskell suite à la dépêche. J'ai lu l'intégralité du tuto en lien à la dépêche. Si j'ai compris certains trucs, il me manque de l'expérience. J'ai commencé le BASIC-A en 1986, puis Turbo-Pascal, ASM, … Aujourd'hui, je pense clairement algorithme impératif.
Je me souviens du Prolog à la FAC et en stage, où après avoir réappris à penser, c'était facile. Mais dans le milieu professionnel, je n'en ai jamais refait.
C'est une approche différente. As-tu des TP avec des exercices à essayer qui sont adapté à la programmation fonctionnelle ? car je crois que c'est ce qui me manque le plus pour le moment.
[^] # Re: C'est pourtant évident.
Posté par Enj0lras . Évalué à 2.
Ça demande réfléxion, mais le seul truc qui me vient à l'esprit dans l'instant c'est cet article :
http://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf
Il ne s'agit pas d'exercices mais je trouve qu'il est très bon pour ce qui est d'expliquer les points centraux de la programmation fonctionnelle.
[^] # Re: C'est pourtant évident.
Posté par chimrod (site web personnel) . Évalué à 4.
J'ai beaucoup aimé le livre le langage caml qui est une introduction à la programmation et caml. La partie caml est aujourd'hui dépassée, mais les exemples donnés (tour de hanoi, tri rapide) sont très pragmatiques. (J'ai trouvé aussi très amusant l'aspect récursif du livre, mais il se peut que ça ne fasse rire que moi…)
Beaucoup plus théorique, il y a le typeclassopedia que l'on peut aussi trouver en pdf qui fait le tour sur la notion de foncteur. L'article ne fait pas seulement le tour des foncteurs existants, mais donne du sens à chacun d'eux. Le but n'est pas de les connaître tous mais de les comprendre.
Sinon je vais suivre cette discussion car je suis aussi intéressé de voir ce que les uns et les autres vont recommander…
[^] # Re: C'est pourtant évident.
Posté par j_m . Évalué à 2.
Les exemples pourraient être implémentés avec de simple fonctions récursives dans un langage impératif. Où est la différence ?
Comment est-ce qu'on contrôle la taille de la pile de mémoire de ces fonctions ?
[^] # Re: C'est pourtant évident.
Posté par Diagonale de Cantor (site web personnel) . Évalué à 6. Dernière modification le 18 avril 2014 à 23:33.
si tu décides par exemple de calculer factorielle n en impératif tu feras quelque chose comme
En mémoire c’est constant (tu n’as que deux variable
fact
eti
)En récursif tu aurais quelque chose comme :
Le problème c’est que la pile grandit beaucoup car en pratique, l’ordinateur déplie le calcul
fact(fact(fact…fact(0))))
et quand il y a beaucoup d’appel récursif tu as un débordement de piles.Maintenant dans certain cas, tu peux optimiser un appel récursif, le compilateur le transformant en boucle while. Pour cela il faut que ton code soit récursif terminale. Exemple :
Tu remarques que avec cette écriture, la dernière opération que fait la fonction
fact
est de s’appeler elle-même (alors que dans l’exemple précédant elle faisait un multiplication après). Dans le cas d’un compilateur d’un langage fonctionnel digne de ce nom, tous les fonctions avec appel récursif terminal sont automatiquement optimisées en boucle par le compilateur.Donc pour résumé, la récursion est optimisés (dans certain cas) dans les langages fonctionnelles et pas chez les langages impératifs.
Cette histoire de récursion terminal est LE point important de la gestion mémoire des programmes fonctionnelles ; toute fonction non terminale est à bannir dans le cas où les appels récursifs sont nombreux. Mais vu que chaque boucle while peut être implémenter en tant que fonction récursives avec appel terminal, on ne perd aucune expressivité par rapport aux langages impératifs.
[^] # Re: C'est pourtant évident.
Posté par lasher . Évalué à 5.
C'est faux. GCC le fait, ICC le fait, MS-VC++ aussi. Si tu mets ta fonction sous forme récursive terminale, n'importe quel compilateur optimisant un minimum moderne sait transformer la récursion terminale en boucle. En fait, GCC sait faire de l'optimisation de récursion terminale depuis au moins la version 2.95 (pour rappel, on en est à GCC v4.8).
Encore pire, il existe tout un tas de cas où GCC va faire du « pattern matching » et reconnaître une forme récursive d'un algo, ou en tout cas un idiome récursif « facile » à transformer en récursion terminale, et du coup effectuer la transformation…
Bref, à moins qu'un compilateur pour langage fonctionnel ait des mécanismes permettant de plus facilement convertir une récursion « normale » en récursion terminale¹, il n'y a absolument aucun avantage en termes d'optimisation à choisir un langage fonctionnel plutôt qu'impératif.
J'aime bien les langages fonctionnels, mais une fois que n'importe quel programme, écrit dans n'importe quel langage, a été correctement analysé (analyse lexicale, grammaticale, sémantique, blah), on se retrouve avec un arbre de syntaxe abstrait, c'est-à-dire une représentation intermédiaire qui permet de « visualiser » un programme sous forme de graphe de dépendance (de données, de contrôle, etc.), et autres machins. À partir de là, on peut commencer à effectuer des transformations sur le programme, à « marquer » les nœuds qui pourraient être groupés avec d'autres, ou même supprimés, etc.
Par contre, là où les langages fonctionnels ont tendance à briller (je trouve), c'est dans la façon dont ils manipulent plus souvent des « valeurs » que des variables. En gros, souvent les langages fonctionnels proposent un mode qui tient plutôt du « write-once » par défaut, qu'on peut explicitement invalider si on veut des effets de bord, alors que les langages impératifs ont tendance à autoriser les variables à être modifiables par défaut, et il faut ensuite mener une guerre méthodologique pour placer autant de constantes que possibles pour se prémunir contre les effets de bord non désirés.
[1] Et pour le coup je ne vois pas du tout comment ce serait possible…
[^] # Re: C'est pourtant évident.
Posté par Diagonale de Cantor (site web personnel) . Évalué à 5.
Le C peut le faire ?? Je me coucherai moins bête ce soir !
C’est imprécis mais c’est pas faux. Dans les langages fonctionnel la récursion terminal est dans la norme car sans elle tu ne peux rien faire ; je doute fortement qu’elle soit dans une norme C ou C++… Donc tu ne peux pas vraiment te baser dessus si tu veux faire un programme portable.
Si j’en croix le site http://blog.fastconnect.fr/?p=174 on a
— Le C, ok pour certain compilateur avec certaine option s’optimisation
— Pour Java
— Python ne le fait pas
— Ruby c’est pas dans la norme
— F# le fait (fonctionnel) mais
Pour résumer l’optimisation est présentes chez tout les langages fonctionnelles dans la norme ; présent accessoirement chez quelque compilateur de certains langages impératifs et absent dans beaucoup d’autre.
Après personne ne dit qu’il faut utiliser des langages fonctionnel uniquement pour cette optimisation ; mais plutôt que sans cette optimisation tu ne peux pas vraiment faire de programmation fonctionnelle.
La programmation fonctionnel est intéressante davantage pour ses variables immutables, son système de type, ses facilité de parallélisation, etc.
[^] # Re: C'est pourtant évident.
Posté par claudex . Évalué à 7.
Et Rust ne le supporte pas non plus, parce c'est trop chiant à gérer proprement
« Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche
[^] # Re: C'est pourtant évident.
Posté par Pascal Obry (site web personnel) . Évalué à 3.
Ça n'a aucun sens. La récursion terminale n'a rien à voir avec le C (comme tu le précise par la suite d'ailleurs) car ce n'est pas une propriété du langage. Un mauvais compilateur C ne le fera pas, un bon le fera. On parle ici d'implémentation du langage et pas du langage lui même. GCC donc le fait, et il le fait pour le C, le C++ et l'Ada. Je pense, mais ne peut pas l'affirmer, que GCC (le middle end du compilateur en fait) le fait pour tous les langages qu'il supporte.
Pourquoi n'est pas une propriété du langage? Parce que lorsque l'on écrit N * F (N-1) on exprime tout simplement une expression récursive sans considérer un seul instant l'implémentation et c'est tant mieux car l'implémentation est du ressort du compilateur. A lui de faire au mieux sans nous demander de préciser explicitement quoi que ce soit. Chacun son niveau d'expression et d'abstraction.
Donc ok ce n'est pas dans la norme C, ni dans la norme Ada mais c'est ce que fait tout bon compilateur car la récursion terminale n'est pas très difficile à transformer en boucle standard.
[^] # Re: C'est pourtant évident.
Posté par Zylabon . Évalué à 3.
D'ailleurs cela fait parfois apparaitre des bugs étranges, par exemple qui se manifestent en
-O0 -g
et pas en-O2
.Il y a aussi des langages qui garantissent que l'optimisation est faite. Typiquement scheme.
Quelqu'un sait ce qu'il en est d'Haskell et d'OCaml par exemple ? Quand on écrit un programme avec une boucle infinie genre un shell, on s'attend à ce qu'il n'utilise pas de plus en plus de mémoire.
Please do not feed the trolls
[^] # Re: C'est pourtant évident.
Posté par chimrod (site web personnel) . Évalué à 2. Dernière modification le 20 avril 2014 à 00:21.
OCaml le gère sans problème au niveau du compilateur, mais la bibliothèque de base n'est pas implémentée pour l'utiliser sur des opérations de base (par exemple List.map) !
Dans la pratique personne n'utilise la bibliothèque fournie par défaut, et se tourne vers des librairies tierces, qui elles le gèrent sans problème.
Edit : Et par rapport à un langage comme scala, il n'est pas possible de demander au compilateur de vérifier qu'une fonction est bien optimisée. En scala je crois que le mot clef « tailrec » va lever une exception s'il est appliqué à une fonction non optimisée.
[^] # Re: C'est pourtant évident.
Posté par lasher . Évalué à 7.
Non, ce n'est pas imprécis. tu dis que les langages impératifs ne permettent pas l'optimisation des fonctions récursives terminales. C'est factuellement faux, car comme le dit Turbo, l'important est de savoir si la forme est récursive « simple » ou bien récursive terminale. Et ceci est indépendant de la nature du langage (fonctionnel, impératif, etc.). En fait, les algorithmes qui transforment une récursion terminale en boucle sont connus depuis un moment, et il y a une équivalence automatique. Donc les compilateurs pour langages comme OCaml (ou F#), ou comme Scala, ou même Common LISP, qui sont tous multi-paradigmes, pourraient tous implémenter la récursion terminale en théorie. Ensuite, pour prendre l'exemple de Scala/Clojure/Java, il n'y a rien, ni dans la JVM, ni dans les langages eux-mêmes, qui empêche la transformation d'une fonction récursive terminale du type :
… en un code bas-niveau du genre (en pseudo-C) :
Étant donné que la JVM a une instruction
goto
pour le bytecode, transformer une fonction récursive terminale en boucle à l'aide d'ungoto
est trivial. Par contre il est possible que la machine à pile qui est à la base de la JVM ajoute des contraintes sur la façon de générer le code (je ne suis pas du tout expert ni même connaisseur du fonctionnement de la JVM).Concernant Python, Ruby, etc., il y a plein d'optimisations qui ne sont jamais faites dans ces langages, dues à la nature dynamique de ceux-ci (dynamique en termes de types, mais aussi pour la génération de code elle-même). Un truc qui serait optimisé dans beaucoup de cas en C+libC serait par exemple¹ :
Dans cet exemple, le compilateur C a le droit de transformer le code ainsi :
En Perl/Ruby/Python, de par la nature dynamique de ces langages, il faut nécessairement effectuer cette optimisation à la main. Maintenant, voilà le côté rigolo de ces langages : je connais mal Python, mais j'ai pas mal programmé avec Perl, et un peu avec Ruby. De ce que je vois, aucun de ces langages n'est purement impératif : ils ont tous des constructions fonctionnelles (par exemple :
map
etgrep
en Perl). Ils proposent des trucs genre les fermetures (closures en Anglais), qui sont apparues avec les premiers langages fonctionnels. De même, des langages impératifs destinés à la programmation parallèle, comme Habanero (Habanero Java, Habanero C, qui sont des dérivés sur langage X10) proposent des trucs qu'on trouve généralement dans les langages fonctionnels, comme le principe de future — et qui se trouve désormais aussi dans le standard de C++11. Tiens, en parlant de C++, la méta-programmation par templates se fait en effectuant de la programmation fonctionnelle (tout est « write once », tout est valeur).Enfin, j'ai une dernière remarque : les ordinateurs qui suivent le modèle d'exécution de von Neumann² sont par définition des machines qui fonctionnent selon un principe impératif/itératif : il y a un compteur de programme (PC), qui est incrémenté à chaque cycle (ou bien, en cas de branchement, à qui on affecte une nouvelle adresse pour la prochaine instruction). Il n'y a aucune trace de comportement fonctionnel. Tout le génie de ceux qui proposent des langages comme les dialectes de LISP, ML, Haskell, etc., est justement de proposer une façon d'exprimer les programmes sous une forme de bien plus haut niveau, non-impérative (et donc, permettant au programmeur de ne pas penser en termes de ce qu'attend la machine), mais de malgré tout réussir à convertir ces programmes à nouveau sous une forme impérative compréhensible par une machine de von Neumann de façon efficace.
Backus (le papa de Fortran) a d'ailleurs expliqué qu'il avait commis une grande erreur en créant Fortran, et que le futur devrait se construire sur la programmation fonctionnelle (le lien que je donne est son discours/sa présentation donné lors de son acceptation pour le prix Turing).
[1] Comme la libC est standard, elle est du coup « magique ». Le compilateur a le droit de faire des trucs étranges avec tant que ça respecte la sémantique des fonctions standard.
[2] Soit 99% des ordinateurs de la planète à travers les âges. Il y a des machines différentes, qui n'utilisent pas du tout les concepts de compteur de programme, mais elles ont malheureusement toutes échoué à dépasser les autres en termes de performances.
[^] # Re: C'est pourtant évident.
Posté par claudex . Évalué à 10.
Rien à voir mais ça fait deux fois que je te vois utiliser un semblant de note de bas de page, alors qu'il y a une syntaxe pour ça :
[^1]
pour la référence et[^1]: note
en fin de commentaire pour la note. Cela donne1note ↩
« Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche
[^] # Re: C'est pourtant évident.
Posté par lasher . Évalué à 2.
OoOoOOoh, je ne connaissais pas. Merci. :)
[^] # Re: C'est pourtant évident.
Posté par Diagonale de Cantor (site web personnel) . Évalué à 4.
Le problème c’est que ce n’ai pas une question d’optimisation mais de validité.
En Erlang le code
est valable ; c’est garantie par le langage que la pile n’explosera pas. En C ce n’est pas garantie. Ça change absolument tout ! Le code ne sera pas plus rapide ou non en fonction de cette optimisation (à peine), il sera par contre correct ou buggé ! Un boucle infinie implémentée avec une fonction récursive terminale est un bug en C car certains compilateurs respectant la norme ou certaine optimisation planteront systématiquement sur ce bout de programme. Ce n’est plus une simple question d’optimisation, mais une question de validité.
C’est imprécis parce que je n’ai jamais dit que c’était impossible de le faire en impératif, j’ai juste dit que c’était quelque-chose que, en pratique, on trouve dans les langages fonctionnels et pas impératifs. Et devine quoi, cette optimisation n’est quasiment jamais garantie par la norme des langage objet/impératif et quasiment systématiquement garantie par les celle des langages fonctionnel. Et pourquoi, parce que ce n’est pas vraiment important dans les premiers et fondamentale dans les seconds.
[^] # Re: C'est pourtant évident.
Posté par lasher . Évalué à 3.
Ce n'est pas garanti en C, mais en même temps, le C ne définit pas une notion de pile. Il existe de vieilles implémentations de C89 qui n'utilisent pas la pile pour les appels de fonction, sur des architectures un peu exotiques.
Mais tu mélanges deux choses :
Que Erlang te donne une garantie sur la transformation des tail calls, c'est très bien. Ça n'indique pas pour autant que la transformation récursion terminale → boucle est toujours effectuée dans les langages fonctionnels. Par exemple, pour Common LISP, presque tous les compilateurs sont capables de le faire, mais tous ne le font pas pour autant. Donc pour le deuxième point, c'est évidemment un plus si le langage garantit la transformation automatique, mais ça n'est (encore une fois) pas quelque chose de fondamentalement lié au côté fonctionnel ou impératif d'un langage. C'est juste que dans un langage fonctionnel pur, il n'y a pas de constructions de boucles, et donc si tu veux pouvoir garantir une certaine performance, il faut implémenter les tail calls sous forme de boucle.
[^] # Re: C'est pourtant évident.
Posté par lasher . Évalué à 3.
J'oubliais de répondre à ceci :
Le code que tu proposes, que je traduis en C ainsi :
… est récursif terminal, et est un programme valide en C. Comme je le disais précédemment, le C n'a pas de notion de pile (même si c'était je pense implicite dans les specs avant la normalisation du langage). Donc il n'y a pas de notion de dépassement de pile en termes de langage. Évidemment, en termes d'implémentation, le risque est grand.
Ceci étant dit, un langage comme Perl est capable d'effectuer des récursions bien plus profondes que ce qu'une simple pile UNIX propose, ce qui implique que la VM de Perl et le langage lui-même implémentent un truc permettre que cela arrive…
[^] # Re: C'est pourtant évident.
Posté par Diagonale de Cantor (site web personnel) . Évalué à 2.
Non ce n’est pas valide ! Un code valide c’est un code qui marche pour tout les compilateurs qui satisfont la norme ; pas seulement quelqu’un ! Et ce code à clairement un fuite mémoire sans l’implémentation de l’optimisation de la récursion terminale (ce qui est un bug).
La transformation d’appel récursif vers une boucle est une optimisation dans le cas des langages impératifs (ce n’est pas dans la norme) mais une fonctionnalité dans les langages fonctionnelles (garantie par la norme). En théorie ça pourrait être différent, mais en pratique c’est ce que l’on observe.
Cette différence de statut (fonctionnalité/optimisation) n’est pas un simple détail ! Elle change la façon dont on programme. En pratique personne ne programme en récursif en dehors des langages fonctionnels (en tout cas c’est minoritaire), ce n’est pas du tout l’esprit. Oui, tu peux faire du C avec des variables immutable, de la récursion et des pointeurs de fonction, mais ce n’est pas du tout l’esprit du langage.
L’optimisation de la récursion terminale fait partie de l’esprit de la programmation fonctionnel, mais pas de celui de la programmation impérative. C’est la différence de statut, fondamentale dans un cas et accessoire chez l’autre qui à mon sens justifie de dire que l’optimisation de la récursion terminale est plus une optimisation de langage fonctionnel que de langage impératif. Certes c’est une opinion discutable (et cela ne sert à rien d’en discuter infiniment), mais c’est ce que l’on observe en pratique.
[^] # Re: C'est pourtant évident.
Posté par claudex . Évalué à 6.
Je dirais que ça dépend des situations, typiquement les parcours de graphes sont souvent fait en récursif. Et puis dire que la récursivité est utilisée en fonctionnel est une tautologie vu que c'est obligatoire.
Ce n'est pas vraiment dans l'esprit, c'est juste parce qu'autrement elle serait inutilisable.
« Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche
[^] # Re: C'est pourtant évident.
Posté par Diagonale de Cantor (site web personnel) . Évalué à 2.
Non mais là on joue sur les mots ; c’est un concept fondamentale de la programmation fonctionnel (parce qu'autrement elle serait inutilisable) et un concept annexe dans les autres formes de programmation.
[^] # Re: C'est pourtant évident.
Posté par lasher . Évalué à 2.
Et moi je te dis que si. Il y aura une optimisation pour transformer la récursion en boucle (ou pas), mais ce code est du C parfaitement valide. Il n'y a pas de discussion possible ici : il est écrit en C, qui autorise la récursion.
Non. Car je le répète, le C n'impose pas l'utilisation d'une pile. La fonction
loop
ci-dessus ne fait absolument aucune allocation — outre le fait qu'effectivement, il faut trouver un moyen de garder les pointeursmsg
successifs en mémoire, mais ce n'est pas un problème du langage, car encore une fois, il ne suppose rien concernant l'organisation de la mémoire physique de la machine (ça se trouve, tout est alloué sur le tas, ou bien le PC a une pile de taille infinie, etc.). De même qu'écrire ceci est valide :Uniquement dans les langages fonctionnels purs, alors. Car j'ai déjà donné l'exemple de Common LISP qui n'a aucune garantie dans la norme à ce sujet. Ensuite, comme tu le dis, il s'agit d'une optimisation pour les langages impératifs, ce qui indique bien que le programme est parfaitement valide lorsqu'il est exécuté sur une machine abstraite (et c'est tout ce qu'on demande à une norme, qui ne peut prévoir tous les progrès architecturaux à venir).
Oui, évidemment, on utilise beaucoup de constructions itératives dans les langages impératifs. Mais dire qu'en pratique on ne pratique pas la récursion, c'est un peu osé.
Transformer un appel récursif terminal en boucle est une obligation pour un langage fonctionnel pur (i.e., qui n'accepte pas les boucles), pour les raisons pratiques que tu as évoquées. Un langage impératif a déjà une façon d'exprimer le résultat final à travers une boucle directement. Dans les deux cas, la transformation d'une récursion terminale vers une boucle est un cas qui n'est pas réservé à un style de programmation : impératif ou fonctionnel, à partir du moment où tu acceptes qu'une fonction peut être récursive, alors la spécification de ton programme dit que toute récursion est légale (je grossis le trait mais j'espère que tu comprends ce que je veux dire). La transformation de RT → boucle est possible dès lors que la forme est respectée, et ceci est indépendant du type de langage. Tu peux tenter de nuancer en disant qu'en C ou C++ ce n'est qu'une optimisation, mais la vérité, c'est qu'il existe énormément d'algorithmes qui sont effectivement exprimés sous forme récursive, et qui, pour des raisons de performance, vont être modifiés jusqu'à atteindre une forme récursive terminale. Ensuite on pourrait bien entendu aller à l'étape suivante « directement » (transformer le tout en boucle), mais comme la plupart des compilateurs savent faire les choses correctement, pourquoi s'emmerder ?
[^] # Re: C'est pourtant évident.
Posté par Diagonale de Cantor (site web personnel) . Évalué à 2.
Valide ou pas, il mène à un bug avec plusieurs compilateur C. Ça te fais une belle jambe que ton programme soit théoriquement valide si en pratique il plante à l’exécution :) J’ai l’impression que la garantie que ton code s’exécute en mémoire bornée n’a aucune espèce d’importance pour toi.
Si la sémantique du langage dit que un fonction qui s’appelle infiniment doit tourner infiniment, alors la sémantique est stupide dans le sens où elle affirme quelque chose d’impossible ! Si une fonction a besoin d’une infinité de mémoire, alors on ne peut pas la faire tourner.
C’est pourquoi en pratique il est important de savoir dans quel cas, on peut faire une récursion infinie. C’est un problème pratique, pas théorique. La norme du langage C ne permet pas de garantir les récursions infinies dans le cas des récursion terminal ; et c’est d’ailleurs pourquoi que certain compilateur transforme des récursion infinies en des programmes qui plantent systématiquement quelque soit la mémoire.
Tu répètes en boucle qu’on peut implémenter la récursion terminal en C, mais j’ai jamais prétendu l’inverse !
Certes ; mais c’est beaucoup plus rare. Il serait intéressant de savoir combien il y a de fonction récursive dans le noyau Linux. J’avoue en avoir aucune idée, mais à mon avis il n’y en a pas beaucoup.
De plus je doute que beaucoup d’entre eux utilise le fait que la récursion terminal existe pour être correct.
[^] # Re: C'est pourtant évident.
Posté par lasher . Évalué à 2.
J'aimerais bien savoir combien d'OS sont écrits dans des langages fonctionnels.
[^] # Re: C'est pourtant évident.
Posté par Diagonale de Cantor (site web personnel) . Évalué à 3.
Emacs n’est pas (au moins en partie) écrit en Lisp ?
[^] # Re: C'est pourtant évident.
Posté par lasher . Évalué à 1.
J'aurais dû préciser que ma réponse était un peu facile. :-)
Mais oui, Emacs pourrait sans doute être qualifié. Mais je croyais qu'il avait été récrit en C (et qu'il avait « juste » un moteur elisp) ? ;-)
[^] # Re: C'est pourtant évident.
Posté par djano . Évalué à 1.
Non: Emacs est ecrit en C est peut etre etendu en utilisant du Emacs LISP.
[^] # Re: C'est pourtant évident.
Posté par Lutin . Évalué à 5.
http://www.haskell.org/haskellwiki/Applications_and_libraries/Operating_system
Il y en a quelques uns en haskell.
[^] # Re: C'est pourtant évident.
Posté par lasher . Évalué à 2.
Intéressant ! Il y a aussi deux chercheurs italiens (L. Verdoscia, et R. Vaccaro) qui essaient de construire une machine à base du modèle d'exécution de dataflow1, et qui voudraient utiliser le langage fonctionnel proposé par J. Backus comme langage « bas-niveau » (comprendre : une sorte « d'assembleur » fonctionnel).
Par contre désolé, c'est derrière un paywall… ↩
[^] # Re: C'est pourtant évident.
Posté par djano . Évalué à 4. Dernière modification le 25 avril 2014 à 09:06.
Reference:
http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options
Cool je connaissais pas!
[^] # Re: C'est pourtant évident.
Posté par ariasuni . Évalué à 4.
Rust? Bon la 1.0 n’est pas encore sortie mais c’est bientôt.
Écrit en Bépo selon l’orthographe de 1990
[^] # Re: C'est pourtant évident.
Posté par Zylabon . Évalué à 4.
Tout le problème est résumé là. Refuser de se servir de l'électricité parce que que l'on sait se servir de bougies c'est stupide.
Please do not feed the trolls
# Effective C++ par Scott Meyers
Posté par F(log) . Évalué à 3.
Je sais, je me repete sur beaucoup de commentaires, mais le livre de Scott Meyers "Effective C++" reste pour moi la reference.
Il faut absolument le lire en premier.
Il est (surement) plus oriente C++ que celui la, mais en meme temps, c'est en regardant des exemples que les notions theoriques prennent tout leurs sens :)
[^] # Re: Effective C++ par Scott Meyers
Posté par lmg HS (site web personnel) . Évalué à 1.
Les (M)EC++ sont beaucoup plus techniques. En comparaison, le chapitre OO de Coder Efficacement est plus éloigné du langage, et il sera valable dans tous les langages OO (mainstreams).
Après, c'est sûr que quelqu'un d'assidu aux forums C++ techniques comme clc++m, dvpz, ou le sdzoc, ou qui connait les FAQs par cœur n'apprendra pas grand chose…
[^] # Re: Effective C++ par Scott Meyers
Posté par JGO . Évalué à 3.
Quelle est la différence entre More effective C++ publié en 1995 et Effective C++ (5e édition) publié en 2005 ? Ils se recoupent, ou il faut lire les deux ?
[^] # Re: Effective C++ par Scott Meyers
Posté par Thom (site web personnel) . Évalué à 6.
Ce n'est pas vraiment le même genre de bouquin.
Scott Meyers avec Effective C++ a écrit un bouquin qui a vraiment pour toile de fond le C++ et illustre ça avec des problématiques C++ très précises. Au final, on a un très bon bouquin de C++.
Là, on a vraiment un bouquin qui est plus pour moi du bon, du raisonnement et du bon sens sur la programmation où l'art d'écrire des programmes. Le C++ sert d'exemple, mais ce n'est pas le sujet principal du bouquin.
La réalité, c'est ce qui continue d'exister quand on cesse d'y croire - Philip K. Dick
[^] # Re: Effective C++ par Scott Meyers
Posté par F(log) . Évalué à 2.
Merci d'avoir mis l'accent sur ce point.
Je pense acheter le bouquin pour pouvoir comparer.
Surtout qu'il est pas tres cher :)
# Cas des constantes
Posté par cfx . Évalué à 2.
Je trouves les exemples concernant la déclaration d'une constante assez maladroits. Après, peut-être que le livre donne plus de détails ou de conseils.
Je dirai plutôt « valeur entière constante », puisque l'une des solution consiste à utiliser une énumération.
On m'a toujours dis de limiter l'utilisation de #define pour déclarer des constantes, en particulier lorsque l'on parle de C++ : effets de bord parce que quasiment personne ne #undef ses #define, pas de notion de d'espace de noms…
[^] # Re: Cas des constantes
Posté par lmg HS (site web personnel) . Évalué à 3.
Cet extrait peut desservir le contenu. Là, ne sont présentées que les syntaxes les plus maladroites. La syntaxe C++11 à préférer est donnée quelques pages plus loin.
[^] # Re: Cas des constantes
Posté par Enj0lras . Évalué à 2.
Il y a aussi le cas des bitfields que les enums ne règlent pas du tout.
[^] # Re: Cas des constantes
Posté par barmic . Évalué à 4.
Dans linuxmag, il y avait une implémentation en teplate qui avait l'air intéressante.
Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)
# Rule of Three
Posté par rewind (Mastodon) . Évalué à 6.
Généralement, la «forme normale de Coplien» (première fois que j'entends ce terme) est utilisé dans le cadre de ce qu'on appelle le Rule of Three : si on implémente un des trois suivants, on implémente les deux autres : constructeur par copie, affectation, destructeur. Et depuis C++11, on a presque le Rule of Five avec le constructeur par déplacement et l'affectation par déplacement. Mais en fait, vu qu'on a maintenant des classes qui gèrent ce genre de cas très bien (
shared_ptr
,unique_ptr
), on a un Rule of Zero (parce que les méthodes par défaut feront exactement ce qu'il faut).Du coup, je pense que le livre s'est arrêté avant C++11.
[^] # Re: Rule of Three
Posté par lmg HS (site web personnel) . Évalué à 2. Dernière modification le 15 avril 2014 à 15:46.
La Forme Canonique Orthodoxe de Coplien précède légèrement la Rule of Big Three. Elle traite également du constructeur par défaut. La version à 3 va supposer un constructeur, mais sans le compter (car il faut bien positionner les invariants)
Quant au passage à 5, il est traité §17. Au moment de l'écriture, on n'avait qu'un seul article sur la règle à 5 ou 0. Et celui que tu pointes (et qui est plus abordable que le premier) n'était pas encore écrit. C'est le genre de chapitre qui pourrait être patché dans les versions électroniques. (Je passe la main à Patricia et/ou Philippe
^^'
)Bref. Non, le livre ne s'arrête pas au C++03. Il y a des éléments de C++11 dedans. Mais pas de C++14 dans mes souvenirs.
Et de toutes façons, quand les développeurs, ou plutôt les qualiticiens, respecteront correctement la règle de 4/3, ou mieux de 2 (2 == avec du RAII dedans)—C'est à dire en respectant les sémantiques des classes—on pourra pinailler sur la version 5-0 en C++11.
# Exceptionnal C++
Posté par pizaninja . Évalué à 4.
Je conseille aussi "Exceptionnal C++", basé sur le site web "GOTW" pour "Gourou Of The Week".
Il complète "Effective C++" et "More Exceptionnal C++", notamment en ce qui concerne la gestion des exceptions (mais pas que), comme le titre le laisse à penser.
[^] # Re: Exceptionnal C++
Posté par lmg HS (site web personnel) . Évalué à 3.
Globalement, tous les bouquins de C++ publiés chez Addisson-Wesley sont excellents…
# Réponses en vrac
Posté par koala01 . Évalué à 10.
Bonjour,
Je me dis qu'en tant qu'auteur, je suis relativement bien placer pour user d'un "droit de réponse", que je vous remercie de m'accorder.
J'ai relevé certains commentaires sur lesquels je souhaite revenir, un peu à la manière de carabiniers d'offenbach. Il ne sont peut être pas dans l'ordre et je m'en excuse.
Le cas des valeur numérique
Je précise que je parle bel et bien de valeurs numérique entières constantes dans le livre, mais il faut avouer que, sorti de son contexte comme le cas est présenté ici, cela ne donne vraiment qu'une idée bien piètre de ce qui se trouve dans le livre.
Car je vais bien plus loin que de dire simplement "voici un #define, un static const et une énumération", je dresse aussi la liste des avantages, des dangers éventuels et des inconvénients des différentes techniques.
Forme canonique de Coplien, Rule of big three
J'ai veillé à faire un parallèle très clair entre la forme canonique et la règle des trois grands. J'en ai profité pour parler des (nouvelles!) règles applicables depuis la sortie de C++11 et des pointeurs intelligents. Mais comme l'a fait valoir LM HS, il n'y avait que très peu de ressources, aussi bien en français qu'en anglais, sur les conséquences de certains choix faits en C++11 au niveau de cette règle et de la Forme canonique de Coplien.
La comparaison (M)EC++ et GOTW
(More) Effective C++ et Guru Of The Week sont de véritables références, il n'y a pas lieu de discuter de ce point.
Mais ce sont des références particulièrement pointues qui abordent des points bien précis du C++. L'optique de mon livre est toute autre et tend à rappeler—car je suis sur que tout développeur expérimenté les connait—les principes généraux que l'on a trop souvent tendance à ne pas appliquer parce que "ca sert à rien" selon beaucoup trop de monde.
Pour ma part, j'estime que le fait d'appliquer directement et avec bon sens les principes que je rappelle dans mon livre permet réellement de rendre le développement plus facile, plus évolutif et plus aisément déboggable.
Mon but en écrivant cet ouvrage était réellement de rappeler et d'expliquer correctement ces principes, afin que les développeurs soient en mesure de comprendre quand et comment les appliquer. Cette approche est donc bel et bien totalement différente de EC++!
Coder Proprement
Voilà sans doute un ouvrage qui manque dans ma bibliothèque, car je ne l'ai pas lu. S'il est orienté vers java, il faut dores et déjà se dire qu'il risque, malheureusement, de prendre les restrictions imposées par ce langage comme acquises et définitives.
Il ne s'agit pas de remettre la philosophie imposée par java et par C# en question ici, car ce sont des philosophies tout ce qu'il y a de plus cohérentes. Mais il s'agit de rappeler que C++ a une philosophie différente, plus permissive, imposée par des choix conceptuels différents.
Limiter l'approche orientée objet à la seule philosophie de java (ou de C#) empêche bien souvent de prendre conscience du problème plein et entier tel qu'il se présente, tend à "amputer" la vision que l'on peut avoir du problème de pans entiers de celui ci.
J'ai choisi C++ à dessein, car non seulement sa philosophie est plus permissive, mais il permet aussi de mettre en place des solutions "originales" et élégantes.
[^] # Re: Réponses en vrac
Posté par gato . Évalué à 1.
Les 3 façons de déclarer des constantes, dans cet article, s'écrivent aussi exactement comme cela en C, et avec les mêmes avantages et inconvénients. Fallait-il vraiment mettre cet exemple-la en avant dans l'article ? Ce n'est pas très alléchant.
[^] # Re: Réponses en vrac
Posté par lmg HS (site web personnel) . Évalué à 2. Dernière modification le 17 avril 2014 à 17:41.
En C tu n'auras pas ces choses là:
Ni
Ni mon préféré en C++98/03
Mais je reconnais volontiers que ce n'est pas forcément l'extrait le plus alléchant. Mais bon. On trouvera toujours à redire car au fond, l'Oncle Bob a déjà décrit SOLID en long et large, ou encore le RAII est un classique des FAQs, etc.
[^] # Re: Réponses en vrac
Posté par BAud (site web personnel) . Évalué à 3. Dernière modification le 17 avril 2014 à 16:27.
l'anti-sèche au bas des commentaires rappelle la syntaxe pour le code (avec l'exemple du ruby) et la page wiki aide-édition rappelle qu'il vaut mieux spécifier le langage.
Un modérateur pourrait passer par là pour remettre au mieux en forme.
[^] # Re: Réponses en vrac
Posté par Benoît Sibaud (site web personnel) . Évalué à 4.
Corrigé.
[^] # Re: Réponses en vrac
Posté par Anthony Jaguenaud . Évalué à 4. Dernière modification le 17 avril 2014 à 16:53.
En fait, il faut mettre trois ' à l'envers ([altgr]+è sur un AZERTY) et c++ en minuscule, et laisser une ligne avant et une ligne après. Pour fermer, trois ' à l'envers. Ex :
'''c++
int a;
'''
Donne :
[^] # Re: Réponses en vrac
Posté par lmg HS (site web personnel) . Évalué à 1.
Je me suis laissé avoir par le bouton de la zone d'édition.
Merci à vous deux. Je saurais pour la prochaine fois.
# Policy-based design
Posté par pilouche (site web personnel) . Évalué à 3.
Hello, j'en profite pour faire partager mon enthousiasme pour
Modern C++ Design: Generic Programming and Design Patterns Applied
Le bouquin m'a appris les policy-based design, une révolution personnelle en ce qui concerne le code C++ : modulaire, quasiment entièrement vérifié à la compilation. Un grand gain de temps, et du code bien plus joli, malgré l'avalanche de templates.
[^] # Re: Policy-based design
Posté par lmg HS (site web personnel) . Évalué à 1.
(Encore un Addisson-Wesley … :) )
Dans un genre proche et différent à la fois, tu as le CRTP, ou encore Mixin-Layers façon Smaragdakis (boudiou! plus de 10ans après, je sais toujours l'écrire…)
Pour le MC++D, en fin de compte, ce qui a été retenu dans boost (et par continuité) dans le dernier standard a des approches différentes (pour les smart-pointeurs, les listes de types, …)
[^] # Re: Policy-based design
Posté par pilouche (site web personnel) . Évalué à 1.
Pour MC++D, google dit… McDonalds ;)
[^] # Re: Policy-based design
Posté par lmg HS (site web personnel) . Évalué à 1.
google ne donnera rien de bon pour AC++, (M)EC++, (M)XC++, PPPuC++, ou le TC++PL non plus.
Sur les forums spécialisés, les gars qui y trainent sauront décrypter les titres de ces bouquins.
[^] # Re: Policy-based design
Posté par devnewton 🍺 (site web personnel) . Évalué à 4.
Sauf à la compilation /o\
Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.