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

Avatar
Gabriel Dos Reis
James Kanze writes:

| Gabriel Dos Reis wrote:
| > Olivier Azeau writes:
|
| > | Gabriel Dos Reis wrote:
| > | > Olivier Azeau
| writes:
| > | > [...]
| > | > | Le critère de performance, je l'oublie car dans la
| > | > | plupart des applis C++ (et surtout dans toutes celles
| > | > | que je connais) le goulot d'étranglement ne vient pas du
| > | > | polymorphisme dynamique.
|
| > | > cela en dit beaucoup sur les programmes que tu n'as pas vus ;-/
|
| > | Et cette réponse en dit autant à ton sujet ;-)
|
| > très certainement.
|
| [...]
|
| > je ne nie pas ce que tu affirmes connaître. Je te fais juste
| > remarque ue la communauté C++ est très diverse et variée. Ses
| > utilisations aussi. Comme BS dirait « I don't know what C++
| > programmers do. » Je ne sais pas non plus, mais je peux
| > certainement reconnaître des affirmations basées sur des faits
| > très limités.
|
| Et pourquoi est-ce que tu ne l'as pas dis comme ça d'abord ?

qu'avais-tu compris (en espérant que tu aies lu le message) ?

-- Gaby
Avatar
Gabriel Dos Reis
Olivier Azeau writes:

| Ivan Vecerina wrote:
| > "Olivier Azeau"
| > wrote in message news:1ldMd.19835$
| >> Aujourd'hui c'est plutôt simple car les templates sont en fait
| >> relativement peu utilisés.
| > ??? Il me semble qu'à ce jour les STL de la librairie standard
| > sont utilisés de plus en plus intensément. Et qui n'utilise
| > pas des 'smart pointers' en C++ (également des templates) rate
| > sérieusement quelque chose en terme de qualité/maintenance/etc
| > du code.
|
| Il y a quand même un monde entre écrire des classes templates et en
| prendre des toutes prêtes, non ?

Oui.

-- Gaby
Avatar
Ivan Vecerina
"James Kanze" wrote in message
news:42028b18$0$24299$
Ivan Vecerina wrote:
AMHA Gaby ne manque jamais de courtoisie envers ceux qui
cherchent à apporter des réponses à ses questions.


Dans la mésure que les réponses sont celles qu'il voulait
entendre, parce que sinon...

Ou est-ce que tu as simplement oublié l'émoticon, et c'est un
essai à l'ironie ?


Ma remarque ne concertait pas uniquement ce commentaire
spécifique d'Olivier. Je pense que lorsqu'on pose une
question et demande des commentaires, il est bon de
ne pas emettre des jugement sommaires sur ces-derniers.
Je suis naturellement (encore) plus tolérant envers celui
qui fait l'effort de répondre.
C'est ma philosophie perso.

J'ai vu de très près un projet européen où l'un des goulots
d'étranglement était précisément la virtualité à toutes les
sauces :




Mais évidemment, Olivier n'a jamais dit qu'une telle chose était
impossible. Seulement, il y a bien peu d'applications réelles où
c'est le cas. (Même dans nos applications de marché, qui sont
des bêtes de calcul numérique, les fonctions virtuelles ne
posent pas de problème.)


Je ne suis pas un gourou des templates ou de la programmation
générique, et MC++D ne m'inspire que très lointainement.
Je ne suis pas dans le calcul numérique avancé non plus.

Mais qu'il s'agisse de traitement d'image, de programmation
graphique, de jeux, de systèmes temps-réel ou de programmation
multi-process, je trouve réguilérement une place à la
paramétrisation d'algorithmes ou de diverses classes.

