From: martin@mwtech.UUCP (Martin Weitzel)
Newsgroups: de.comp.lang.c++
Subject: Re: Lippmann - was ist das?
Date: 11 Dec 92 16:55:17 GMT
Reply-To: martin@mwtech.UUCP (Martin Weitzel)
Organization: MIKROS Systemware, Darmstadt/W-Germany

In article <1g5sp6INN9d9@smurf.smurf.sub.org> urlichs@smurf.sub.org (Matthias Urlichs) writes:
>In de.comp.lang.c++, article <1359@mwtech.UUCP>,
>  martin@mwtech.UUCP (Martin Weitzel) writes:
>> In article <vaillant.723748577@hathi> vaillant@hathi.informatik.rwth-aachen.de (Stefan Vaillant) writes:
>> >martin@mwtech.UUCP (Martin Weitzel) writes:

[... Martin Weitzel (also ich) vertritt hier die Meinung, dass die Kritik
     an der *Sprache* C++ eher Kritik an den *gaengigen Implementationen*
     ist
...]
>Der Compiler erzeugt Objectcode, i.e. einen
>Haufen Prozeduren mit Funktionsaufrufen drin. Danach kommt ein Linker, der im
>Idealfall intelligent genug sein muss, die Objektstruktur deines Programms zu

Wie kommt denn dann ein Eiffel/NYFOOPL-Compiler mit so einem "dummen" Linker
zurecht?  Oder erfordern die ihren eigenen Linker?  Wenn ja, ist das IMHO ein
unfairer Vergleich (ungefaehr so wie zu sagen, dass ein Auto, bei dem ein
Air-Bag im Preis von 50 TDM gleich drin ist, sicherer sei als ein Auto fuer
35 TDM, bei dem ein Air-Bag 2000 DM Aufpreis kostet ...).

[...]
>Die Spielzeugloesung, zunaechst das C++ nach C zu uebersetzen und dann von
>einem Linker binden zu lassen, der (unter Unix) aufgrund mangelhaftem
[...]
>Und vom Debuggen reden wir lieber gar nicht erst.

Da sehe ich mich eigentlich nur bestaetigt (ich nehme an, das wolltest Du
auch).  Um es anders auszudruecken:  IMHO liegen Leute, die wegen der
Moeglichkeit der falschen Verwendung von "virtual" und/oder "inline"
das *Design* von C++ kritisieren, ebenso falsch wie Leute, die das Design
von C (ohne ++) kritisieren, weil es da die "register"-Vereinbarung gibt
und kein Mensch doch wissen koenne, welche Variablen man denn am besten
in Register lege (u.a. weil man in einem portablen Programm garnicht weiss,
wieviele Register es gibt), und dass es besser sei, wenn der Compiler das
selbst entscheiden wuerde.  (Fuer die uninformierten Leser:  Fast alle
*heutigen* C-Compiler machen genau diese Optimierungen von sich aus und
ignorieren den Zusatz "register" bei der Vereinbarung einfach.)

[...]
>Die Hilfestellungen sind uninteressant. Du sagst dem Compiler, ob du sehr
>viel Platz oder sehr wenig Zeit hast, und ueberlaesst das Inlining und den
>ganzen anderen Kram den hoffentlich in ausreichendem Umfang eingebauten
[...]

Eben, "Quality of Implementation" ... Ich halte es fuer gut, dass gaengige
Praxis die typischen Optimierungen und Warnungen der modernen C (ohne ++)
-Compiler gepraegt hat, und nicht das Spach-Design.  (Im letzteren Fall
waere C mit grosser Wahrscheinlichkeit genauso eine Totgeburt geworden wie
ADA, das NOCH NICHT EINMAL als vom DoD gefoerderte Sprache was geworden ist).

Eine *Qualitaetsimplementation* von C++ kann nach heuristischen Methoden
auch durchaus vor typischen Programmierfehlern warnen.  Ich finde es deshalb
nicht noetig, allen moeglichen Pipapo in das Sprach-Design reinzunehmen.

