Je ne ma�trise pas l'enti�ret� du fran�ais. Par exemple, jusqu'� il y a 10 secondes, je ne savais pas ce que � d�cize � voulait dire. Mais je me d�brouille quand m�me pour comprendre ce que racontes les autres.
Version imprimable
Je ne ma�trise pas l'enti�ret� du fran�ais. Par exemple, jusqu'� il y a 10 secondes, je ne savais pas ce que � d�cize � voulait dire. Mais je me d�brouille quand m�me pour comprendre ce que racontes les autres.
Tr�s dr�le :-) Mais plaisanterie mise � part, l'exemple est tr�s mauvais. Il peut �tre impossible de comprendre le sens de certaines phrases si on ne maitrise pas le vocabulaire qui y est employ�. Mais il est �galement vrai que des phrases compos�s de mots tr�s simples peuvent �tre difficiles � comprendre.
Ceci est du code �crit dans un langage
- sans classes ni constructeur pour enforcer les invariants,
- ni r�f�rences, pour �galement enforcer d'autres invariants.
Vu qu'il est difficile d'avoir des garanties offertes par des syntaxes alternatives trop simplistes, le code est farci jusqu'� l'os de programmation d�fensive car il est difficile de maitriser o� l'on va et qui pourrait faire quoi comme b�tise. Au final, on a un code bien plus difficile � maintenir qu'un �quivalent C++.
Avec de la syntaxe suppl�mentaire, on se met dans des conditions qui simplifie la logique du code. La contre-partie, perdre un petit peu de temps au d�but pour apprendre des notions de conception, et des nouvelles syntaxes, pour gagner beaucoup de temps en maintenance.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 struct Image : boost::noncopyable { explicit Image(std::size_t nb) : pixels(new double[nb]), nb_pixels(nb) {} ~Image() { delete[] pixels; } std::size_t get_size() const { return nb_pixels;} double const& operator[](std::size_t idx) const { assert(idx < get_size()); return pixels[idx]; } double & operator[](std::size_t idx) { assert(idx < get_size()); return pixels[idx]; } private: double * pixels; std::size_t nb_pixels; };
Tout le monde a du mal avec le niveau de templates qui augmente. Et pourtant, bien utilis�s, il permettent d'�crire des trucs comme
L'utilisateur ne sait pas (/ne veut pas savoir) comment c'est fichu, et cela lui est pourtant tr�s utile.Code:
1
2
3
4
5 using non_null_double = my::non_null<double>; boost::unit::length f(non_null_double factor, boost::unit::length distance) { return distance / factor; // pas de question à me poser ici, je sais que factor est non nul. }
Je partirais sur cette base pour impl�menter une telle fonctionnalit�. Je renverais une exception plutot que la valeure 1. Mais c'est surement tr�s na�f.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 template <typename Type_> struct NonNull { Type_ value; NonNull() : value(Type_()) {} NonNull(Type_ val) : value(val) {} operator Type_() { if(!value) return 1; else return value; } }; int main(int argc, char** argv) { NonNull<double> non_null_double; double d = 10.0 / non_null_double; return 0; }
C'est plus subtil.
- Le constructeur par d�faut doit �tre retir� (= delete)
- Le constructeur mono-param�tre doit �tre explicite, et faire un assert.
- L'op�rateur de conversion doit �galement �tre explicite -- il faut le C++11 pour �a.
Sans �a, la classe ne pr�sente pas grand int�r�t, sinon, l'utilisateur pourrait �crire sans soucis des choses comme "double d = 0; f(d);". Or on d�sire une erreur de compilation qui force l'utilisateur � �tre conscient que la fonction attend un nombre non null, ou � d�faut qu'il en soit conscient, qu'il passe un nombre non null. "auto d = mon_rationnel_valide.as_real(); f(d);"
J'ai bien dit que je renverais une exception meme si dans l'exemple je mets 1.
Pas pris encore l'habitude. Des fois j'y pense des fois non.
En quoi le constructeur par d�faut g�ne t-il ? Initialiser la valeur, m�me � z�ro, ne pose pas de problemes. Il ne faut juste pas l'utiliser telle quellle ,mais en m�me temps �a n'aurait pas beaucoup de sens que de l'utiliser telle quelle.
a- Exception que tu auras le jour o� les donn�es entrantes ne seront pas bonnes et qui ne te permettra pas de corriger le code pour lui permettre de renvoyer un message d'erreur pertinent : http://luc-hermitte.developpez.com/t...heorie/#LIII-A
Avec une erreur de compilation, on renvoie la responsabilit� de la v�rification au bon endroit.
b- Si la variable est initialis�e par d�faut � 0, c'est totalement en contradiction avec l'objectif : faire en sorte que la donn�e ne puisse jamais �tre dans un �tat non utilisable afin de n'avoir jamais � se poser la moindre question.
Oui en effet. Je viens d'aller faire des courses et sur la route j'ai r�fl�chi au probl�me, � comment je l'impl�menterai. Et effectivement je n'avais pas bien compris le principe. Le but n'�tant pas de ne pas pouvoir utiliser la valeur si elle est �gale � z�ro, mais tout simplement faire en sorte qu'elle ne soit jamais �gale � z�ro. C'est pas la m�me chose.
De m�me que j'aurais du d�clar� la valeur en priv�e et non en public et tout un tas d'autres subtilit�s auxquelles je n'avais pas sp�cialement pens�es sur le moment. Mais enfin bon, on est un peu hors sujet la :?
C'est une question d'habitude. Pour ma part, je comprends ce code du premier coup d'oeil. D'ailleurs, du code comme �a, �a a �t� la norme pendant TRES longtemps. Les nouvelles constructions syntaxiques sont utiles, ce n'est pas le probl�me, mais on n'est pas non plus oblig� de mettre toutes les constructions syntaxiques existantes d'un langage dans un programme.
C'est m�me qu'une question de langage. Ce code avec des pointeurs est du code C (en changeant enum class par enum) alors que la version avec RAII est du C++. Un code correctement �crit en C est aussi compr�hensible qu'un code correctement �crit en C++. Tout d�pend des besoins. Pour programmer un MCU dans l'aviation par exemple on choisira le C pour obtenir un ex�cutable plus l�ger, moins groumant en RAM, plus performant et surtout compl�tement pr�dictible dans un contexte critique car le C++ fait des choses derri�re le dos du programmeurs qui ne sont pas toujours souhaitables.
A propos de C plus l�ger et plus rapide, je renvoie aux pr�sentations que j'avais �voqu�es ici: http://www.developpez.net/forums/d32...r/#post8505022
Sinon, AMA, trouver ce type de code plus simple � comprendre est une illusion dont on se berce.
Ceci n'est que le code "bas-niveau". Comme je disais, imaginez maintenant un filtre qui va extraire un bandeau de l'image (et donc construire un objet sous-image), et parser tous les pixels pour calculer des statistiques ou faire autre chose.
Il faut pr�voir une nouvelle ressource allou�e : le bandeau (et donc sa lib�ration en cas d'erreur sur get_pixel), et une boucle qui va it�rer sur chaque pixel. Ce cas est encore simple. Cela devient encore plus compliqu� sur des calculs de corr�lation o� l'on extrait 2 bandeaux qui sont parcourus simultan�ment).
D�j� qu'un code C correct est complexe: cf le code en bas � gauche dans http://alexandre-laurent.developpez....ou-exceptions/, si en plus on rajoute de la programmation d�fensive (pour r�sister aux erreurs de programmation), le code devient encore plus complexe.
En C, il aurait �t� plus propre de rendre la classe/structure image compl�tement cach�e (comme FILE), histoire de retirer le code qui v�rifie � chaque fois si tout ce qui est re�u est dans un �tat correct. C'est � dire: simuler des invariants assur�s par encapsulation+constructeur.
Mon point, est que le C++ offre de "nouveaux" (pour le coup, ceux l� vieux) moyen pour simplifier notre code. On ne va quand m�me pas refuser des sucres syntaxiques sous pr�texte que c'est une syntaxe alternative � une que nous avons d�j�.
J'utilise � la fois C et C++ dans l'embarqu� et je peux confirmer que dans l'immense majorit� des cas, et c'est logique, C est plus performant que C++ et surtout moins gourmand en m�moire. Le fais que l'orateur ne sache pas pourquoi certains programmes �crit en C++ donnent un ex�cutable de taille moindre est pour moi r�v�lateur du probl�me que pose C++ dans l'embarqu�. Il y a bien eu des tentatives de porter certains projets de l'embarqu� �crit en C vers du C++ (le plus connu �tant le kernel Linux) mais la plupart se sont av�r�es �tres des �checs o� ont �t� rapidement abandonn�es apr�s �tude. Dans le cas des MCU, la question est souvent vite r�gl�e par le fait que l'ensemble des outils de la STL (� l'exception de std::array) et la plupart des m�canismes du langage comme les exceptions ne peuvent tout simplement pas �tre mis en oeuvre.Citation:
A propos de C plus l�ger et plus rapide, je renvoie aux pr�sentations que j'avais �voqu�es ici: http://www.developpez.net/forums/d32...r/#post8505022
[Ca devient de plus en plus HS, relativement aux concepts ^^']
Justement, ce n'est pas si logique.
Le C++ te permet de choisir quelle fonctionnalit� tu prends du C d'origine, ou des apports qui viennent du C++. A partir de l�, il n'y a aucune raison que l'on ne soit pas capable d'avoir un code au moins aussi efficace/petit -- quitte � retirer les exceptions pour garder un petit binaire.
L�, o� �a devient int�ressant, c'est que l'on peut se donner de nouveaux outils, et dans le lot, on peut en trouver qui ne vont pas d�grader performances et empreinte. Quelques un ont �t� list�s dans la pr�sentation : algos standards qui permettent de nouvelles optims (je ne parle pas des conteneurs -- autres que std::array, ou les array_view/string_view), not_null qui �vite de payer pour les branchements de la programmation d�fensive, etc.
Les m�canismes de C++ sont � la fois plus complexes et plus lourds, c'est donc logique. Les cas pr�sent�s � charge du C sont s�lectionn�s et hors contexte. Dans la majorit� des cas, les performances de C sont meilleures comme le montre ce benckmark. La plupart des lib bas niveau et des applications temps-r�el sont �crites en C en partie pour cette raison. N'importe quel ing�nieur s�rieux dans l'embarqu� le dira. J'aime beaucoup C++ mais il n'est pas � m�me de tenir la barre dans les applications critiques ou n�cessitant des performances.
Je pense qu'il y a un souci dans la fa�on dont tu t'exprimes.
Le fait que du code soit simple a comprendre n'implique pas qu'il soit appropri� pour une situation donn�e.
Tu semble confondre simplicit� de compr�hension et r�utilisabilit�. A partir de l�, �a devient un dialogue de sourd. Mais sinon, dans le fond, sur l'exemple donn�, je te rejoins. Il serait plus g�n�rique d'encapsuler le code. Mais �a n'en fait pas un programme plus simple � comprendre. D'ailleurs, l'encapsulation en cascade peut elle aussi poser des probl�mes de compr�hension du code.
Si tu prends fasta, et regarde les codes, tu verras une �norme diff�rence: "#pragma OMP". On ne compare pas les m�mes choses. Pour les arbres binaires, on n'utilise pas le m�me COTS. Pareil pour la lib de regex dans le suivant. Il est difficile de comparer quand autant d'�l�ments changent, et qu'il ne s'agit pas juste de remplacer des structures par des classes (pour mieux contr�ler les invariants et remplacer de nombreux cas d'utilisation du d�buggeur par le compilateur dans l'assistance � la maintenance de l'application), et prendre un peu de template par-ci par-l�.
La part du C dans l'embarqu� est du � deux raisons : la tradition et les aprioris (je ne sais plus si c'est le sujet de la 1�re ou de la 2nd pr�sentation de Dan Saks lors du dernier code::dive), et au probl�me de support par des compilateurs maintenus par les fournisseurs de matos (qui n'ont pas forc�ment envie, ni les moyens, de fournir des compilateurs plus complexes comprenant le C++). Et aussi on a facilement des probl�mes d'ABI. Si tu veux faire dans l'ad hominem, je pense pouvoir dire que Dan Saks est un d�veloppeur s�rieux qui bosse dans l'embarqu�. Et pourtant il se fait l'avocat du C++ depuis tr�s longtemps.
Qui plus est, si une construction propre au C++ n'est pas acceptable, il suffit d'utiliser l'�quivalente du C. Un code C compil� avec un compilateur C++ n'a pas � �tre plus lent -- cf la video de l'autre intervenant dont le nom m'�chappe. A partir de l�, tu utilises juste ce que tu veux du C++. Et m�me en embarqu� (moyennant la disponibilit� d'un compilateur), tu ne dois pas observer de d�gradations.
En effet, je sens un probl�me de communication. D�sol�.
La simplicit� de compr�hension ne se borne pas au cas local. Il est vrai que la simplicit� que je critique ne se limite pas � ces deux fonctions. Elle englobe tout le produit de traitement d'image. Quand je vois un tel code (en g�n�ral, je commence par la couche haute avant de descendre pour savoir si on n'aurait pas des fuites de ressources), je dois accorder plus d'attention pour comprendre ce qu'il fait. Cela vaut aussi bien pour la maintenance (a-t-on oubli� des cas?), que pour son utilisation.
Et justement, son utilisation est � 100% embarqu�e dans du code qui continue � faire la m�me chose. Ce code que j'ai montr� est le plus simple car tout au fond des appels. Quand on maintiens les couches au dessus, (qui suivent la m�me politique, d�tail tr�s important), c'est vite l'enfer car il faut v�rifier les cas remont�s par cette partie, plus ceux remont�s par les autres parties employ�es. L�, on a constitu� une op�ration plus ou moins simple � appr�hender, et on recommence en l'utilisant � un niveau sup�rieur. Mon exp�rience est que la complexit� explose et qu'il y a des potentiels de fuites assez importants si un erreur de programmation est bel et bien d�tect�e.
Le probl�me de ce type de code est le parasitage par la programmation d�fensive qui rend vite tout plus compliqu�.
get_size() fait du d�fensif. Il est localement assez simple. get_pixel fait du d�fensif, il serait presque simple, sauf qu'il appelle une fonction qui elle-m�me fait du d�fensif, ce qui implique une complexification du code de get_pixel. get_region fait du d�fensif � son niveau et appelle d'autres fonctions qui font du d�fensif (get_size(), get_pixel()).
S'il y a des raccourcis que je prends, c'est li� au fait que j'affirme que gr�ce � class+private+constructeur, j'ai moyen d'�liminer une part non n�gligeable du d�fensif, ce qui permet d'avoir des fonctions plus simples � chaque niveau. Avec les exceptions, on peut encore aller plus loin : si on a un objet bandeau, alors il ne peut que �tre valide, et alors nul besoin de tester des choses assur�es par construction du programme.
Ce que montre Dan Saks dans sa vid�o n'est tout simplement pas possible dans bon nombre de syst�mes embarqu�s ou induit clairement d'importants surco�ts de m�moire par rapport � une impl�mentation en C. De plus il ne parle pas des performances et des questions temps-r�el importantes dans l'embarqu� et pour lesquelles il n'est pas possible d'obtenir des r�sultats satisfaisants en C++. Il est du reste compliqu� de pr�dire le code machine qui r�sultera d'une compilation en C++ lorsque �a n'est pas tout simplement impossible. On n'est donc pas en mesure de pouvoir utiliser C++ dans des applications exigeant des preuves solides ou n�cessitant une tr�s faible empreinte m�moire.Citation:
La part du C dans l'embarqu� est du � deux raisons : la tradition et les aprioris (je ne sais plus si c'est le sujet de la 1�re ou de la 2nd pr�sentation de Dan Saks lors du dernier code::dive), et au probl�me de support par des compilateurs maintenus par les fournisseurs de matos (qui n'ont pas forc�ment envie, ni les moyens, de fournir des compilateurs plus complexes comprenant le C++). Et aussi on a facilement des probl�mes d'ABI. Si tu veux faire dans l'ad hominem, je pense pouvoir dire que Dan Saks est un d�veloppeur s�rieux qui bosse dans l'embarqu�. Et pourtant il se fait l'avocat du C++ depuis tr�s longtemps.
En reprenant le code dans l'autre vid�o de Bartosz Szurgot mais en rempla�ant la boucle for par un simple memset, l'ex�cutable en C est 30% plus petit et 40% plus rapide. La question � se poser est, "quel est le probl�me?". Chacun de ces 2 langages a une solution a apporter et l'id�e est de prendre la meilleure.
Je ne dis pas qu'il n'est pas possible que la majorit� des personnes dans l'embarqu� fassent erreur mais il y a quand m�me toujours mati�re � r�fl�chir sur le s�rieux d'une d�marche lorsqu'elle est minoritaire. Ici c'est justifi�.