Qu'il s'agisse des caractères d'un texte, d'un pixel d'une image,
ou d'un vertex sur un modèle 3D, il est excessivement coûteux
d'utiliser de l'orienté objet et des appels virtuels "à la pièce".
[et j'ai pu le constater très concrètement...]
Par contre, la flexibilité apportée par la paramétrisation
judicieuse de certains composants apporte des avantages majeurs,
en terme de maintenance et de performance.

Dans les applis que je connais, les bottlenecks il faut les
chercher dans les allocations dans le tas,



Dans les applications que j'ai vu, le goulot a prèsque toujours
été l'écriture disque. Une écriture disque, c'est 10
millisecondes, incomprimable. Avec les processeurs modernes, 10
millisecondes CPU, c'est une éternité.


Dans mes applications interactives critiques en terme de
performance, le 'goulot' principal souvent l'accès mémoire.
D'ou l'importance de la contiguité des accès, et la tendance
(dans tout ce qui est graphisme et structures de données)
à utiliser des SOA plutôt que des AOS (structures de tableaux
dynamiques (structure of array) plutôt que tableaux de structures)
ce qui permet d'augmenter la densité des données accédées
par un algorithme spécifique.

Pour ce qui est des accès disque (lecture ou écriture), je
procède en général par memory-mapping (sous NT ou Unix).
Ceci simplifie le code et permet au systèmes d'optimiser
et de paralléliser les accès mémoire.

Pour la reste, il y en a encore un qui n'a pas compris ton
propos. Comment on optimise, on le sait. La question était bien,
qu'est-ce qu'il faut optimiser. (Et oui, ça m'est arrivé aussi
une fois que le goulot était bien les allocations mémoire. Et la
solution était de allouer moins souvent, non d'optimiser des
allocations pour un type particuler.)
Un système de cache pour les allocations, ça se paramétrise

également volontiers, pour qu'il ne s'applique pas uniquement
à un type particulier ;)


Amicalement,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form




Avatar
kanze
Ivan Vecerina wrote:
"James Kanze" wrote in message
news:42028b18$0$24299$


[...]
Mais évidemment, Olivier n'a jamais dit qu'une telle chose
était impossible. Seulement, il y a bien peu d'applications
réelles où c'est le cas. (Même dans nos applications de
marché, qui sont des bêtes de calcul numérique, les
fonctions virtuelles ne posent pas de problème.)


Je ne suis pas un gourou des templates ou de la programmation
générique, et MC++D ne m'inspire que très lointainement. Je
ne suis pas dans le calcul numérique avancé non plus.

Mais qu'il s'agisse de traitement d'image, de programmation
graphique, de jeux, de systèmes temps-réel ou de programmation
multi-process, je trouve réguilérement une place à la
paramétrisation d'algorithmes ou de diverses classes.


Quel rapport ? Quand les templates conviennent, on utilise les
templates. Quand l'héritage convient, on utilise l'héritage. Les
deux sont là pour une raison, et c'est même plutôt rare que
leurs champs d'applications se récouvrent.

Qu'il s'agisse des caractères d'un texte, d'un pixel d'une
image, ou d'un vertex sur un modèle 3D, il est excessivement
coûteux d'utiliser de l'orienté objet et des appels virtuels
"à la pièce". [et j'ai pu le constater très concrètement...]

Par contre, la flexibilité apportée par la paramétrisation
judicieuse de certains composants apporte des avantages
majeurs, en terme de maintenance et de performance.

Dans les applis que je connais, les bottlenecks il faut
les chercher dans les allocations dans le tas,



Dans les applications que j'ai vu, le goulot a prèsque
toujours été l'écriture disque. Une écriture disque, c'est
10 millisecondes, incomprimable. Avec les processeurs
modernes, 10 millisecondes CPU, c'est une éternité.


Dans mes applications interactives critiques en terme de
performance, le 'goulot' principal souvent l'accès mémoire.
D'ou l'importance de la contiguité des accès, et la tendance
(dans tout ce qui est graphisme et structures de données) à
utiliser des SOA plutôt que des AOS (structures de tableaux
dynamiques (structure of array) plutôt que tableaux de
structures) ce qui permet d'augmenter la densité des données
accédées par un algorithme spécifique.


Tu fais donc beaucoup de calcul pour peu d'affichage, sur de
grands jeux de données en mémoire. Ce sont typiquement des
applications numériques où c'est le cas, ou peut-être les jeux.
Mais ce n'est pas typique de beaucoup de programmeurs ; si je
régarde dans les démandes d'emploi, par exemple, il y a fort peu
de démande pour les matheux, en dehors des banques (et les
programmes de marché sont un peu spéciaux comme applications
numériques, parce qu'ils ne traitent en général qu'un petit jeu
de données, en lui appliquant des formules on ne peut plus
compliquées).

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.

Pour ce qui est des accès disque (lecture ou écriture), je
procède en général par memory-mapping (sous NT ou Unix). Ceci
simplifie le code et permet au systèmes d'optimiser et de
paralléliser les accès mémoire.


Mais ça ne garantit rien. L'écriture n'est pas forcement faite.
C'est bon pour des choses « jettables », mais je n'ai pas le
droit d'informer le client que son ordre a été pris en compte
tant que je ne peux pas garantir pouvoir le récupérer, même en
cas de crash système.

Pour la reste, il y en a encore un qui n'a pas compris ton
propos. Comment on optimise, on le sait. La question était
bien, qu'est-ce qu'il faut optimiser. (Et oui, ça m'est
arrivé aussi une fois que le goulot était bien les
allocations mémoire. Et la solution était de allouer moins
souvent, non d'optimiser des allocations pour un type
particuler.)


Un système de cache pour les allocations, ça se paramétrise
également volontiers, pour qu'il ne s'applique pas uniquement
à un type particulier ;)