Bei den naechsten drei Zitaten beachte man das Quoting:

[Stefan Vaillant schreibt]
>> >Auf Pointer kann man wohl in keiner OO Sprache verzichten

[Martin Weitzel (Ich) antwortet]
>> Was zu beweisen waere.
[...]

[Matthias Urlichs kommentiert]
>Auf Pointer kann man sehr wohl verzichten. Man schreibt einfach das Objekt
>selber hin, nicht einen Pointer auf dieses, und ueberlaesst es dem
>eingebauten Speicherallokator/Muellschlucker/Referenzzaehler (vorsicht
>zyklische Strukturen...), den Kram wieder freizugeben.

Wie ich schon sagte:  Wenn ich C++ auf einem relativ hohen Level (nahe dem
"problem space") programmiere, dann haben da Pointer IMHO nichts zu suchen
(ebensowenige "rohe" Arrays).  Es ist ungefaehr so wie mit den Casts in C:
Manchmal braucht man sie halt, aber ein C-Programm, das in jeder dritten
Zeile einen Cast hat, ist mir suspekt.  Was schade ist (aber in meinen
Augen eher ein Schulungs- als ein C++-Problem), ist, dass man nicht einfach
die Verwendung von Pointern und Arrays in High-Level Modulen VERBIETEN kann.
Aber ich sehe keinen Grund, dass ein C++-Compiler nicht eine Warnung

	file "xyz.c": line 123
	you defined or used a pointer/array here
	
ausgeben koennte, so wie ein C-Compiler z.B. eine "dangerous cast"-Warnung
ausgeben kann.

