Warum Muss Cee Wie Modula Aussehen
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern
Zitat von CeeIdioms (und das ist der Punkt):
- Für das Beispiel benötigte Definitionen in Headerfiles (Puristen wird das Folgende vielleicht nicht gefallen, aber mir leistet es gute Dienste):
| #define StrLen strlen
#define StrSize(s) (strlen(s)+1)
#define StrFindStr strstr
#define MemCpy memmove
#define MemCpyFast memcpy |
|
|
Welchen Vorteil bietet StrLen gegenüber strlen? Es muss zweimal die Umschalt-Taste gedrückt werden, also muss es ja wohl einen Nutzen haben, eine Funktion der Standardbibliothek umzubennen, besonders wenn dass ganze als "Redewendung" in C verkauft werden soll.
StrSize bietet etwas, das strlen() nicht bietet, aber wem klar ist, dass an einer Stelle StrSize anstelle von StrLen verwendtet werden müsste, dem ist vermutlich auch klar, dass an dieser Stelle 1 zum Rückgabewert von strlen() addiert werden muss. Trotzdem, ein gewisser Restnutzen bleibt hier.
StrFindStr erfordert gegenüber strstr sogar 7 zusätzliche Anschläge. Welchen Vorteil hat dieser Bezeichener gegenüber strstr?
Warum soll es ein CeeIdiom sein, einer Funktion der Standardbibliothek einen anderen, längeren Namen zu geben? Ist das nicht vielmehr genau das Gegenteil einer in Cee gebräuchlichen "Redewendung"? Ist "Es regnet Hunde und Katzen" oder "Über meinen toten Körper" eine gebräuchliche Redewendung im Deutschen?
Wenn es darum gehen soll, dass Zeichenkettenfunktionen aus der Standardbibliothek und selbstdefinierte Zeichenkettenfunktionen gleich aussehen: Ist das ein Ziel, dass es sich zu verfolgen lohnt? Sollte nicht vielmehr angestrebt werden, den Unterschied in der Herkunft zwischen Funktionen der Standardbibliothek und Funktionen einer eigenen Bibliothek klar zu machen? Versetzen wir uns in die Rolle einer Wartungsprogrammiererin, die die Sprache kennt, in der der zu wartende Code geschrieben ist: Wuerde sie sofort erwarten, dass sich hinter StrFindStr das unschuldige strstr verbirgt, oder würde sie nicht eher annehmen, dass diese Funktion etwas subtil anderes tut als strstr? -- KurtWatzka
- Hallo Kurt, also hier nur kurz, was ich mir zu der Sache denke... Also ich halte das ganze für eine reine "Stilfrage". Offenbar sagen eben demjenigen, der die oben von Dir zitierten #defines formuliert hat die "neuen" (eigenen) Bezeichner einfach "mehr zu". Dass das Programm für einen DRITTEN dadurch nicht gerade einfacher wartbar wird, scheint mir allerdings auch auf der Hand zu liegen... ;-)))
- Als möglichen VORTEIL für einen selbst (wenn man also diese Sachen für SICH SELBST einführt) sehe ich schon, dass vielleicht ein Bezeichner wie "StrLen" in komplexen Code einfach leichter zu lesen (erkennen) ist, als "strlen" - durch die abwechselnde Groß-Klein-Schreibung springt einem das Wort (der Bezeichner) sozusagen "ins Auge"... // Das muss aber natürlich keineswegs jeder so empfinden!
- Ähnlich sehe ich das bei Bezeichnern wie "StrSize" - hier kommt noch hinzu, dass hier ja wirklich auch noch eine neue BEDEUTUNG eingeführt wird - die Idee find ich OK.
- Auch der "Nutzen" (oder vielmehr Sinn) von "StrFindStr" leuchtet mir ein; wobei ICH hier aber z.B. "FindStrPattern" vorziehen würde... ;-)
- Man kann sich natürlich auch auf den Standpunkt stellen, dass es EVIL ist, Bibliotheksfunktionen einfach NUR umzubenennen! Besonders auf in Hinblick auch auf Wartbarkeit des Codes durch Dritte, hat dieser Standpunkt sicher auch was für sich.
- Was mich stört ist nicht, dass jemand solche #define-Direktiven für sich verwendet. Was mich stört ist, solche Direktiven als gängige Redewendungen in C anzubieten. DaNeben glaube ich nicht, dass Text besser lesBar wird, wenn GrossBuchStaben in Worte einGeMischt werden. Das ist aber wirklich eine StilFrage.
- Halt, halt, halt: Hier werden Wortbilder, die man schon von Kindesbeinen an lernt (und sich einprägt!) *willkürlich* verändert: dass d a s nicht gerade zur Erhöhung der Lesbarkeit beiträgt, ist klar. Ich hatte auch nicht von "Text" gesprochen, sondern von komplexem Code! (Allerdings meinte ich damit schön strukturierten und mit vielen Whitespaces versehenen Code - vgl. CodingStyle? - und nicht Bandwurmsätze... ;-)
- Wenn ich dieses Argument aufgreifen darf: Warum soll etwas einen neuen Namen erhalten, das bereits einen bekannten Namen hat? Ich habe die, vieleicht naive, Hoffnung, dass C-Programme ausserhalb von Lehrbüchern von Menschen gelesen werden, die die Programmiersprache C kennen. Wer die Sprache C kennt, der kennt die Funktionen der Standardbibliothek. Wer lgamma noch nicht kennt, hat entweder wenig mit Problemen zu tun, bei denen diese Funktion sinnvoll eingesetzt werden kann, oder wird diese Funktion ebenfalls kennen. --kw
- Zum Nutzen von FindStrPattern im Vergleich zu strstr würde mich interessieren: Warum nicht FindSubStringStartingWith? Bei FindStrPattern würde ich als naiver Wartungsprogrammierer erwarten, dass die Funktion einen regulären Ausdruck verarbeiten kann. --kw
- Es wird hier noch eine *semantische* Information mitgegeben, die bei strstr fehlt. "FindSubString" gefällt mir aber auch! :-) // Ist vielleicht sogar noch besser geeignet... - auf die Typ "Information" ist es mir nämlich hier nicht wirklich angekommen, sondern mehr auf die "Funktion" der Funktion... ;-)
- Diese Argumentation ist für selbstdefinierte Funktionen gültig. Dass diese einen Namen tragen sollen, der den Zweck der Funktion möglichst gut beschreibt, ist vermutlich unstrittig. Die Funktionen der Standardbibliothek sind, entgegen widriger Gerüchte, Teil der Sprache C für ein "hosted environment". Diese Funktionen umzubenennen verringert die Lesbarkeit und Wartbarkeit von C-Quelltexten für diejenigen, die die Sprache C kennen, und ob jemand, der die Sprache C nicht kennt von dem höheren Imformationsgehalt von StrLen im Vergleich zu strlen beim Lesen eines C-Programms wirklich profitieren kann möchte ich bezweifeln. --kw
Zusätzlich verringert dies Vorgehensweise auch die Wiederverwendbarkeit von Quelltexten (ist der Header mit den "schöneren" Namen den ich heute verwende auch der, mit dem diese Funktion erstellt wurde?),
wirkt also genau entgegen der damit verfolgten Ziele --kw
WarumMussCeeWieModulaAussehen? Antwort: es muss nicht.
Ich kenne Modula nicht einmal, Ähnlichkeiten sind also rein zufällig.
Zunächst: C läßt ein großes stilistisches Spektrum zu und zufälligerweise sind mit HelmutSchellong und mir zwei Extremisten anwesend. Er ist der Meister des knappen, trickreich performanten C, das aber für den Normalverbraucher "zu kompiziert" ist (Ich hoffe er postet einmal ein Extrembeispiel). Ich bin Verfechter der extremen Optimierung hin auf Wiederverwendung und Lesbarkeit. Wir haben aber - da wir uns nicht als Missionare fühlen - überhaupt kein Problem miteinander, im Gegenteil.
Die obigen Definitionen sind eigentlich nur aus Faulheit in CeeIdioms hineingerutscht. Ich wollte das String-Replace dort plazieren (so etwas wird ja häufig nachgefragt) und habe die erforderliche Infrastruktur mit übernommen.
Dass dabei eine zufällige Auswahl passiert ist, die an der Grenze des erträglichen ist, war mir bewusst (siehe Einleitungssatz).
Das Argument der Tipp-Anschläge lasse ich allerdings nicht gelten, sonst wäre SpracheAPL die einzig wahre Sprache. Und ähnlich wie bei OTBS erklären sich die kurzen, kryptischen Namen der C-Standardbibliothek nicht aus gezieltem Design sondern aus der damals üblichen 8-Zeichen-Bezeichner-Limitierung. Niemand, der das heute neu designen oder benennen würde, käme auf die alten Namen. Die Frage ist, wie lange man sich von der Vergangenheit belasten lässt.
Ob ein konsistentes System für die Namensgebung sinnvoll ist und wie weit man
es treiben möchte, um auch vorhandene Standardfunktionen zu "wrappen", zu korrigieren oder zu überformen, ist natürlich die Frage. Jeder Wiederverwendung scheitert im großen Maßstab, wenn die neugeschaffenen Funktionen in ihrer Semantik und Lesbarkeit nicht glasklar sind. Abstrahiert von C-Vorkenntnissen sagt "strstr" eben nichts, "StrFindStr" aber fast alles.
Vielleicht einige weitere "Anstößigkeiten":
| #define StrClear(s) *(s)='\0'
#define StrCmp strcmp
#define StrEqu(s,p) (!strcmp(s,p))
#define MemClear(p,size) memset(p,'\0',size)
int StrCmpMem(char *s,char *p,int len);
#define StrEquMem(s,p,size) (StrCmpMem(s,p,size)==0)
#define StrCat strcat
void StrCatChr(char *s,char c);
void StrCatMem(char *s,char *p,int size);
#define StrCpyFmt sprintf
void StrCatFmt(char *s,char *fmt,...); |
|
|
Das ist jetzt ganz bewusst auf die "borderline", auf die Grenze der Sinnhaftigkeit ganz am unteren Rand gezielt. Die Beispiele lassen sich beliebig in höhere Ebenen ausdehnen, wo die Standardfunktionen längst nicht mehr sichtbar sind, z.B. ein
| s=UrlRetStr("http://www.apa.at"); |
|
|
Ziel der von mir angebotenen Stils ist die unmittelbare Lesbarkeit und einfachste Verwendbarkeit.
- Meiner Meinung nach erhöhen sprechende Namen für selbstdefinierte Objekte und Funktionen die Lesbarkeit deutlich. Auch explizit gemachte Zusicherungen im Quelltext verbessern die Wiederverwendbarkeit von Funktionssammlungen.
- Es bleibt die Frage, ob von dem Leser, an den sich solcher Quelltext wenden soll, erwartet werden darf, dass ihm die Sprache bekannt ist, in der der Quelltext abgefasst ist. Deswegen ist es auch nicht unbedingt nützlich, Idiome und nützliche Schnippsel in einen Topf zu werfen. Bei Idiomen ist das Ziel, die übliche Redewendung für einen bestimmten Sachverhalt zu lernen. Bei nützlichen Schnippseln kann der Zweck ein anderer sein.
| #include <string.h>
void StrDelLen(char *string, size_t numChars)
{
size_t length = strlen(string);
if (numChars > length) {
numChars =length;
}
memmove(string, string + numChars, length - numChars + 1);
}
void StrInsStr(char *string, char const * toInsert)
{
size_t insertLength = strlen(toInsert);
memmove(string + insertLength, string, strlen(string) + 1);
memcpy(string, toInsert, insertLength);
}
void StrReplaceGlobal(char *string, char const * replace,
char const * replacement, int global)
{
size_t replaceLength = strlen(replace);
size_t replacementLength = strlen(replacement);
char *p = string;
do {
p = strstr(p, replace);
if (p) {
StrDelLen(p, replaceLength);
StrInsStr(p, replacement);
p += replacementLength;
if(!global) {
return;
}
}
} while(p);
} |
|
|
Ist dieser Code für jemanden, der C lernen will oder kennt, weniger geeignet als der Code mit den umdefinierten Funktionsnamen? Hier ist einigermassen klar, was aus der Standardbibliothek stammt und was selbstdefinierte Funktionen sind. Einige Funktionen der Standardbibliothek werden in einer Situation vorgestellt, in der sie üblicherweise verwendet werden.
Ob dieser Quelltext weniger lesbar ist als der ursprüngliche käme auf einen Versuch mit einem Einsteiger an.
- Variablen und Parameter tragen Namen, die einem Leser ihre Bedeutung klar machen sollten.
- Nicht qualifizierte Zeiger werden nur dort übergeben, wo diese erforderlich sind.
- Die Anzahl der zu ersetzenden Zeichen in StrDelLen sollte in der angegebenen Implementation besser nicht negativ sein. Warum soll sie in einem int übergeben werden? --kw
Tausche bitte meinen Code gegen deinen auf der Seite CeeIdioms aus. Ich bin zwar nicht von allen deinen Details überzeugt, aber in Summe ist es sicher für den Einsteiger besser. --hl
Nebenbei ergeben sich einige interessante (subjektive?) Beobachtungen:
- ObjektOrientiertesDenken und ObjektOrientierteProgrammierung sind in gewisser Weise widersprüchlich!
- Interessante Aussage. Wo liegen denn die Widersprüche?
- Viele Objekte mit denen Programmierer umgehen, sind keine formalen Objekte (Instanzen von Klassen) im Sinne der OOP.
- Welche Objekte mit denen Programmierer umgehen genügen dem nicht?
- Viele Features habe ihre einfachste Repräsentation nicht in Klassen und Objekten sondern in prozeduralen Funktionen.
- Einfach im Sinne von 'am schnellsten zu realisieren' vielleicht. Einfach im Sinne von 'einfach zu warten und zu erweitern' möchte ich stark bezweifeln.
- Es ist schwierig für mich, eine sprachunabhängige Terminologie zu finden. Wenn ich von "einfach" spreche, dann nur im Zusammenhang der Verwendung des API durch den Programmierer.
StartSeite | Neues | TestSeite | ForumSeite | Teilnehmer | Kategorien | Index | Hilfe | Einstellungen | Ändern
Text dieser Seite ändern (zuletzt geändert: 30. Januar 2003 22:29 (diff))