Mais si le problème, s'est qu'on fait trop de copies et trop
d'allocations, la solution n'est pas d'optimiser les
allocations.

--
James Kanze GABI Software http://www.gabi-soft.fr
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:

[...]

| > Mais qu'il s'agisse de traitement d'image, de programmation
| > graphique, de jeux, de systèmes temps-réel ou de programmation
| > multi-process, je trouve réguilérement une place à la
| > paramétrisation d'algorithmes ou de diverses classes.
|
| Quel rapport ? Quand les templates conviennent, on utilise les
| templates. Quand l'héritage convient, on utilise l'héritage. Les

Monsieur de la Palisse n'aurait pas dit le contraire.

| deux sont là pour une raison, et c'est même plutôt rare que
| leurs champs d'applications se récouvrent.

Ah bon. simple example, regarder comment la généricité est pratiquée
dans des langages comme Java et autres et avant (peut-être encore
aujourd'hui) avec C++ dans certains milieux par des autor-proclamés
orienté objets. Mais hein.

-- Gaby
Avatar
Ivan Vecerina
| wrote in message
|news:
|Ivan Vecerina wrote:
|> "James Kanze" wrote in message
|> news:42028b18$0$24299$
|> Mais qu'il s'agisse de traitement d'image, de programmation
|> graphique, de jeux, de systèmes temps-réel ou de programmation
|> multi-process, je trouve réguilérement une place à la
|> paramétrisation d'algorithmes ou de diverses classes.
|
|Quel rapport ? Quand les templates conviennent, on utilise les
|templates. Quand l'héritage convient, on utilise l'héritage. Les
|deux sont là pour une raison, et c'est même plutôt rare que
|leurs champs d'applications se récouvrent.

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 pour pouvoir manipuler des données (relativement) brutes
et pas tout-à-fait encapsulée derrière des objets et des messages
que l'on doit se résoudre à avoir recours à d'autres formes
de dispatching et de réutilisation de code.
Le résultat, en C++, est effectivement que l'on a des champs
d'application relativement distincts pour les templates et
les fonctions virtuelles/héritages.


|> Pour ce qui est des accès disque (lecture ou écriture), je
|> procède en général par memory-mapping (sous NT ou Unix). Ceci
|> simplifie le code et permet au systèmes d'optimiser et de
|> paralléliser les accès mémoire.
|
|Mais ça ne garantit rien. L'écriture n'est pas forcement faite.
|C'est bon pour des choses « jettables », mais je n'ai pas le
|droit d'informer le client que son ordre a été pris en compte
|tant que je ne peux pas garantir pouvoir le récupérer, même en
|cas de crash système.
Qu'il s'agisse de memory-mapping ou d'écriture d'une séquence
d'octets, là n'est pas la question. Sans flush il n'y a pas de
garantie, ni dans un cas ni dans l'autre.



|> > Dans les applications que j'ai vu, le goulot a prèsque
|> > toujours été l'écriture disque.

Sur quoi j'ai mentionné un autre genre d'applications...
la réponse pourrait presque être amusante:

|Si tu régardes autour de toi, tu verras que la plupart des
|programmes font bien peu de choses, en somme.

Qui ne voit pas assez loin ?
Qu'est-ce qui définit "la plupart" ?


|Tu fais donc beaucoup de calcul pour peu d'affichage, sur de
|grands jeux de données en mémoire. Ce sont typiquement des
|applications numériques où c'est le cas, ou peut-être les jeux.
|Mais ce n'est pas typique de beaucoup de programmeurs ; si je
|régarde dans les démandes d'emploi, par exemple, il y a fort peu
|de démande pour les matheux, en dehors des banques (et les
|programmes de marché sont un peu spéciaux comme applications
|numériques, parce qu'ils ne traitent en général qu'un petit jeu
|de données, en lui appliquant des formules on ne peut plus
|compliquées).
Je suis impressionné par la portée de l'interprétation et
du jugement que vous vous permettez de faire. Le "matheux
qui fait beaucoup de calcul pour peu d'affichage, sans perspective
professionnelle sinon dans le bancaire pour faire des trucs très
compliqués avec peu de données" avait jusqu'à présent une
certaine considération pour vous.

Voilà qui me coupe l'envie de poursuivre.
Avatar
Alain Naigeon
"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é)

--

Français *==> "Musique renaissance" <==* English
midi - facsimiles - ligatures - mensuration
http://anaigeon.free.fr | http://www.medieval.org/emfaq/anaigeon/
Alain Naigeon - - Strasbourg, France

Avatar
Gabriel Dos Reis
"Ivan Vecerina" writes:

[...]

| |Tu fais donc beaucoup de calcul pour peu d'affichage, sur de
| |grands jeux de données en mémoire. Ce sont typiquement des
| |applications numériques où c'est le cas, ou peut-être les jeux.
| |Mais ce n'est pas typique de beaucoup de programmeurs ; si je
| |régarde dans les démandes d'emploi, par exemple, il y a fort peu
| |de démande pour les matheux, en dehors des banques (et les
| |programmes de marché sont un peu spéciaux comme applications
| |numériques, parce qu'ils ne traitent en général qu'un petit jeu
| |de données, en lui appliquant des formules on ne peut plus
| |compliquées).
| Je suis impressionné par la portée de l'interprétation et
| du jugement que vous vous permettez de faire. Le "matheux
| qui fait beaucoup de calcul pour peu d'affichage, sans perspective
| professionnelle sinon dans le bancaire pour faire des trucs très
| compliqués avec peu de données" avait jusqu'à présent une
| certaine considération pour vous.
|
| Voilà qui me coupe l'envie de poursuivre.

Patience.
Pour je ne sais quelle raison, James a tendance à faire passer pour
secondaire tout ce qui a relation de près ou de loin au monde
scientifique. Probablement, parce qu'il part du principe que tout ce
qu'il ne connaît pas n'existe.
Si tu persévères un peu, il se décribilisera lui même et tu n'auras
plus besoin d'avoir envie de poursuivre la discussion. Mais, cela peut
prendre un certain temps.

-- Gaby
Avatar
Gabriel Dos Reis
"Alain Naigeon" writes:

| "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é)

Je ne comprends pas ce que tu veux dire. Il est possible d'écrire des
programmes inefficaces dans n'importe quel langage.
Cependant, la possibilité d'exprimer certaines choses directement en
C++ peut amener en fait à gagner en efficacité.

http://www.research.att.com/~bs/new_learning.pdf

-- Gaby
Avatar
Olivier Azeau
Ivan Vecerina wrote:
| wrote in message
|news:
|Quel rapport ? Quand les templates conviennent, on utilise les
|templates. Quand l'héritage convient, on utilise l'héritage. Les
|deux sont là pour une raison, et c'est même plutôt rare que
|leurs champs d'applications se récouvrent.

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.


Qu'est-ce qui définit "souvent" ? (qui finalement n'est qu'un synonyme
de "la plupart")
J'ai croisé la route d'un certain nombre d'applis avec du C++ dedans
qui, certes, ne sont probablement pas représentatives de quoi que ce
soit et je n'ai jamais vu un tel coût rédhibitoire.
Ceci étant dit, personne ne fait du tout-dynamique pour le plaisir d'en
faire : il arrive parfois à quelqu'un qui n'utilise jamais de templates
de mettre autre chose que des pointeurs comme membres de ses classes.