Es ist EBENFALLS ein Schulungs- und/oder ein "Quality of Implementation"-
Problem, wenn eine "Warnung" in manchen Faellen zu wenig oder zu viel ist.
Unter der Voraussetzung, dass es mir eine Compiler-Implementation erlaubt,
mit zumutbarem Aufwand meine Programme so zu gestalten, dass ich ALLE
Warnungen wegbekomme, finde ich die Massgabe richtig, dass innerhalb
eines SW-Entwicklungsprojektes alle Kompilierungen ohne jegliche Warnungen
ablaufen muessen.  Eine ordentliche Qualitaetssicherung sollte m.E. auf
diesem Punkt nicht verzichten.  (Der einzige Grund fuer einen Verzicht
waere fuer mich gegeben, wenn der Aufwand, die Warung zu umgehen, unzumutbar
wird.  Eine Qualitaets-Implementation sollte daher fuer alle Warnungen eine
Moeglichkeit vorsehen, dem Compiler zu sagen, "das geht schon OK so", z.B.
#pragma I_AM_SURE_THAT_I_NEED_THE_FOLLOWING_CAST_AND_WANT_NO_WARNING).

[...]
>Das Problem ist, dass ich mich mit vielem Kleinkram beschaeftigen muss
>(zB bei der Zuweisung Referenzen mitzuschleppen, damit keine blinden Zeiger
>entstehen. zB persistente Objekte neu erfinden. Die Liste ist ziemlich lang),
>der mich von der Arbeit abhaelt und in dem sich dann die meisten Bugs finden.

Wieder eine C-Analogie: Hat es C geschadet, dass die *Sprache* weder ISAM-
Dateien noch hardwareunabhaengigen Bildschirm- und Drucker-I/O enthaelt?
Natuerlich, wenn jemand daherkommt und ein COBOL-Programm mit moeglichst
wenig Aufwand in C umsetzen will, dann braucht er erstmal eine Bibliothek
fuer beides, und die muss er sich zur Not selber schreiben (und zusaetzlich
zu dem eigentlich zu portierenden Programm debuggen - insofern passt das
gut zu Deinem Bild, dass man von der "eigentlichen" Arbeit  abgehalten wird).

Nun koennte er aber auch auf C-ISAM und Curses zugreifen, vielleicht mit
ein paar Hilfsfunktionen, die die gewuenschte Schnittstelle realisieren,
und die sicher keinen wesentlichen Debugging-Aufwand verursachen.  Ich
sehe da einen Vorteil in der groesseren Variationsbandbreite:  Dadurch
dass C bestimmte Mechanismen NICHT im Sprachkern enthaelt, dafuer aber
den allgemeinen Mechanismus des Bibliothekskonzeptes (mit getrennter
Kompilierung der Module) ist die Sprache letztendlich staerker als mit
jedem fest integrierten Mechanismus, der je nach Problem auch Overkill
oder zu armselig sein koennte.

So aehnlich ist das auch mit dem "neu Erfinden" in C++ und ich denke, gerade
die Tatsache DASS sich da noch keine Standard-Klassenbibliothek heraus-
gebildet hat, zeigt, wie UNTERSCHIEDLICH hier der reale Bedarf ist.  Und
genau das bestaetigt die Richtigkeit des Konzepts, derartige Mechanismen
aus dem Sprach-*Design* herauszulassen.  (Ich finde es aber auch richtig,
dass man die Exceptions jetzt integriert, weil hier so viel Zusammenspiel
mit dem Compiler erforderlich ist, dass dieser auf zahlreiche moegliche
Optimierungen verzichten muesste, wenn man die Sache rein extern ueber
Bibliotheken abwickeln wollte.)

Wenn es eine andere Sprache als C++ gibt, in der alles erforderliche genau
im richtigen Mass enthalten ist (nicht so simpel, dass man in ernsthaften
Programmen eben doch alles wieder selbst machen muss, aber auch nicht mit
einem Aufwand, der ein simples "hello world"-Programm auf 400 KB aufblaesst
oder jede reale Anwendung im Schneckentempo dahinkriechen laesst): Gut!
Wenn das allgemeine Interesse an dieser Sprache auch noch so gross ist,
dass sie fuer das gewuenschte Zielsystem (= Kombination von HW + OS)
verfuegbar ist: Noch besser!!

Bei Leuten, die "ihre" OOP-Sprache fuer "ihr" Zielsystem noch suchen, gilt
wenigstens eines von beidem nicht.  Wenn dann jemand zu C++ greift (weil
es fuer das Zielsystem verfuegbar ist), habe ich zwar Verstaendnis dafuer,
das er das, was ihm an C++ fehlt, als "Mangel" empfindet, dies aber dem
Sprach-Design als Fehler anzulasten, ist eine sehr egozentrische Sicht
der Dinge.  (Was "ich" brauche, das hat da zu sein, was "ich" nicht
brauche, dass sollte man rauswerfen.)

[...]
>Die Probleme liegen in einem Design der Sprache, das
>mich zwingt, fuer viele real vorkommende Probleme jedesmal spezielle
>Loesungen zu schreiben, anstatt den Kram von der Implementierung erledigen zu
>lassen oder zu modularisieren.

Das *Design* der Sprache verbietet es doch keiner Implementierung, Dinge
fuer Dich zu erledigen.  Ist es einem C++-Compiler verboten zu sagen
	
	file "foo.c": line 4711
	inline ignored as you specified the command line option -small;
	use "#pragma I_DEFINATELY_WANT_THIS_TO_BE_INLINE" to override.

Oder ist es einem Linker verboten, den vtable-Zeiger wegzuwerfen, wenn er
(evtl. im Zusammenspiel mit dem Compiler) entscheiden kann, dass kein
"late binding" erforderlich ist?

Ich stimme aber mit Dir ueberein, dass es kritisch wird, wenn das Sprach-
Design die Modularisierung bestimmter Dinge *verbietet* - ich nehme an, Dein
naechstes Beispiel soll in diese Richtung gehen.

>Beispiel: Das Objekt enthaelt einen Zeiger auf ein anderes solches.
>Ein Compiler kann das feststellen und beim Kopieren einen Referenzzaehler
>erhoehen bzw. eine Garbage Collection durchfuehren, wenn der Speicher knapp
>wird.

Hmm, ich denke da gerade an die 30t-Presse die eben durch die Wand der
Werkshalle gerauscht ist, und der Programmierer kratzt sich nachdenklich
am Kopf:  Also eigentlich reagiert das Programm ja binnen 20 msec auf den
Endeschalter, aber so in einem von tausend Faellen koennte sein, dass da
mal die garbage collection dazwischenkommt ...)

