Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Erreur du preprocesseur

113 réponses
Avatar
candide
Bonjour,

Dans le bouquin de Ph. Drix ("Le langage C ANSI"), je trouve l'exemple
suivant pour illustrer les "substitutions réitérées" par le préprocesseur :


------------- 8< -------------------------------
#define w 0,1
#define f(x,y) (x)+(y)

f(w) /* est remplacé par (0)+(1) */
------------- >8 -------------------------------


Or, chez moi sur gcc, ça ne marche pas :

------------- 8< -------------------------------
candide@candide-desktop:~$ gcc -E test.c

test.c:4:4: erreur: macro « f » requiert 2 arguments, mais seulement 1
ont été passés
f
------------- >8 -------------------------------

Pourtant il me semble que l'exemple est valide, non ?

10 réponses

Avatar
Wykaaa
Wykaaa wrote:
In article <47f24354$0$898$,
Wykaaa wrote:
Ca dépend. Si seulement c'était bien enseigné !
Et aujourd'hui, il y a quand même de très bon bouquins sur ces sujets
(la plupart en anglais, hélas...)
J'ai fabriqué des cours sur tout ça, faudrait que je les mette en
ligne...
Le plus gros probleme est d'ordre psychologique: les vraies bases sont

tres simples. Elles s'expliquent en cinq minutes, mais sont dures a
appliquer correctement... je crois plus a l'approche _refactoring_ pour
enseigner ces notions.