C'est pour pouvoir manipuler des données (relativement) brutes
et pas tout-à-fait encapsulée derrière des objets et des messages
que l'on doit se résoudre à avoir recours à d'autres formes
de dispatching et de réutilisation de code.


C'est quoi ces données brutes ?
Des grands jeux de données en mémoire ? ;-)

Le résultat, en C++, est effectivement que l'on a des champs
d'application relativement distincts pour les templates et
les fonctions virtuelles/héritages.


En l'état actuel, je vois surtout des champs sociologiques distincts :
des connaisseurs++ qui font des templates et les autres.

[...]
|> > Dans les applications que j'ai vu, le goulot a prèsque
|> > toujours été l'écriture disque.

Sur quoi j'ai mentionné un autre genre d'applications...
la réponse pourrait presque être amusante:

|Si tu régardes autour de toi, tu verras que la plupart des
|programmes font bien peu de choses, en somme.

Qui ne voit pas assez loin ?
Un myope ?


Qu'est-ce qui définit "la plupart" ?
La même chose que ce qui définit "souvent".


En fait, la remarque de James ne me surprend pas car j'ai souvent vu de
près des parties de systèmes qui ne faisaient "rien", en tout cas rien
de bien compliqué au niveau technique : pas de calcul, pas d'algorithme
complexe, pas de gros jeux de données, pas trop de classement de
données, de l'affichage (mais avec des composant tiers qui prennent en
charge le gros du boulot), du stockage de données (mais sans toucher au
disque car le SGBD est là pour ça), du réseau (au pire avec des sockets)
Et des applis qui ne font pas tout ça, il y en a des tas parce qu'un des
gros besoin (sinon le plus gros) c'est de (bien) relayer l'information
entre les quelques morceaux qui eux font vraiment quelque chose.