Gut, das Echtzeit-Beispiel ist vielleicht nicht ganz fair, aber ich will
damit etwas allgemeineres sagen: Was aus dem Blickwinkel des einen bequem
ist, kann aus dem Blickwinkel des anderen problematisch sein und sich fuer
einen dritten gar verbieten.

>In C++ muss ich mich fuer jede einzelne solche Referenz extra
>anstrengen, und zwar an mindestens drei verschiedenen Stellen (Zuweisung/
>/Initialisierung/Freigabe eines Objekts). Da Zeiger auf Objekte ein
>wichtiger Bestandteil der Sprache sind, deklariere ich das als Designfehler;
>umso mehr, als eines der zentralen Paradigmen der objektorientierten
>Programmierung, naemlich solche Abhaengigkeiten zu lokalisieren und
>moeglichst in einem Modul zu verstecken, an dieser Stelle nicht erreicht
>werden _kann_.

Gut, das *Design* von C++ enthaelt Zeiger und die koennen unter gewissen
Umstaenden problematisch werden (hatten wir schon). Ich sage, dass Zeiger
ein Low-Level-Mechanismus sind, der aus Effizienz-Gruenden fuer diejenigen
Situationen vorhanden ist, bei denen entsprechende High-Level-Mechanismen
zu aufwendig waeren.  Ich sehe aber keine unueberwindlichen Schwierigkeiten
darin, Mechanismen zu modularisieren, die auf einer hoeheren Ebene die
Verwendung von Zeigern ueberfluessig machen.

Vermutlich wird sich die Modularisierung nicht auf eine Weise machen lassen,
dass alles, angefangen von der HW-nahen Programmiererung einer Maschinen-
steuerung bis zum GUI einer OO-Datenbank damit zufriedengestellt ist, aber
die Staerke von C++ ist gerade dieser Freiheitsgrad, der sich aus dem ergibt,
was die Sprache NICHT beinhaltet.  Aus diesem Grund hat sich IMHO bislang
auch keine Klassenbibliothek allgemein und weit verbreitet, weil der Bedarf
(einfache Anwendung, geringer Maschinencode, Performance, Integrierbarkeit
in vorhandene Software, Erweiterbarkeit, ...) eben viel zu verschieden ist.

Und genau deshalb sind Sprachen, die bereits im Design entsprechende
Mechanismen enthalten, auf eine Breite Anwendungsbasis bezogen gegenueber
C++ im Nachteil, denn sie koennen zwangslaeufig nur einen Teil der
Wuensche zufriedenstellen.  Etwas ueberspitzt gesagt:  Wuerde C++ z.B. in
einer Klassenbibliothek eine Standardklasse fuer Strings bereitstellen -
was ich mir schon oft gewuenscht habe, damit nicht JEDER wieder meint,
sein eigenes Sueppchen kochen zu muessen, haetten vielleicht 3/4 der
Anwender was daran zu bemaengeln ("ach ist das umstaendlich zu benutzen",
"warum gibt denn das ploetzlich soviel Maschinencode", "wenn ich die
garbage collection nicht unter Kontrolle kriege, macht das die Antwortzeit
kaputt, die ich fuer den worst case garantieren muss" ...)

Da ich aus den Artikeln, die ich sonst noch so von Dir gesehen habe, weiss,
dass Du Dich sehr fundiert aeusserst, wuerde mich mal eine Konkretisierung
der von Dir angesprochenen Problematik bezueglich mangelnder Modularisier-
barkeit interessieren  (vielleicht unter geaendertem Subject, denn mit
Lipmann hat das ja nun nix mehr zu tun).
-- 
Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83