Prend un cours `classique' d'oriente objet, tu vas expliquer
abstraction et encapsulation en cinq minutes, et passer 3/4 h sur
l'heritage... et apres, si tu demandes a un etudiant de te
caracteriser programmation OO, forcement
il va te parler d'heritage...
Dans l'enseignement de l'approche objet, j'ai toujours adopté l'approche

de Grady Booch.


Le probleme c'est que cette approche est fortement correlee avec les
langages static avec single-dispatch. Dans les languages dynamiques
et/ou avec multiple-dispatch, les responsabilites sont reparties tres
differement.
C'est vrai mais en première approche, pour des novices, ceci n'est pas

très grave. Il faudra raffiner plus tard dans le cursus.

Je dis (et je décris) que les 4 concepts majeurs de l'objet sont :
- le concept d'abstraction
- le concept d'encapsulation
- le concept de modularité


Ce "concept" (qui n'en est pas un) est un terme vague (inspire de la
notion de module?) incluant l'encapsulation et la reutilisabilite qui
inclue elle-meme la composabilite.


Bien sûr que si, la modularité est un concept. Ca me fait justement
bondir, à chaque fois que j'entends des informaticiens qui disent le
contraire. Et c'est bien pour ça que la conception globale est
généralement "foirée" parce que ce concept est mal appliqué (car les
gens ne le comprennent pas)..
Dans le contexte objet, ce n'est pas un terme vague. ce qui trompe,
c'est que la modularité a plusieurs niveaux de granularité (je parle,
encore une fois, de la modularité dans le cadre de l'objet). Du plus fin
au plus grossier :
- la classe,
- le package : ensemble de classes
- le composant : ensemble de packages (dans l'approche de développement
par composants)
- le sous-système : ensemble de composants

Si l'on prend la hiérarchie IEEE, il y a d'autres groupements
intermédiaires.

Là vous mélangez beaucoup de choses. L'encapsulation est un concept à
part (on peut faire des modules où tout est visible à l'extérieur). La
composabilité est au niveau le plus fin des classes (du moins au sens ou
on entend composabilité en objet, à savoir lien de composition). C'est
donc une des relations de hiérarchie. La modularité est une condition
pour la réutilisabilité

(au sens objet et non pas dans son sens plus
ancien) qui s'appuie sur les deux principes de : 1- Forte cohésion
interne d'une abstraction, 2- faible couplage entre abstraction


Ce ne sont pas des principes mais des metriques (ordinal) tres utiles
pour eviter/detecter les mauvais designs.


Non. Ce sont bien des principes sur lesquels s'appuie la modularité (au
sens objet, sinon on n'aurait pas le faible couplage dont une partie est
mise en oeuvre grâce au concept d'encapsulation). C'est tout ceci qui
montre, comme je l'ai dit ailleurs, comment les différents concepts
"s'épaulent" les uns, les autres.

La métrique de faible dépendance est :
(nombres de dépendances entre modules)/(nombre de modules) = 1 (+ ou -
0,2 environ) en remplaçant module par classe, package, etc.

- La notion de hiérarchie : héritage, mais aussi agrégation et
composition qui sont toutes 3 des relations d'ordre strict entre
abstractions (c'est fondamental de comprendre ça pour éviter des erreurs
de conception)

Une fois exposer ces 4 concepts majeurs, j'indique, en insistant
fortement, que ce n'est qu'à la condition que ces 4 concepts soient mis
en oeuvre conjointement qu'on peut parler d'approche objet.


Interessant. Sauf que la notion de Programmation Orientee Objet n'est
pas clairement definie a ma connaissance (avec d'interminable debat
sur
le sujet).


Vous parlez de programmation OO alors que je parle d'approche OO !
Cette approche est parfaitement définie depuis les premiers articles de
Grady Booch en 83 (25 ans quand même !).

La notion d'heritage inclue plusieurs concepts bien souvent
melanges ce qui rend son enseignement difficile.


Quels sont les concepts que mélange la notion d'héritage ?
L'héritage est un sous-concept de la notion de hiérarchie entre modules,
un point c'est tout (c'est donc une relation entre modules au même titre
que l'agrégation et la composition. Elle en a les mêmes propriétés :
c'est une relation d'ordre stricte).

Enfin, puisque vous
connaissez plus de 50 languages, vous devriez savoir que les concepts
cites ci-dessus sont aussi presents dans des languages _non_ objet
(fonctionnel ou prototype par exemple) et donc ne suffisent pas a
caracteriser un language OO.


La modularité existait avant l'objet, bien sûr voir l'article de Parnas
en 72 "On the Criteria To Be Used in Decomposing Systems into Modules"
(voir : http://sunnyday.mit.edu/16.355/parnas-criteria.html) mais la
modularité a été redéfinie dans le cadre de l'objet en s'appuyant sur
les principes de forte cohésion interne d'un module (il traite une seule
abstraction et cette abstraction est traitée entièrement dans le module
) et le faible couplage (minimiser les dépendances entre modules et
encapsuler les détails non nécessaires à leur utilisation).

Encore une fois, je ne cherche pas à caractériser un langage de
programmation OO mais l'approche OO (ceci est moins difficile).
Je ne tiens pas à rentrer dans la querelle des langages OO ou pas OO
(qui est sans fin et n'apporte rien)


Ce qui _pourrait_ caracteriser un language OO, c'est subtyping +
polymorphisme (d'inclusion). Ces deux concepts sont les seuls vraiment
present dans tous les languages OO et absent dans les non OO.


Je ne parlais pas de ce qui caractérise un langage objet mais des
concepts à mettre en oeuvre pour qu'on puisse parler de véritable
approche objet (ce n'est pas du tout la même chose).

Le subtyping existe dans ADA 83 qui n'est pas objet.

Il y a en fait 4 sortes de polymorphismes :
- Le polymorphisme ad'hoc : la surcharge et la coercion (conversion de type)
- Le polymorphisme universel qui se subdivise en polymorphisme
paramétrique (comme dans ML, par exemple) et en polymorphisme d'héritage
(qui est effectivement appelé, quelques fois, polymorphisme d'inclusion)

Cf lucacardelli.name/Papers/OnUnderstanding.A4.pdf (le fameux article de
Cardelli et Wegner : "On Understanding Types, Data Abstraction, and
Polymorphism" qui est ce que je connais de mieux sur le sujet)



Après, il faut faire de nombreuses études de cas pour montrer comment,
EFFECTIVEMENT, ces 4 concepts doivent être mis en oeuvre ENSEMBLE dans
une réelle approche objet et comment ils contribuent les uns aux autres
à cette approche.


J'ai fait ca pas plus tard que la semaine derniere a des physiciens
qui
ne connaissait rien d'autre que Fortran 77 (qui sevit encore ici, he
oui...) et un peu C. Ca m'a pris 6-7 heures, dont la moitie sur
l'impact
des concepts des languages de programmations sur le design de
software.
En revanche mon approche n'est pas dans les livres (et donc discutable
a
souhait, en particulier ma classification des concepts). Neanmoins,
tout
le monde a compris en 1h a 2h (pour la partie OO).


Oui mais quelle est votre approche ?
Vous n'en dites rien alors que j'ai détaillé la mienne.
Ce qui me gêne c'est que vous vous situez toujours par rapport aux
langages de programmation OO alors que ce n'est pas mon cas.

Pédagogiquement parlant, je ne passe pas plus de temps sur la notion de
hiérarchie (et pas seulement l'héritage, c'est ça la clé) que sur les
autres concepts.


C'est dommage, parce que dans les languages a typage statique, la
notion
de hierarchie est intrinsequement liee a celle de couplage que l'on
cherche a eviter. Le jeux consiste donc a montrer comment reorganiser
les hierarchies pour diminuer le couplage sans rendre Liskov furieux.


Je vous reprends : "sans rendre Liskov furieuSE". j'ai assisté à un
workshop de Barbara Liskov (auteur du langage CLU) en 85 à Berlin.
C'était extra.
Vous faites allusion au fameux principe de substitution ?

C++ utilise les templates presque partout pour resoudre ce probleme,
mais les autres languages n'ont guere le choix que d'utiliser des
interfaces (au sens Java du terme).


Mais les interfaces "à la Java" c'est très bien non ?

J'ai vu une application de 450 mille lignes de Java qui utilisait très
proprement les interfaces. Cette application était nickel.

Enfin, je ne suis pas d'accord que les "vraies" bases s'expliquent en 5
minutes car moi j'y passe 3 (oui trois) jours sur les 4 concepts.


Je suis d'accord, 3-4 jours c'est ce qu'il faut pour un etudiant moyen
n'ayant aucun background sur le sujet. Ne serait-ce que pour lui
laisser
le temps de se faire a l'idee (comme pour les pointeurs). Le probleme,
c'est qu'il faut encore 1-2 ans pour savoir le mettre a profit dans
des
gros projets (design).


Hélas oui, mais il n'y a pas de mystère...




Avatar
Antoine Leca
En news:47f29e3d$0$863$, Wykaaa va escriure:
En news:, wykaaa va escriure:
Pour le Web, les gens utilisent n'importe quoi et il n'y a qu'à
regarder les résultats catastrophiques concernant l'interopérabilité
multi-plateformes (les sites qui ne marchent qu'avec tel OS ou tel
navigateur, ou le machin flash dernier cri, etc.).


Il semble clair que l'interopérabilité multi-plateforme n'est *PAS*
le critère primordial d'un serveur web.


Ceci est contraire à l'esprit des pionniers de l'Internet.


Et alors ? Qui s'en préoccupe ?
L'esprit de Niels Bohr ou d'Alfred Einstein était contraire à l'utilisation
qui a été faite de leurs inventions, mais qui peut-on aujourd'hui ? La
France devrait-elle se priver de l'arme atomique sur ce principe-là ?
[ L'exemple est outré mais je pense que l'idée devrait être claire. ]


Par contre, en ce qui concerne le délivré, actuellement les choses
s'améliorent beaucoup, les normes étant nettement moins mouvantes...
En effet, quand la période entre deux versions incompatibles entre
elles des « standards » est inférieure au temps moyen de dévelop-
pement d'un site web, il est difficile de réussir l'impossible.


Les standards de l'Internet (et pas seulement du Web) sont les RFC,
ceux du W3C et de l'IETF (Internet Engineering Task Force).


J'ai pris la peine de mettre le mot norme en début de paragraphe, et
d'entourer standard de guillemet ; donc j'osais espérer que personne ne
ferait d'auto-traduction du mot anglais... :-(

Par ailleurs et pour revenir aux normes, le W3C ne produit qu'épisodiquement
des RFC. Et à mon goût, ils produisent beaucoup trop de choses et donc des
choses pas assez stabilisées, qui ne sont pas appliquées dans les faits ; et
cela ne date pas d'aujourd'hui, au moment du grand boum d'internet ils
travaillaient d'arrache-pied sur HTML 3.0...


Depuis que 1º Microsoft a imposé un navigateur sur >90% des
machines cibles, et que 2º --en rupture complète avec le passé
immédiat-- a cessé de le développer dans toutes les directions
pendant 6 ans, c'est beaucoup mieux ! Le bienfait des standards...


Microsoft n'a fabriqué quasiment aucun standard


... et on va donc dire que Windows est un système d'exploitation parmi
beaucoup d'autres... voire même bien inférieur à beaucoup d'autres...

...surtout quand quelques lignes plus bas, tu rajoutes:
Il y a deux types de standards les standards de Jure et les standards
de Facto.


Évidemment, dans mon propos il faut lire « norme » pour désigner les
premiers.

Les seconds sont en bien plus grand nombre...


Tu as dû te tromper de sens : il y a bien plus de norme inappliquées (les
RFC en sont à plus de 5000) que de normes issues de la standardisation sur
la base d'un existant.



(quand il a tenté, souvent il s'est fait renvoyé dans les cordes...).


[ Cela va faire bien rire ceux qui travaillent dans le groupe chargé du
développemnt de la norme C++ ; sans parler de C#. ]


Quant à son navigateur, parlons-en, il n'est plus développé sur Mac
depuis la version 5.2. Pour Linux, je ne sais pas. C'est donc un total
non respect des plates-formes et des OS.


Les versions Unix ne sont pas allées au-delà de 5.0 (et je ne crois pas
qu'il y ait eu une version pour Linux, en dehors de Wine évidement).
Mais comme je l'écrivai ci-dessus, pour Windows non plus il n'y eut
quasiment aucun développement à partir du moment où il est devenu clair que
Netscape n'était plus un concurrent.

Et le gros _bénéfice_ de cela pour nous autres utilisateurs, c'est que
l'inflation des nouveautés avec sa conséquence directe, l'obligation de
mettre à jour les applications et les machines tous les quatre matins, s'est
pratiquement arrêtée en 2000. Ouf !

Alors bien sûr (attention je force le trait), les développeurs du W3C ne
sont pas restés les bras croisés, ils ont pondus tout plein de choses autour
d'XHTML, qui sont restées bien soigneusement dans leur coin jusqu'au jour où
des gars un peu plus malins que les autres ont mis au point un système basé
sur les parties intéressantes des normes XHTML et cie, qui fonctionnait à la
fois sur IE5/6 _et_ sur Firefox : gros succès, et à ce que je vois pas du
tout attendu par les développeurs de normes...


La politique de Microsoft a conduit beaucoup de gouvernements à
adopter les standards et, par voie de conséquence, les logiciels
libres qui se basent dessus (plus généralement, ils se basent sur
les standards ouverts.


C'est selon. Ici en Espagne, on a bien des gouvernements qui font des
efforts remarquables dans le sens que tu décris (LinEx).
Et d'un autre côté, tout plein d'administrations qui ne font pas assez
d'efforts pour proposer des solutions indépendantes de la solution
commerciale (www.registradores.org / www.scregistradores.com, qui est le
point de passage obligé pour les entreprises d'une certaine taille pour
présenter ses comptes annuels à l'équivalent de l'INPI, obligent à... avoir
une machine Windows [et même à utiliser Internet Explorer]
http://foros.scregistradores.com/foro_firma/viewtopic.php?tA&highlight=linux&sidž08ccffe7bf083796b93f09beb47a81).
Et puis il y a aussi le manque de moyens des développeurs. Ainsi, même pour
des administrations supposément bien outillées comme le Ministère de
l'industrie et du commerce, le fait d'avoir un client qui n'a pas les
privilèges d'administrateur local (!) est une condition bloquante ; cela
marchait (malheureusement) bien il y a quelques années, mais ces temps-ci
avec Vista, c'est plus chaud... Seule solution, attendre que les
développeurs aient terminé la nouvelle moûture (qui tourne*ra* sur Java), et
entre temps retour sur la vieille machine 2000 ou xp de dépannage.

Je peux multiplier les exemples (dans les deux sens). Il est évident que
tous les jours on voit de nouvelles applications qui fonctionnent sur des
plateformes plus diverses, mais je crois beaucoup au fait que les dites
plateformes se sont stabilisées depuis quelques années, ce qui a permis aux
développeurs de cesser de se concentrer sur d'autres aspects que le suivi de
la dernière version de NN ou IE, comme au glorieux temps.


Antoine



Avatar
Antoine Leca
En news:, JKB va escriure:
Il existe d'autres langages autrement mieux conçus. En Fortran, par
exemple [...]


DO I=1.10

envoie une fusée sur la lune...


Pour moi, la syntaxe C est aussi moisie que la
syntaxe Python sur ce point parce que d'une part un bloc peut être
implicite (if () gnagnagna;) et d'autre part parce qu'une
instruction peut être nulle (if ();).


Dame, il est clair donc que C et Python ont été conçus par des
implémenteurs, tandis que Ada (et probablement la construction IF+THEN/ENDIF
du Fortran que tu cites) ont été conçus par des comités.


Antoine

Avatar
Laurent Deniau
Wykaaa wrote:
Dans l'enseignement de l'approche objet, j'ai toujours adopté l'approc he
de Grady Booch.


Le probleme c'est que cette approche est fortement correlee avec les
langages static avec single-dispatch. Dans les languages dynamiques
et/ou avec multiple-dispatch, les responsabilites sont reparties tres
differement.
C'est vrai mais en première approche, pour des novices, ceci n'est pas

très grave. Il faudra raffiner plus tard dans le cursus.


C'est ce que j'ai cru pendant 15 ans. Aujourd'hui, base sur mon
experience, je pense que les multi-methodes sont plus simple a
enseigner et a apprehender que le single dispatch pour de multiples
raisons (qu'il serait long a expliquer ici mais directement lier au
probleme de design et de ce qu'il faut faire et de ce qu'il ne faut
pas faire).

Je dis (et je décris) que les 4 concepts majeurs de l'objet sont :
- le concept d'abstraction
- le concept d'encapsulation
- le concept de modularité


Ce "concept" (qui n'en est pas un) est un terme vague (inspire de la
notion de module?) incluant l'encapsulation et la reutilisabilite qui
inclue elle-meme la composabilite.


Bien sûr que si, la modularité est un concept. Ca me fait justement
bondir, à chaque fois que j'entends des informaticiens qui disent le
contraire. Et c'est bien pour ça que la conception globale est
généralement "foirée" parce que ce concept est mal appliqué (car l es
gens ne le comprennent pas)..
Dans le contexte objet, ce n'est pas un terme vague. ce qui trompe,
c'est que la modularité a plusieurs niveaux de granularité (je parle,
encore une fois, de la modularité dans le cadre de l'objet). Du plus fin
au plus grossier :
- la classe,
- le package : ensemble de classes
- le composant : ensemble de packages (dans l'approche de développement
par composants)


La encore cette definition est tres specifique. Dans mon cas, je
presente un composant comme un entite elementaire inviolable (brique
de base+encapsulation totale). Ca peut donc etre une fonction (plus
generalement une fermeture lexicale), une classe, un module, etc...

- le sous-système : ensemble de composants


C'est bien ce que je pensais, vous parlez d'encapsulation... La
modularite, c'est la capacite a evolue pour satifaire un contexte
d'application (ex: par composabilite) sans etre modifier,
contrairement a l'adaptabilite qui est la meme chose mais avec la
capacite a etre modifier/adapter facilement (prevu dans le design).

Parce que beaucoup de languages proposent la notion de module, on
parle de modularite, mais le "concept" est lui-meme decomposable en
concept orthogonaux qui aident a mieux comprendre comment tout cela
s'agence.

Si l'on prend la hiérarchie IEEE, il y a d'autres groupements
intermédiaires.

Là vous mélangez beaucoup de choses. L'encapsulation est un concept à
part (on peut faire des modules où tout est visible à l'extérieur).


Et ca n'a de nom que le mot-clef module du langage.

La
composabilité est au niveau le plus fin des classes (du moins au sens ou
on entend composabilité en objet, à savoir lien de composition).


Ce qui est aussi applicable a des fonctions/closures ou meme a des
programmes (ex: philosophie de UNIX). Certe, un concept a une
semantique dependante du domaine, mais il n'y a pas de raison de le
restreindre autant. Restons simple et libre.

C'est
donc une des relations de hiérarchie. La modularité est une condition
pour la réutilisabilité


Ce n'est donc pas un concept puisqu'il peut etre decompose en...
concepts.

(au sens objet et non pas dans son sens plus
ancien) qui s'appuie sur les deux principes de : 1- Forte cohésion
interne d'une abstraction, 2- faible couplage entre abstraction


Ce ne sont pas des principes mais des metriques (ordinal) tres utiles
pour eviter/detecter les mauvais designs.


Non. Ce sont bien des principes


Exemple de principes (tires du LaTeX de la presentation):

Open Closed Principle:
Components should be open for extension but closed for modification

Least Knowledge Principle (Law of Demeter)
Assume and expose as little as possible about components

Liskov Substitution Principle
Subclasses should be substitutable for their base classes

Dependency Inversion Principle
Depend upon abstractions, do not depend upon concretions

Interface Segregation Principle
Few client-specific interfaces are better than one general-purpose
interface

Exemple _d'une_ metrique ordinal de la Cohesion:

Coincidental Cohesion
Components are grouped arbitrarily

Categorical Cohesion
Components are grouped because they do the same kind of things

Sequential Cohesion
Components are grouped because they operate in the same execution path

Structural Cohesion
Components are grouped because they operate on the same data

Functional Cohesion
Components are grouped because they contribute to single well-defined
task

Exemple de concepts:

Encapsulation
Ability to reduce dependencies by hiding/protecting information
begin{itemize}
item Expose (stable) interface} and abstract types
item Hide (unstable) implementation and concrete types
end{itemize}

Indirection
Ability to reach a target through a key/reference/pointer (wide sens)

Aggregation
Ability to group objects into collections

Delegation
Ability to defer/redirect/forward function dispatch

Reflection
Ability to reify meta-information
begin{itemize}
item {em Introspection}, ability to read/execute meta-data
(interpreter)
item {em Intercession}, ability to modify meta-data (run-time
optimization)
end{itemize}

Donc la Cohesion elle-meme est un concept (localite de la connaissance/
reponsabilite), mais une _forte_ cohesion comme vous le mentionez est
une metrique. Le fait est que dans ma presentation, je donne une
mesure ordinale pour les deux metriques qui semble plus pratique pour
les developpeurs que des metriques cardinales fortement correlees avec
certains langages (modele objet) et qui n'ont aucune signification
avec d'autre modele objet.

- La notion de hiérarchie : héritage, mais aussi agrégation et
composition qui sont toutes 3 des relations d'ordre strict entre
abstractions (c'est fondamental de comprendre ça pour éviter des err eurs
de conception)

Une fois exposer ces 4 concepts majeurs, j'indique, en insistant
fortement, que ce n'est qu'à la condition que ces 4 concepts soient mi s
en oeuvre conjointement qu'on peut parler d'approche objet.


Interessant. Sauf que la notion de Programmation Orientee Objet n'est
pas clairement definie a ma connaissance (avec d'interminable debat
sur
le sujet).


Vous parlez de programmation OO alors que je parle d'approche OO !


Ok. Dans ce cas, tous les languages ou presque (a condition d'avoir la
notion d'inclusion de type et de pointeur) supporte l'approche OO.
C'est large! Ca inclu C, Pascal, etc...

Cette approche est parfaitement définie depuis les premiers articles de
Grady Booch en 83 (25 ans quand même !).


Et contestee/redefinie chaque annee depuis ;-)

La notion d'heritage inclue plusieurs concepts bien souvent
melanges ce qui rend son enseignement difficile.


Quels sont les concepts que mélange la notion d'héritage ?
L'héritage est un sous-concept de la notion de hiérarchie entre module s,
un point c'est tout


ou est la notion de module dans les languages a prototype?

Et les langages comme Pascal ISO avait la notion de module (package).
Ou est la relation de hierarchie? La encore, c'est l'encapsulation qui
est recherchee, et elle n'a pas de relation hierarchique a priori.

Vous utiliser des termes bien plus vagues que les concepts soujacents
et dont depuis 20 ans personne n'arrivent a donner une definition
claire. Il est en revanche incontestable que des definitions existes,
a peu pres autant que d'auteur d'ouvrage sur le sujet.

(c'est donc une relation entre modules au même titre
que l'agrégation et la composition. Elle en a les mêmes propriétés :
c'est une relation d'ordre stricte).


L'aggregation n'est pas une relation d'ordre stricte puisqu'elle
permet les dependances cycliques. La composition oui.

Enfin, puisque vous
connaissez plus de 50 languages, vous devriez savoir que les concepts
cites ci-dessus sont aussi presents dans des languages _non_ objet
(fonctionnel ou prototype par exemple) et donc ne suffisent pas a
caracteriser un language OO.


La modularité existait avant l'objet,


Je n'ai jamais dis le contraire. C'est bien pour ca que je la definie
comme orthogonal a la notion d'objet et cela apparait clairement
lorsqu'on le decompose sur des concepts ou subtyping et polymorphisme
n'apparaissent pas. Par exemple, les langages fonctionnels permettent
d'ecrire du code beaucoup plus modulaire que les languages objet parce
qu'ils supportent la composition fonctionnelle. En revanche. il est
moins facile d'etendre les fonctions existantes (typiquement par
derivation d'interface) -- pour ce cas, je mets Haskell a part parce
que son systeme de classe permet exactement cela non pas par
derivation comme en OO mais parce qu'il permet d'avoir un modele
ouvert (specialization).

bien sûr voir l'article de Parnas
en 72 "On the Criteria To Be Used in Decomposing Systems into Modules"
(voir : http://sunnyday.mit.edu/16.355/parnas-criteria.html) mais la
modularité a été redéfinie dans le cadre de l'objet en s'appuyant sur
les principes de forte cohésion interne d'un module (il traite une seule
abstraction et cette abstraction est traitée entièrement dans le modul e
)


C'est effectivement un niveau de cohesion (le plus fort). Ceci-dit,
depuis d'autres choses ont ete dites dans le cadre OO, dont

R.C. Martin
Design Principles and Design Patterns
ObjectMentor (http://www.objectmentor.com), 2000.

J. Bloch
How to Design a Good API and Why it Matters
LCSD'05 (http://lcsd05.cs.tamu.edu), 2005.

J. Gorman
Object-Oriented Design Principles and Metrics
ParlezUml (http://www.parlezuml.com), 2006.

et le faible couplage (minimiser les dépendances entre modules et
encapsuler les détails non nécessaires à leur utilisation).

Encore une fois, je ne cherche pas à caractériser un langage de
programmation OO mais l'approche OO (ceci est moins difficile).
Je ne tiens pas à rentrer dans la querelle des langages OO ou pas OO
(qui est sans fin et n'apporte rien)


C'est bien ce que je dis depuis le debut...

Ce qui _pourrait_ caracteriser un language OO, c'est subtyping +
polymorphisme (d'inclusion). Ces deux concepts sont les seuls vraiment
present dans tous les languages OO et absent dans les non OO.


Je ne parlais pas de ce qui caractérise un langage objet mais des
concepts à mettre en oeuvre pour qu'on puisse parler de véritable
approche objet (ce n'est pas du tout la même chose).

Le subtyping existe dans ADA 83 qui n'est pas objet.


Il existe aussi en C (explicit) qui n'est pas objet. C'est pour ca que
ma phrase avait "subtyping + ..."

Il y a en fait 4 sortes de polymorphismes :
- Le polymorphisme ad'hoc : la surcharge et la coercion (conversion de
type)
- Le polymorphisme universel qui se subdivise en polymorphisme
paramétrique (comme dans ML, par exemple) et en polymorphisme d'hérita ge
(qui est effectivement appelé, quelques fois, polymorphisme d'inclusion)

Cf lucacardelli.name/Papers/OnUnderstanding.A4.pdf (le fameux article de
Cardelli et Wegner : "On Understanding Types, Data Abstraction, and
Polymorphism" qui est ce que je connais de mieux sur le sujet)


Je connais. Et d'ailleurs il fait parti des classifications avec
lesquelles je ne suis pas tout a fait d'accord. En parti parce qu'il
melange polymorphisme de type (que j'appelle directe) et polymorphism
de fonction (indirecte=type des arguments) ce qui fait que cette
decomposition n'est pas orthogonale. Par exemple la surchage
(overload) est indirecte mais aussi la redefinition (override), le
parametrique (au sens C++ ou Haskell) est en revanche directe
(polymorphisme de type). Ma decomposition (qui a aussi 4
polymorphismes) est d'avantage orthogonale et plus abstraite. Mais
elle est aussi plus simple a comprendre (d'apres les personnes qui la
rencontre) parce que non formatee pour certains langages.

Par exemple, quel est la nature du (des) polymorphisme(s) dans

template <typename T1, typename T2>
void func(T1& arg1, T2& arg2)
{
...
}

d'apres Cardelli, c'est du parametrique alors que c'est aussi (!) de
la surchage et dans certain languages ca pourrait etre aussi de la
redefinition (via l'heritage, si C++ supportait les multi-methodes
templates par ex, cf TR N2216). Bref, c'est tout a la fois selon sa
decomposition parce qu'elle n'est pas orthogonale.

Ou encore, quelle est la difference entre

struct B {
void func();
};

struct D : B {};

et

struct B {
virtual void func();
};
struct D : B {};

d'apres Cardelli?? D'ou mon attachement a separer subtyping de
polymorphisme (que je ne nomme plus d'inclusion, mais plutot lie a ses
specialisations)

Voici la mienne (so simple ;-) ):

Parametric Type
Type with definitions parametrized by types

Polymorphic Type
Type bound to several specializations

Parametric Function
Function with definitions parametrized by arguments type

Polymorphic Function
Function bound to several specializations (by arguments type)

Evidement, sorti du contexte, ca parait _trop_ simple et abstrait. Ces
definitions sont precedees d'autres concepts associes aux types et aux
fonctions (separement). Elles sont intentionnellement decouplees de
leur utilisation (syntax) et de leur implementation. Les 's' dans les
definitions ont tous une importance (en rouge+souligne sur mon
transparent). L'avantage, c'est que les multi-methodes rentrent dans
cette decomposition (dernier cas de Type + dernier cas de Function).

Pour bien faire, il faudrait encore decomposer Parametric parce que la
parametrisation en Java et en C++ n'ont rien a voir, mais chez moi
comme chez Cardelli, c'est le meme polymorphisme (et ca me gene). Mais
comme COS ne supporte pas la parametrisation, c'est pas primordial
dans cette presentation.

Après, il faut faire de nombreuses études de cas pour montrer commen t,
EFFECTIVEMENT, ces 4 concepts doivent être mis en oeuvre ENSEMBLE dans
une réelle approche objet et comment ils contribuent les uns aux autre s
à cette approche.


J'ai fait ca pas plus tard que la semaine derniere a des physiciens
qui
ne connaissait rien d'autre que Fortran 77 (qui sevit encore ici, he
oui...) et un peu C. Ca m'a pris 6-7 heures, dont la moitie sur
l'impact
des concepts des languages de programmations sur le design de
software.
En revanche mon approche n'est pas dans les livres (et donc discutable
a
souhait, en particulier ma classification des concepts). Neanmoins,
tout
le monde a compris en 1h a 2h (pour la partie OO).


Oui mais quelle est votre approche ?


Enoncer des concepts simples et orthogonaux mais tres abstraits.
Ensuite il est aise de re-classer les taxonomies existantes en disant
ce polymorphisme de Cardelli correspond a la combinaison de celui-ci
+celui-la.

Vous n'en dites rien alors que j'ai détaillé la mienne.
Ce qui me gêne c'est que vous vous situez toujours par rapport aux
langages de programmation OO alors que ce n'est pas mon cas.


Parce que les techniques/approches OO, c'est trop vague. Par exemple,
j'utilise en C des approches OO que tres peut de language OO me
fournissent (meta-classe, multi-methodes, delegation generique,
contrats). Pour plus de lecture, voir

http://cern.ch/laurent.deniau/html/cos-oopsla07-draft.pdf

(bien que obsolete puisque COS a ete ameliore sur bien des points
depuis et l'est encore)

Pédagogiquement parlant, je ne passe pas plus de temps sur la notion d e
hiérarchie (et pas seulement l'héritage, c'est ça la clé) que su r les
autres concepts.


C'est dommage, parce que dans les languages a typage statique, la
notion
de hierarchie est intrinsequement liee a celle de couplage que l'on
cherche a eviter. Le jeux consiste donc a montrer comment reorganiser
les hierarchies pour diminuer le couplage sans rendre Liskov furieux.


Je vous reprends : "sans rendre Liskov furieuSE". j'ai assisté à un


Non, je ne parle pas de Barbara elle-meme qui n'a rien a voir avec
cette discussion en tant qu'auteur du principe, mais du principe lui-
meme "Liskov Substitution Principle" qui est inapplicable en pratique
(on commence seulement a s'en rendre compte ;-) ).

workshop de Barbara Liskov (auteur du langage CLU) en 85 à Berlin.
C'était extra.
Vous faites allusion au fameux principe de substitution ?


oui d'ou le masculin.

C++ utilise les templates presque partout pour resoudre ce probleme,
mais les autres languages n'ont guere le choix que d'utiliser des
interfaces (au sens Java du terme).


Mais les interfaces "à la Java" c'est très bien non ?


Oui mais c'est dynamique, les templates sont statiques (donc plus
compliques). Ce qui veut dire pour les interfaces check au runtime et
faible couplage sont au rendez-vous (comme dans les languages
dynamiques). Ce n'est pas pour rien que le JDK a ete completement
reorganise sur ce principe.

J'ai vu une application de 450 mille lignes de Java qui utilisait très
proprement les interfaces. Cette application était nickel.


Mois aussi ;-) Et j'ai vu la meme chose en C qui n'etait autre que
l'implementation de la JVM elle-meme par Sun ;-)

Mais la aussi, j'explique dans mon cours que les interfaces (au sens
Java) sont des artefacts necessaires pour rendre plus dynamique les
langages statiquement types. Dans les langages dynamiques (duck
typing), l'heritage a une autre signification (pas de LSP) beaucoup
plus pragmatique comme la reutilisation de code ou la classification
des types. Du coup les hierarchies de classes sont quasi inexistantes.

Fin 2007-debut 2008, nous avons eu un etudiant qui a developper en
Java tout un systeme de gestion de plug-in externe (module C, matlab
etc...) pour nos applications. C'etait tres joli, bien fait avec plein
d'interface et base en parti sur les capacites d'introspection de
Java. Comme il est question d'utiliser COS d'ici peu (cf ref ci-
dessus) qui est dynamiquement type et supporte les multi-methodes,
tout risque de partir a la poubelle parce que c'est devenu inutile.

Enfin, je ne suis pas d'accord que les "vraies" bases s'expliquent en 5
minutes car moi j'y passe 3 (oui trois) jours sur les 4 concepts.


Je suis d'accord, 3-4 jours c'est ce qu'il faut pour un etudiant moyen
n'ayant aucun background sur le sujet. Ne serait-ce que pour lui
laisser
le temps de se faire a l'idee (comme pour les pointeurs). Le probleme,
c'est qu'il faut encore 1-2 ans pour savoir le mettre a profit dans
des
gros projets (design).


Hélas oui, mais il n'y a pas de mystère...


Python, OO, concepts... Rarement vu un OT pareil sur f.c.l.c

a+, ld.



Avatar
espie
In article ,
Laurent Deniau wrote:
C'est ce que j'ai cru pendant 15 ans. Aujourd'hui, base sur mon
experience, je pense que les multi-methodes sont plus simple a
enseigner et a apprehender que le single dispatch pour de multiples
raisons (qu'il serait long a expliquer ici mais directement lier au
probleme de design et de ce qu'il faut faire et de ce qu'il ne faut
pas faire).



Est-ce que tu pourrais detailler un peu ? En particulier donner des
exemples simples ou les multi-methodes sont une nettement meilleure
solution que des techniques plus classiques...

Avatar
Steph
Euh, il n'y a pas besoin d'un cas aussi extrême.
Perso, un script très court exploité sur deux machines, donc deux éditeurs
de texte différents, dont les paramètres par défaut pour la génération
correspondant à la touche TAB du clavier étaient différents (HT d'un côté et
série d'espace de l'autre).
Résultat, au premier coup de correction à chaud pour « réparer » une c***ie
au milieu d'une focntion sur « l'autre » machine, crac tu casses le script
(en fait, il ne charge même pas, l'interpréteur détecte le souci, preuve
selon moi que je ne suis pas le premier à qui cela arrive ;-) ).


D'un autre côté dans un process sérieux et normal ca n'arrive pas.
Les programmes sont livrés pour tests. Si les tests passent ils sont
installés en production. C'est tout.
S'il y a modif on reprend le process.


Depuis, j'ai sur les *deux* machines reconfigurer les éditeurs pour
visualiser les espaces et les tabulations « dures ».
Cela doit s'appeler l'expérience, non ?


Antoine



Avatar
Laurent Deniau
Marc Espie wrote:
In article ,
Laurent Deniau wrote:
C'est ce que j'ai cru pendant 15 ans. Aujourd'hui, base sur mon
experience, je pense que les multi-methodes sont plus simple a
enseigner et a apprehender que le single dispatch pour de multiples
raisons (qu'il serait long a expliquer ici mais directement lier au
probleme de design et de ce qu'il faut faire et de ce qu'il ne faut
pas faire).



Est-ce que tu pourrais detailler un peu ? En particulier donner des
exemples simples ou les multi-methodes sont une nettement meilleure
solution que des techniques plus classiques...


Voici un exemple simple tire du cours sur COS (que j'espere
comprehensible tel quel, mais normalement c'est apres 2h de cours) et
ou assert remplace les contrats pour simplifier. Dans ce code _n et
selfn (n=1..3) representent la meme chose, mais pas avec le meme type
(C oblige...). OBJ est un ADT jamais defini nul part (encapsulation
totale) dont les membres ne peuvent etre accedes que dans ses
(multi-)methodes ou il trouve ses specialisations. Pour le reste, COS
est une bibliotheque C, donc ce n'est que du C ci-dessous.

Le code ci-apres est ni simple a ecrire, ni simple a etendre ou
modifier en C++, Java, C#, ou il faudra utiliser des visitor patterns
un peu partout soit environ 200 a 500 lignes de codes pour faire la
meme chose et de maniere tres peu extensible sans parler des
performances (je mets a part les templates qui peuvent remplir en
_apparence_ la meme tache, mais avec un resultat tres different). J'ai
pris le cas de Matrix parce que le cours est dans le cadre de
modelisation par element finis, mais les multi-methodes sont tout
aussi utiles pour les stream, les strings, les conteneurs en general
et bien d'autre cas. En fait presque tout si je considere les
utilisations dans COS, 70% des methodes sont des multimethodes. Une
fois que l'on a pris l'habitude, c'est tres tres difficile de s'en
passer tellement ca simplifie la vie, un peu comme les templates en C+
+. Les ref [3] et [9] dans le papier sur COS sont entre autre sur
l'influence des fonctions generiques sur le design. Autre lecture
interessante, le C++ TR N2216 sur une proposition des multi-methodes/
open-methodes en C++, mais sans m'etendre, cela ne resout que
partiellement le probleme par rapport au design lui-meme.

defclass(RowMatrix, Matrix)
size_t nrow, ncol;
double val[];
endclass

defmethod(OBJ, gputAt, RowMatrix, Double, Index2)
size_t row = self3->_1; // first index -> row
size_t col = self3->_2; // second index -> column

assert( row < self->nrow && col < self->ncol );

self->val[row * self->ncol + col] = self2->val;

retmethod(_1); // return the matrix
endmethod

defmethod(OBJ, gputAt, RowMatrix, Double, Slice2)
size_t nrow = self3->size[0];
size_t ncol = self3->size[1];

assert( slice2_index(self3,nrow,ncol) < self->nrow * self->ncol );

for (size_t i = 0; i < nrow; i++)
for (size_t j = 0; j < ncol; j++)
self->val[ slide2_index(self3,i,j) ] = self2->val;

retmethod(_1); // return the matrix
endmethod

-----
avec pour information:

defgeneric(OBJ, gputAt, to, what, at);

gputAt est une fonction generique avec 3 arguments: to, what, at, sont
des types "ouverts", c'est a dire non definis ici mais qui le seront
dans les methodes qui le specialiseront. Ils font donc parti du
dispatch comme l'est this en C++ ou en Java. Par exemple

defgeneric(OBJ, gputAtIdx, to, what, (size_t)idx);

utilise un type "ferme" pour idx, qui ne participe pas au dispatch et
ne peut etre specialise.

defclass(Double, Floating)
double val;
endclass

defclass(Index2, Index)
size_t _1, _2;
endclass

defclass(Slice2, Slice)
size_t start;
size_t size [2];
size_t stride[2];
endclass

static inline size_t
slice2_index(struct Slice2* s, size_t i, size_t j) {
return s->start + i * s->stride[0] + j * s->stride[1];
}

a+, ld.


Avatar
Bruno Desthuilliers
Euh, il n'y a pas besoin d'un cas aussi extrême.
Perso, un script très court exploité sur deux machines, donc deux
éditeurs
de texte différents, dont les paramètres par défaut pour la génération
correspondant à la touche TAB du clavier étaient différents (HT d'un
côté et
série d'espace de l'autre).
Résultat, au premier coup de correction à chaud pour « réparer » une
c***ie
au milieu d'une focntion sur « l'autre » machine, crac tu casses le
script
(en fait, il ne charge même pas, l'interpréteur détecte le souci, preuve
selon moi que je ne suis pas le premier à qui cela arrive ;-) ).


D'un autre côté dans un process sérieux et normal ca n'arrive pas.
Les programmes sont livrés pour tests. Si les tests passent ils sont
installés en production. C'est tout.
S'il y a modif on reprend le process.


En théorie, la pratique est conforme à la théorie. En pratique... Bin en
pratique, les interventions d'urgence sur du code en prod, ça arrive.
Ok, c'est Mal(tm), ok, c'est à éviter par tous les moyens possibles,
mais bon, faut être pragmatique : ça arrive.


Avatar
Jean-Marc Bourguet
(Marc Espie) writes:

In article ,
Laurent Deniau wrote:
C'est ce que j'ai cru pendant 15 ans. Aujourd'hui, base sur mon
experience, je pense que les multi-methodes sont plus simple a
enseigner et a apprehender que le single dispatch pour de multiples
raisons (qu'il serait long a expliquer ici mais directement lier au
probleme de design et de ce qu'il faut faire et de ce qu'il ne faut
pas faire).



Est-ce que tu pourrais detailler un peu ? En particulier donner des
exemples simples ou les multi-methodes sont une nettement meilleure
solution que des techniques plus classiques...


Dans la plupart des cas, ce que veulent ceux qui pretendent utiliser le
pattern visiteur, c'est une implementation des multimethodes. En fait, il
y a pas mal de gens qui ne voient pas la difference entre les deux.

En plus, les multimethodes sont conceptuellement plus simples: c'est de la
surcharge resolue dynamiquement plutot que statiquement. Introduire une
surcharge resolue de maniere mixte (dynamiquement pour un parametre --
clairement identifie avec une syntaxe a la C++, moins clairement pour Ada
mais au moins la syntaxe d'Ada est directement extensible au cas des
multimethodes --, statiquement pour les autres) me semble une complication.

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Steph
En théorie, la pratique est conforme à la théorie. En pratique...
Bin en

pratique, les interventions d'urgence sur du code en prod, ça arrive.
Ok, c'est Mal(tm), ok, c'est à éviter par tous les moyens possibles,
mais bon, faut être pragmatique : ça arrive.


Bah non j'ai été sur pas mal de gros projet, des modifs dans du code en
prod non je n'ai jamais vu.
Des patchs fait rapidement sur une machine de dev oui. Mais dans ce cas
à priori pas de soucis avec l'éditeur de text ...
Et puis c'est testé tout de même un minimum. Je ne connais personne
d'assez inconscient pour ne pas faire de test sur un prog avant de le
livrer en prod.