OVH Cloud OVH Cloud

La fin de l'héritage ?

103 réponses
Avatar
Olivier Azeau
J'ai lu avec grand intérêt l'article "Concepts for C++0x" mentionné dans
un thread récent.
Habituellement, je ne m'intéresse pas aux évolutions du langage car
elles ne me concernent qu'à un relativement long terme, mais là, j'ai
l'impression qu'un mouvement de fond relatif aux paradygmes du C++ prend
une certaine ampleur.
Et ce mouvement m'amène à quelques interrogations.

La plupart des développeurs que je cotoie programment en C++ dans un
style orienté objet très proche de ce que l'on trouve en Java.

Je prends un exemple classique de Bridge+Factory pour illustrer mon propos.
On a typiquement une hiérarchie d'implémentations :
| class DocumentDisplay {
| virtual ~DocumentDisplay();
| virtual void drawText( int x, int y, std::string const &text ) = 0;
| virtual void drawLine( int x1, int y1, int x2, int y2 ) = 0;
| };
|
| class GraphicDocumentDisplay : public DocumentDisplay {
| virtual void drawText( int x, int y, std::string const &text );
| virtual void drawLine( int x1, int y1, int x2, int y2 );
| };
|
| class TextDocumentDisplay : public DocumentDisplay {
| ...

une hiérarchie d'abstractions qui utilisent les implémentations :
|
| class Document {
| public:
| Document( DocumentDisplay *display ) : display_(display) {}
| virtual ~Document();
|
| void drawFrame( int x, int y, int w, int h, std::string const &title ) {
| display_->drawLine( x, y, x+w, y );
| display_->drawLine( x, y+h, x+w, y+h );
| display_->drawText( x, y, title );
| }
| private:
| DocumentDisplay *display_;
| };
|
| class Memo : public Document {
| public:
| Memo( DocumentDisplay *display ) : Document(display) {}
| void drawSummary() { drawFrame( 0, 0, 150, 100, "Summary" ); }
| };
|
| class Invoice : public Document {
| ...

une hiérarchie de fabriques pour instancier tout ça :
| class DocumentFactory {
| public:
| virtual ~DocumentFactory() {}
| virtual Memo *createMemo() = 0;
| virtual Invoice *createInvoice() = 0;
| };
|
| class GraphicDocumentFactory : public DocumentFactory {
| public:
| virtual Memo *createMemo() { return new Memo( new
GraphicDocumentDisplay ); }
| virtual Invoice *createInvoice() { return new Invoice( new
GraphicDocumentDisplay ); }
| };

et je rajoute un programme principal pour utiliser le tout :
| class Application {
| public:
| Application( DocumentFactory *factory ) : factory_(factory) {}
|
| void run() {
| Memo *memo = factory_->createMemo();
| memo->drawSummary();
| }
| private:
| DocumentFactory *factory_;
| };
|
| int main() {
| Application app( new GraphicDocumentFactory );
| app.run();
| }

En pratique, ça a une tête un peu différente (avec le RAII par exemple),
mais l'idée des hiérarchie de classes est là.

Depuis quelques temps se répand la programmation générique qui permet de
faire la même chose avec (en général) moins de lignes de code.

Les implémentations deviennent des "policy" et n'ont plus besoin de
classe de base
| class GraphicDocumentDisplay {
| virtual void drawText( int x, int y, std::string const &text );
| virtual void drawLine( int x1, int y1, int x2, int y2 );
| };

Les abstractions sont paramétrées par la policy.
On garde un héritage pour partager l'implémentation :
| template <class DOCDISP>
| class Document {
| public:
| virtual ~Document() {}
|
| void drawFrame( int x, int y, int w, int h, std::string const &title ) {
| display_.drawLine( x, y, x+w, y );
| display_.drawLine( x, y+h, x+w, y+h );
| display_.drawText( x, y, title );
| }
| private:
| DOCDISP display_;
| };
|
| template <class DOCDISP>
| class Memo : public Document<DOCDISP> {
| public:
| void drawSummary() { drawFrame( 0, 0, 150, 100, "Summary" ); }
| };

Dans un cas aussi simple, on oublie la factory et on paramètre
directement l'application :
| template <class DOCDISP>
| class Application {
| public:
| void run() {
| Memo<DOCDISP> memo;
| memo.drawSummary();
| }
| };
|
| int main() {
| Application<GraphicDocumentDisplay> app;
| app.run();
| }

Une telle approche est actuellement plutôt prisée par des personnes qui
connaissent bien le langage et est donc globalement plutôt minoritaire.
Parmi les raisons de cette situation je vois :
- la forte présence de langages comme Java ou C# qui ne proposent pas
cette approche (les versions "Generic" restent anecdotiques) et donc le
grand nombre de personnes qui font du C++ comme ils font du Java
- le faible support des templates par certains compilateurs jusqu'à une
période récente (cf les interrogations récurrentes relatives au support
des templates dans VC6)
- un support méthodologique peu adapté (UML se prête beaucoup plus à
décrire des héritages que de paramétrages)
- une complexité de mise au point d'une approche à base de templates
(typage structurel, définitions statiques, ...)

Sur ce, je découvre les "concepts" (dont je ne pense pas avoir saisi le
dixième des utilisations et implications) qui me laissent supposer que,
dans un avenir plus ou moins proche, on pourrait écrire les choses de
manière plus explicites.

Les policy pourraient être nommées et contrôlées avant usage. Si j'ai
bien compris les notions et syntaxes proposées dans l'article, cela
donnerait quelque chose comme :
| template <DOCDISP>
| concept DisplaysDocuments {
| void DOCDISP::drawText( int x, int y, std::string const &text );
| void DOCDISP::drawLine( int x1, int y1, int x2, int y2 );
| };
|
| class GraphicDocumentDisplay {
| public:
| void drawText( int x, int y, std::string const &text );
| void drawLine( int x1, int y1, int x2, int y2 );
| };
|
| model DisplaysDocuments<GraphicDocumentDisplay>;

| template <class DOCDISP>
| class Application where { DisplaysDocuments<DOCDISP> } {
| public:
| void run() {
| Memo<DOCDISP> memo;
| memo.drawSummary();
| }
| };

Et j'ai même l'impression que des implémentations par défaut définies au
niveau des concepts pourraient rendre obsolète une grand pan de
l'utilisation de l'héritage.

En écrivant par exemple ce qui suit, j'ai l'impression d'avoir
entièrement réécrit l'exemple vu précédemment sans utiliser aucun
héritage C++ mais avec l'impression d'avoir quand même fait de l'"objet"
(s'il est encore possible de définir ce terme...) mais "autrement".
| template <DOC>
| concept IsDocument {
| typename doc_display;
| require DisplaysDocuments<doc_display>;
|
| doc_display &DOC::display();
|
| void DOC::drawFrame( int x, int y, int w, int h, std::string const
&title ) {
| display().drawLine( x, y, x+w, y );
| display().drawLine( x, y+h, x+w, y+h );
| display().drawText( x, y, title );
| }
| };
|
| template <class DOCDISP>
| class Memo {
| public:
| typedef DOCDISP doc_display;
| doc_display &display() { return display_; }
|
| void drawSummary() { drawFrame( 0, 0, 150, 100, "Summary" ); }
| private:
| DOCDISP display_;
| };
|
| template <class DOCDISP>
| model IsDocument< Memo<DOCDISP> >;

Pour ceux qui auront eu le courage de lire jusqu'ici, j'aimerais savoir
s'ils pensent :
- que je n'ai rien compris aux "concepts" ?
- que ces notions vont avoir un impact technique majeur sur l'écriture
de code en C++ ?
- que ces notions vont avoir un impact sociologique majeur sur le
développement en C++ ?

Je suis plus particulièrement intéressé par l'aspect sociologique des
choses.
J'ai l'impression d'être face à une évolution du même ordre de grandeur
que le passage du C au C++.
Pour tout dire, j'ai même l'impression que le terme C++ n'est conservé
que pour des raisons marketing (la "marque" est déja connue, appréciée,
possède une base de consommateurs, ...)

Il est toujours possible d'écrire du C avec un compilateur C++ mais, sur
une période d'environ 10 ans (en gros les années 90) on est passé d'une
approche majoritaire en termes de structures/procédures a une approche
majoritaire classes/héritages/associations.
Cela a impliqué un changement de principes de modélisation, un
changement de techniques d'écriture de code mais surtout un changement
de mentalité.
Et quand je regarde les efforts qu'il a fallu déployer pour que
l'ensemble des intervenants en arrive à penser les développements plus
ou moins de la même manière, j'ai un peu l'impression, en voyant ces
nouvelles notions qui se profilent à l'horizon, que nous ne sommes pas
au bout de nos peines...

10 réponses

7 8 9 10 11
Avatar
kanze
Gabriel Dos Reis wrote:
writes:

| Ivan Vecerina wrote:
| > "Alain Naigeon" wrote in message
| > news:4204038c$0$602$

| > > "Ivan Vecerina"
| > > a écrit dans
| > > le message news: cu0s5d$jn2$
| > >> On ne perd certainement pas en puissance et en
| > >> flexibilité en faisant du tout-object et
| > >> tout-dynamique. Cependant, même dans des applications
| > >> banales, ceci a un coût souvent rédhibitoire.

| > > C'est marrant, quand il s'est agi de passer de C à C++,
| > > on affirmait le contraire à ceux qui émettaient des
| > > doutes (ou qui ne voyaient pas ce qu'on gagnait en temps
| > > de mise au point et en sécurité)

| > L'orienté-objet introduit par le C++ n'a rien à voir avec
| > le dynamisme quasi-total offert par un language comme
| > SmallTalk.

| Oui et non. La notion de la résolution à l'execution y
| est. Mais comme Eiffel, il ne rénonce pas à la vérification
| statique des types, et je crois que Stroustrup a été
| influencé par Meyers pour certaines choses.

BS avait formulé dès 77-78 qu'il avait vraiment besoin de la
vérification statique des types et c'était à la base de ses
travaux avec « C with Classes. » Voir D&E.


Il y a sans doute beaucoup de choses qui joue. Déjà, pour
commencer, s'il veut que les extensions s'integrent dans le C
(et non qu'elles fassent partie à part, comme dans Objective C),
une vérification statique de types s'impose.

Alors, qui a quoi de qui, je ne sais pas. Je sais que dans
TC++PL édition 2, Stroustrup a bien cité Meyer comme une
influence importante en ce qui concerne la programmation OO.
Pour la programmation par contrat, certainement, mais je crois
aussi pour d'autres aspects. Et en fin de compte, qu'est-ce que
c'est la vérification statique des types autres qu'une partie du
contrat vérifié par le compilateur.:-)

Ce que je sais de source sûre, c'est qu'il avait décidé de ne
pas tomber dans la trappe, comme Eiffel, avec la
contravariance.


Disons qu'avec les surcharges de fonction, c'est une
complication en plus. Je ne le connais pas assez pour savoir si
c'est une trappe, mais j'avoue être sceptique en ce qui concerne
l'utilité. (Mais je ne vois pas beaucoup d'intérêt à la
covariance non plus. Mais ça tient peut-être de mon style de
programmation.)

| (En revanche, je ne suis pas sûr qu'il n'a pas introduit
| l'héritage avant de connaître l'oeuvre de Meyers. Il
| faudrait lui démander.)

C'est simple : C++ est influencé directement par Simula et
Simula avait la notion d'héritage, qu'on retrouvera dans « C
with Classes ». Et c'était quand déjà ? Voir D&E.


Je sais que l'influence principale, c'était Simula, et que c'est
de là que viennent les classes. Je sais aussi (d'après ma
lecture de TC++PL édition 2) que Stroustrup tient (ou tenait)
les idées de Meyer sur l'orientation objet en estîme, même si je
ne crois pas qu'il s'entend particulièrement bien avec Meyer ni
qu'il ait une haute opinion d'Eiffel. (C'est un peu la
différence entre les deux. Stroustrup peut apprécier certaines
idées de la personne et en reconnaître la valeur même s'il
n'aime pas la personne particulièrement, ou qu'il en trouve
d'autres idées moins intéressantes.)

Enfin, j'imagine qu'il y a des idées dont le temps est arrivé,
et que c'était peut-être le cas alors en ce qui concerne le
mariage typage statique et OO.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Jean-Marc Bourguet
Olivier Azeau writes:

Jean-Marc Bourguet wrote:
Olivier Azeau writes:

Tout à fait, même si j'essaie de ne pas en abuser de ce
pattern un peu décrié ("pourquoi rajouter une méthode
'accept' qui permet de rajouter dynamiquement des méthodes
sur la hiérarchie plutôt que de rajouter directement ces
méthodes dans les classes de la hiérarchie ?")


Encore une attitude que je n'ai pas rencontrée. Je vais
finir par penser que mon environnement est meilleur que je
ne le pensais :-)


Quelle attitude ?
"pourquoi rajouter une méthode..."



Donc se poser la question de rajouter des méthodes à une hiérarchie de
classes par rapport à accepter des visiteurs sans se demander si on
n'alourdit pas l'ensemble de la conception ne te semble pas une pratique
intéressante ?


Le visiteur pour moi est quelque chose d'assez proche de l'iterateur:
il faut une structure de donnee dont on veut visiter les elements,
tout comme on pourrait iterer dessus. Je ne crois pas que ce soit ce
dont il est question ici. Lors de la visitie, il faut souvent
executer du code qui depend a la fois du visiteur et de l'objet
visite. Dans un langage ayant du dispatch multiple comme CL, ca
poserait pas de probleme. Le bouquin du GOF donne en plus une
technique pour le faire en se contentant d'un dispatch simple, mais
avec la contrainte que quelque chose qui est a priori symetrique
favorise l'un des parametres. Je crois que cette technique est le
sujet de cette partie du thread.

Je ne comprends plus, si j'ai jamais compris le sens de ta remarque
qui me semblait ironique: je ne vois pas comment remplacer un
mecanisme de double dispatch par des membres dans une seule
hierarchie.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org





Avatar
kanze
Loïc Joly wrote:

[...]
La robotique est AMA un domaine en train de demander de plus
en plus de puissance de calcul. L'idée à long terme est bien
qu'on dise à un robot : Voici la CAO de la pièce, débrouille
toi.


La robotique est un domaine assez vaste, et il y en a
effectivement des aspects où il y a pas mal de calcul numérique.
(La vision me vient tout de suite à l'esprit.) En revanche, au
niveau des processeurs qui contrôlent les moteurs de
positionnement, on a souvent moins d'une dizaines d'opérations
fondamentales à faire, tous les 10 millisecondes.

Mais au fond, ce que je veux faire, c'est simplement rélativiser
la chose. Il arrive qu'il y a des problèmes de performance. On
peut même prèsque les garantir, en choisissant de mauvaus
algorithmes -- en remplaçant des tableaux hachés par des
recherches linéaires dans mon application, j'arriverais bien à
ce que le temps CPU concurrence le temps d'écriture disque. Mais
le point de départ était le coût d'un appel virtuel, non d'une
utilisation d'un bubble sort sur des millions d'éléments. Et
j'ai aussi supposé une programmation propre et correcte, avec
une conception préalable, etc. Dans ce cas-là, ça doit être
vraiment rare d'avoir des problèmes de performance, en dehors de
certains domains bien précis où, pour la plupart, le calcul
numérique joue un rôle important. Le choix entre template et
héritage doit se faire sur des bases de la conception, et non
pour des soi-disantes raisons de performance.

Note aussi que dans les applications de masse, l'optimisation de
la mémoire est souvent plus importante que l'optimisation de la
vitesse. Ajouter un PROM dans un appareil qui se produit à des
millions d'exemplaire, c'est cher. Pour les applications
portables, aussi, il y a une notion d'optimisation de
l'utilisation de la batterie, dont les implications sur le
programme ne sont pas souvent évidentes (et qui ont des
interactions avec la vitesse apperçue).

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
kanze
Loïc Joly wrote:
wrote:


[...]
Regarde autour de toi. Pas seulement au boulot, où tu
travailles peut-être dans un domaine où la performance CPU
est importante, mais plus généralement. Les ordinateurs dans
ta voiture, par exemple.


Ce n'est par l'impression que m'ont donné les fournisseurs
automobiles que j'ai pu cotoyer. Surtout que l'optique ici est
que si l'on arrive à faire tourner un calculateur ESP sur un
système coûtant 1 centime moins cher, le bénéfice se chiffre
en millions d'euros.


Ce qui leur amène parfois à optimiser l'utilisation de la
mémoire. Un PROM de moins, ou un PROM d'une taille plus petit,
ça fait des économies. Mais d'après ce que je vois, il n'exagère
pas trop dans ce sens non plus. Le prix d'une voiture, ce n'est
pas que le prix des processeurs qui s'y entrent. Donc, il est
souvent moins cher de standardise sur un processeur, même s'il
est plus cher et surdimentionné par la plupart des applications,
plutôt que de gerer un stock avec un processeur différent pour
chaque application dans chaque modèle. De même, il coût moins
chers d'utiliser plusieurs processeurs localisés qu'un seul
processeur avec beaucoup de cablage. Du coup, c'est monnaie
courante que les processeurs ne font rien 90% du temps.

Les serveurs de page web (ou il y a certainement quelques un
où la performance est importante, mais combien par rapport à
ceux qui ne font que de resservir des pages tout faites ou
gérer un chariot d'achat).


C'est là un domaine que je ne connais pas.


En fait, il peut y avoir des contraints de temps. Mais
typiquement, ils se situeront dans la base de données.
L'application utilise du C++ ultra-optimisé, mais il a été
optimisé par les programmeurs chez Oracle, ou chez IBM (pour
DB2).

Les ordinateurs de l'état (je suppose que tu paies des
impots, ou que tu as un permit de conduire),


Pareil, même si on se prend à rêver qu'avant même de
fonctionner vite, ils soient capables de fonctionner sans se
planter...


Je ne sais pas si tu as remarqué, mais il ne plante que quand il
s'agit de te renvoyer un remboursement d'un trop payé. Pas pour
les prélevements. Il semble un constant dans tous les pays où
j'ai habité que le seul « service » public qui fonctionne d'une
mannière efficace, c'est les impôts.

les ordinateurs du boulanger (qui s'appelle pas
toujours par le nom d'ordinateur), ou du grande surface.


Un ami travaillant dans le domaine m'a rapporté des problèmes
de performances qu'ils avaient, sur le temps de traitement
admis d'un code barre, entre la recherche d'informations de
prix centralisées, la possibilité d'offre promotionelles
tordues...


Chez un simple boulanger ? J'imagine bien qu'il y a des
problèmes de performance dans les points de vente d'une grande
surface. Mais là aussi, ce ne sont pas tellement des
performances en temps CPU qui sont en question, mais les temps
de reseau et de recherche dans la base de données. Et
l'optimisation, ce n'est pas de virer les fonctions virtuelles,
mais d'utiliser un protocol plus réactif ou de réorganiser la
base de données avec d'avantage des indices, etc.

Peut-être à la place d'avoir dit que les performances ne sont
pas importantes, j'auris dû dire que c'est rare que les
performances CPU dans la partie écrite par le programmeur soient
le problème, dans la mésure au moins qu'il a fait une conception
raisonable et qu'il fasse une utilisation « normale » de ses
outils.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
kanze
Loïc Joly wrote:
Olivier Azeau wrote:

J'ai réordonné mes réponses dans un sens plus logique :

Je crois que tu as mis le doigt sur le point important :
avant de se demander si le boulot est fait assez vite, on se
demande toujours si le boulot est fait correctement, et une
optimisation est un risque de bug supplémentaire.


Je dirais plutôt qu'une optimisation est un risque de coût de
développement supplémentaire, et que ce développement sera
fait à vitesse moindre, pour éviter les bugs dans une zone un
peu plus dangereuse.

Je ne connais pas du tout ce domaine mais rien que l'idée
de savoir que quelqu'un pourrait envisager de me vendre une
voiture quelques euros de moins en prenant le risque de
rajouter un bug suite à une optimisation de code me fait un
peu froid dans le dos...


Dans un logiciel vendu en grand nombre, le coût de
développement supplémentaire (unique) est probablement amorti
par rapport au coût de hard (par système). Par contre, je ne
pense pas que la fiabilité s'en ressente.


Disons que pour le constructeur, tout est une question de prix.
Un problème de fiabilité impose des rappels, qui coûtent très
chers. Donc, ils investissent pour les éviter. Mais ne perdons
pas de vue que la problème de la fiabilité informatique dans la
voiture, c'est surtout un problème hardware. Les fonctionnements
critiques sont prèsque toujours fait par des processeurs
spécialisés, les algorithmes sont connus, et généralement ne
sont pas complexes. Tandis que le milieu où doit tourner le CPU
est un des plus néfaste pour l'électronique de précision.

Du coup, le développement hardware coûte plus souvent que le
développement software. Et le prix du CPU même est negligeable à
côté de tous les circuits de protection et d'anti-parasitage.

les ordinateurs du boulanger (qui s'appelle pas toujours
par le nom d'ordinateur), ou du grande surface.


Un ami travaillant dans le domaine m'a rapporté des
problèmes de performances qu'ils avaient, sur le temps de
traitement admis d'un code barre, entre la recherche
d'informations de prix centralisées, la possibilité d'offre
promotionelles tordues...


Le problème était-il vraiment un problème de perf CPU sur
l'ordinateur du boulanger ? Je pense que personne n'osera
incriminer des appels virtuels C++ (du moins pas avant
d'avoir envisagé 50 autres pistes) sur un système qui a
probablement plus de couches qu'un mille feuille et des I/O
dans tous les sens.


Je ne sais pas les détails, mais même si je pense qu'un appel
virtuel C++ n'est probablement pas en cause (mon pote bosse en
VB de mémoire), je ne répondais pas à "Le coût d'une fonction
virtuelle est en général acceptable" mais à "Sauf dans des
domaines particuliers, les performances ne comptent pas de nos
jours".


J'aurais dû être plus précis. Je parlais des performances en CPU
de l'application écrite en C++. Si elles ne sont pas
importantes, c'est parce qu'il y a prèsque toujours d'autres
goulots de performance plus limitants.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34




Avatar
kanze
Ivan Vecerina wrote:
wrote in message
news:
Mais ce n'était pas mon propos. Tout ce que j'ai dit, c'est
que la plupart des programmeurs n'en sont pas directement
concernés par la différence en vitesse entre un appel virtuel
et un appel non-virtuel.


Vraiment? Je trouve que c'est là une interprétation bien
restrictive et partiale de ce que tu as écrit:


Tout à fait:-). C'est plus restrictive que ce que je pense ; à
la rigueur, il faut considérer « différence en vitesse entre un
appel virtuel et un appel non-virtuel » comme tenant place à
toutes les micro-optimisations, à toutes les optimisations au
niveau du code C++. C'était simplement le propos initial qui a
declencher la discussion, et donc, l'exemple que j'avais en tête
pour ce qu'on entend par « optimisation ».

De l'autre côté, je ne veux pas dire que les performances (au
sens plus large) ne sont que rarement importantes. C'est même
rare qu'elle ne font pas partie du cahier de charges. Seulement,
dans la plupart des cas, les facteurs limitants de la
performance ne se trouverait pas dans le code C++, en tant que
tel.

wrote in message
news:
Si tu régardes autour de toi, tu verras que la plupart des
programmes font bien peu de choses, en somme. En revanche,
ils communiquent ce qu'ils ont fait (accès réseau) et ils le
sauvent (écriture disque). Et que dans la pratique, ce sont
les deux choses qui rallentire le plus.


A mon humble avis, il y a un monde entre "n'être affecté que
par les entrées-sorties" et "ne pas être directement concerné
par la différence entre un appel virtuel et un appel
non-virtuel".

Je ne pense pas que ce soit par malhonnêteté. Mais je suis
d'avis que tu devrais faire preuve de plus de cohérence, de
nuance, et sans doute de modération dans tes propos.


Le problème, c'est qu'à chaque coup, je réagis à un posting
donné. Et ma réaction est conditionée par ce posting. Je crois
que la plupart du temps, un programmeur C++ moyen n'a pas besoin
de considérer les performances CPU de son code -- elles seront
adéquates. Si je régarde autour de moi, la plupart des
processeurs passent la plupart du temps dans une boucle
d'attente, sans rien faire, parce que ce sont les parties du
système externe au processeur limitent les performances. Régarde
les exemples que j'ai cité.

Maintenant, j'avoue que j'ai supposé une utilisation
« normale », de l'outil -- que le programmeur ait assez de bon
sens pour choisir des algorithmes qui conviennent, et ne pas se
servir d'un tri à bulle sur un ensemble d'une million
d'éléments. C'est certain qu'en s'y cherchant, on pourrait
occuper 100% du CPU, quoique soit l'application. Mais en
programmant normalement, avec une conception propre et des
abstractions qu'il faut, on n'aurait pas de problèmes ; on n'a
pas besoin d'avoir peur des fonctions virtuelles, ni des
opérateurs ++ post-fixés, ni des centaines d'autres
« micro-optimisations » dont certains en parlent tout le temps.
Et le programme passera quand même la plupart de son temps à
attendre -- à ne rien faire.

Maintenant, je ne veux pas que ce soit déformer pour dire que je
pense que la performance n'est jamais importante. La
performance, c'est partie du cahier de charges ; il faut la
respecter. Mais si on choisit les bons algorithmes et la bonne
structure de données au départ, c'est rare qu'il faut y pensait
au niveau du codage C++ (qui est quand même le sujet normal
ici).

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Gabriel Dos Reis
writes:

| Gabriel Dos Reis wrote:
| > writes:
|
| > | Ivan Vecerina wrote:
| > | > "Alain Naigeon" wrote in message
| > | > news:4204038c$0$602$
|
| > | > > "Ivan Vecerina"
| > | > > a écrit dans
| > | > > le message news: cu0s5d$jn2$
| > | > >> On ne perd certainement pas en puissance et en
| > | > >> flexibilité en faisant du tout-object et
| > | > >> tout-dynamique. Cependant, même dans des applications
| > | > >> banales, ceci a un coût souvent rédhibitoire.
|
| > | > > C'est marrant, quand il s'est agi de passer de C à C++,
| > | > > on affirmait le contraire à ceux qui émettaient des
| > | > > doutes (ou qui ne voyaient pas ce qu'on gagnait en temps
| > | > > de mise au point et en sécurité)
|
| > | > L'orienté-objet introduit par le C++ n'a rien à voir avec
| > | > le dynamisme quasi-total offert par un language comme
| > | > SmallTalk.
|
| > | Oui et non. La notion de la résolution à l'execution y
| > | est. Mais comme Eiffel, il ne rénonce pas à la vérification
| > | statique des types, et je crois que Stroustrup a été
| > | influencé par Meyers pour certaines choses.
|
| > BS avait formulé dès 77-78 qu'il avait vraiment besoin de la
| > vérification statique des types et c'était à la base de ses
| > travaux avec « C with Classes. » Voir D&E.
|
| Il y a sans doute beaucoup de choses qui joue. Déjà, pour
| commencer, s'il veut que les extensions s'integrent dans le C
| (et non qu'elles fassent partie à part, comme dans Objective C),
| une vérification statique de types s'impose.

Pas nécessairement. À l'époque où il expérimentait avec
« C with Classes », la vérification statque des types n'était pas le
point fort de C. Il était supposé que le programmeur savait ce qu'il
faisait. Il pouvait donc bien reporter la vérification de type à
l'exécuation pour les constructions nouvelles.

| Alors, qui a quoi de qui, je ne sais pas. Je sais que dans
| TC++PL édition 2, Stroustrup a bien cité Meyer comme une
| influence importante en ce qui concerne la programmation OO.

Très certainement B, Meyers a influencé la programmation OO, mais
c'est un propos différent de ce à quoi je répondais.

En ce qui concerne la conception et l'évolution de C++, D&E donne des
explications plus poussées que l'ensemble des TC++PL.

En ce qui concerne les influences, oui il y a beaucoup de langages qui
ont influencé C++. Mais ici, je répondais à ton questionnement sur la
vérification statique de types et l'héritage. Il te suffit d'ouvrir
D&E. Pourquoi ne prends-tu pas le temps pour répondre à message pour
pour essayer de lire une partie ?

Quand il parle de l'influence des langages, il est souvent aussi
question des choses à ne pas faire -- parce que les exemples existants
ne correspondent pas à ses besoins. Il s'est inspiré aussi des
réussites que des râtés.

[...]

| > Ce que je sais de source sûre, c'est qu'il avait décidé de ne
| > pas tomber dans la trappe, comme Eiffel, avec la
| > contravariance.
|
| Disons qu'avec les surcharges de fonction, c'est une
| complication en plus.

la surcharge dans ce contexte est un problème mineur fasse à la trappe
fondamentale.

[...]

| > | (En revanche, je ne suis pas sûr qu'il n'a pas introduit
| > | l'héritage avant de connaître l'oeuvre de Meyers. Il
| > | faudrait lui démander.)
|
| > C'est simple : C++ est influencé directement par Simula et
| > Simula avait la notion d'héritage, qu'on retrouvera dans « C
| > with Classes ». Et c'était quand déjà ? Voir D&E.
|
| Je sais que l'influence principale, c'était Simula, et que c'est
| de là que viennent les classes. Je sais aussi (d'après ma
| lecture de TC++PL édition 2) que Stroustrup tient (ou tenait)
| les idées de Meyer sur l'orientation objet en estîme,

Oui, mais les idées et les notions fondamentales à la base de
l'introduction de OO en C avec C with Classes viennent de Simula.
L'histoire est là. Tu peux la vérifier.
Mais pourquoi, hein ?

-- Gaby
Avatar
Gabriel Dos Reis
writes:

[...]

| > Je ne pense pas que ce soit par malhonnêteté. Mais je suis
| > d'avis que tu devrais faire preuve de plus de cohérence, de
| > nuance, et sans doute de modération dans tes propos.
|
| Le problème, c'est qu'à chaque coup, je réagis à un posting
| donné.

émotif ?

[...]

| Maintenant, je ne veux pas que ce soit déformer pour dire que je
| pense que la performance n'est jamais importante. La

attention au fanstisme modérateur quand même.

-- Gaby
Avatar
James Kanze
Gabriel Dos Reis wrote:
writes:


[...]


| > Je ne pense pas que ce soit par malhonnêteté. Mais je suis
| > d'avis que tu devrais faire preuve de plus de cohérence,
| > de nuance, et sans doute de modération dans tes propos.


| Le problème, c'est qu'à chaque coup, je réagis à un posting
| donné.


émotif ?


Parfois, oui. Mais surtout, sans régarder plus loin, et en
écrivant une « réaction ». Donc, si X dit A, et je sais que A
est faux, je dis le contraire d'A, même si je sais que la vérité
se trouve quelque part entre les deux. Je m'adresse à celui qui
a écrit, et a ce qu'il a écrit, sans toujours tenir compte que
d'autres le lisent aussi, et qu'ils ne se mettent pas forcément
dans la position de A absolu, et qu'ils lisent mon ~A comme un
absolu, et non comme une réaction contre A.

L'autre problème, évidemment, c'est que j'ai une affreuse
tendance à la verbosité. Ce qui fait que si j'expliquais ce que
je pensais réelement, avec toutes les nuances, ça serait un
livre, et non un posting. Alors, rassure-toi, je connais des
nuances, même si ça ne se voit pas toujours dans mes postings.
Je vois en général les deux côtés de l'argument, même quand je
n'en présente qu'une.

[...]


| Maintenant, je ne veux pas que ce soit déformer pour dire
| que je pense que la performance n'est jamais importante. La


attention au fanstisme modérateur quand même.


Je regrette, mais je ne comprends pas cette phrase.

--
James Kanze home: www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34

Avatar
marc.boyer.news
Bon, j'arrive un peu après la bataille, mais j'ai été privé de news
un certain temps.


Olivier Azeau wrote in message news:<HuzLd.19143$...
J'ai lu avec grand intérêt l'article "Concepts for C++0x" mentionné dans
un thread récent.


Je l'ai lu suite à ton message.

Habituellement, je ne m'intéresse pas aux évolutions du langage car
elles ne me concernent qu'à un relativement long terme, mais là, j'ai
l'impression qu'un mouvement de fond relatif aux paradygmes du C++ prend
une certaine ampleur.
Et ce mouvement m'amène à quelques interrogations.
[SNIP l'exemple]


Une telle approche est actuellement plutôt prisée par des personnes qui
connaissent bien le langage et est donc globalement plutôt minoritaire.
Parmi les raisons de cette situation je vois :
- la forte présence de langages comme Java ou C# qui ne proposent pas
cette approche (les versions "Generic" restent anecdotiques) et donc le
grand nombre de personnes qui font du C++ comme ils font du Java
- le faible support des templates par certains compilateurs jusqu'à une
période récente (cf les interrogations récurrentes relatives au support
des templates dans VC6)
- un support méthodologique peu adapté (UML se prête beaucoup plus à
décrire des héritages que de paramétrages)
- une complexité de mise au point d'une approche à base de templates
(typage structurel, définitions statiques, ...)


Le dernier point me semble le pire frein.


Sur ce, je découvre les "concepts" (dont je ne pense pas avoir saisi le
dixième des utilisations et implications) qui me laissent supposer que,
dans un avenir plus ou moins proche, on pourrait écrire les choses de
manière plus explicites.
[SNIP le long exemple]

Pour ceux qui auront eu le courage de lire jusqu'ici, j'aimerais savoir
s'ils pensent :
- que je n'ai rien compris aux "concepts" ?
- que ces notions vont avoir un impact technique majeur sur l'écriture
de code en C++ ?
- que ces notions vont avoir un impact sociologique majeur sur le
développement en C++ ?

Je suis plus particulièrement intéressé par l'aspect sociologique des
choses.



Puisque tu voulais parler avant tout de l'aspect sociologique, je
dirais que les concepts vont dans le bon sens, puisqu'ils passent
du côté du sous-typage déclaré, alors qu'on en était au sous-typage
structurel (duck-typing).

Sans prétendre que l'un est meilleur que l'autre (même si j'ai mon
avis sur la question), le fait est que le programmeur C++ "de base"
(je mets entre guillemets ) est habitué au sous-typage déclaratif,
puisque c'est celui qui est utilisé dans l'héritage public pour
le sous-typage dynamique. Que le sous-typage statique (template)
offre cette voie là me semble un bon point.

Néanmoins, un reproche au sous-typage déclaratif est son aspect
verbeux. Pour les débutants, la majorité des classes seront
DefautConstructible et Assignable (1). Je pense aux gens qui
désireraient se mettre aux concepts. S'il faut rajouter "models
Assignable, DefautConstructible" sur (presque) toutes les classes
d'un projet, pour pouvoir utiliser vector, les gens hésiteront
surement, non ?

Mais c'est le seul bémol que je vois à la proposition. Elle me semble
aller dans le bon sens sinon. J'ai noté que le papier proposait
de définir une interface et pas simplement des cas d'utilisations
(constraints), ce qui me semble le bon choix.

En fait, ça fait quelque temps que je dis, quand on me demande pourquoi
je m'intéresse tant à C++ que je dis qu'un champs d'expérimentation sur
la généricité y a été ouvert. La généricité était présente dans d'autres
languages (Eiffel, Ada), mais sous une forme plus contrainte (mais on
savait où on allait). Là, C++ semble avoir la maturité sur le sujet pour
transformer l'expérimentation en technique maitrisée.


(1) D'ailleurs, C++ génère par défaut un constructeur de copie et
un opérateur = pour une classe si on ne lui dit rien. Assignable
semble donc plus la norme que l'exception.


J'ai l'impression d'être face à une évolution du même ordre de grandeur
que le passage du C au C++.


En effet, dans le sens où, en passant du C à C++ beaucoup de gens
sont passés du procédural à l'OO, qui avait déjà été défriché par pas
mal de langages.

Pour tout dire, j'ai même l'impression que le terme C++ n'est conservé
que pour des raisons marketing (la "marque" est déja connue, appréciée,
possède une base de consommateurs, ...)


Non, pas que. Il y a aussi (surtout ?) la compatibilité asendante:
on pourra avoir dans le même code des bouts "anciens" (OO et templates
limités à l'utilisation de vector et map) et des bouts "nouveaux".

Il est toujours possible d'écrire du C avec un compilateur C++ mais, sur
une période d'environ 10 ans (en gros les années 90) on est passé d'une
approche majoritaire en termes de structures/procédures a une approche
majoritaire classes/héritages/associations.
Cela a impliqué un changement de principes de modélisation, un
changement de techniques d'écriture de code mais surtout un changement
de mentalité.
Et quand je regarde les efforts qu'il a fallu déployer pour que
l'ensemble des intervenants en arrive à penser les développements plus
ou moins de la même manière, j'ai un peu l'impression, en voyant ces
nouvelles notions qui se profilent à l'horizon, que nous ne sommes pas
au bout de nos peines...


Tout à fait.
Mais avant d'avoir une unité dans le développement, il vaut mieux
avoir des outils. Voilà, il me semble que les outils arrivent.

Marc Boyer

7 8 9 10 11