Dans tout ce code qui ne fait rien, généralement là pour répondre aux
besoins (changeants) des utilisateurs, on se soucie des performances
mais sans jamais, pour ainsi dire, remettre en cause le typage dynamique.
Ce dont ce code a surtout besoin c'est d'être lisible par le plus grand
nombre (genre Paris-Match ou Télé 7 jours) et d'être écrit le plus
rapidement possible (mêmes exemples). Donc écrire une classe template =
OVNI sauf pour certains cas maîtrisés (des traits par exemple)

Les raisons techniques qui font que ce code est écrit en C++ se résument
souvent à un langage compilé (le C) et facile à lire (le ++)
Les autres raisons sont souvent plus sociologiques (terrain connu,
ressources humaines, réputation, ...)

Tout ça pour dire que je pense continuer mes essais pour mieux
comprendre les templates et les notions encore plus avancées qui s'y
rapportent mais sans grand dessein quant à leur utilisation en tant que
vulgus pecum du développement C++ (du moins pas avant une décade)

|Tu fais donc beaucoup de calcul pour peu d'affichage, sur de
|grands jeux de données en mémoire. Ce sont typiquement des
|applications numériques où c'est le cas, ou peut-être les jeux.
|Mais ce n'est pas typique de beaucoup de programmeurs ; si je
|régarde dans les démandes d'emploi, par exemple, il y a fort peu
|de démande pour les matheux, en dehors des banques (et les
|programmes de marché sont un peu spéciaux comme applications
|numériques, parce qu'ils ne traitent en général qu'un petit jeu
|de données, en lui appliquant des formules on ne peut plus
|compliquées).
Je suis impressionné par la portée de l'interprétation et
du jugement que vous vous permettez de faire. Le "matheux
qui fait beaucoup de calcul pour peu d'affichage, sans perspective
professionnelle sinon dans le bancaire pour faire des trucs très
compliqués avec peu de données" avait jusqu'à présent une
certaine considération pour vous.


Je suis certain qu'il n'y avait aucun jugement personnel dans la
remarque mais il faut quand même avouer que les besoins en connaisseurs
de C++ de haut niveau (j'entends par là le besoin d'une connaissance qui
va au delà d'une programmation à la Java) ne courent pas les rues (ou
alors c'est que ceux qui en ont besoin l'ignorent)

Voilà qui me coupe l'envie de poursuivre.


Il est fort probable par ailleurs que ce thread ait assez duré...