Sauberes Programmieren // Varibeln mit Prefix
-
Original erstellt von Daniel E.:
ZB? (Mehr Tippaufwand gilt nicht :))Basis klassen getue und new einsatzt (smart pointer) könnte man sich sparen
aber auf der anderen seite spart typenstrengeheit arbeit(debug) und laufzeit(IMHO)
-
Eine Basisklasse hat mit Typenprüfung ähnlich viel zu tun, wie Smart-Pointer: nichts. Wenigstens sind mir keine Smart-Pointer in Ada vorgekommen und 'Basis klassen getue' meine ich auch schon in Python gesehen zu haben.
-
Ich weiß, dass ich mit meiner Abneigung gegenüber typedefs ziehmlich allein dastehe. Das ändert aber nix dran, dass ich sie nur in äußersten Notfällen einsetze, wenn z.B. der Funktionspointertyp sonst gar so lang werden würde.
Klar, sie sind praktisch, wenn man den Typ ändern will, aber ehrlich gesagt is mir das bis jetzt noch nicht so häufig vorgekommen, dass man projektweit nen Typ umstellen muss. Mach mir eigentlich immer sehr viele Gedanken, was für nen Typ ich nehmen muss. Und kommt natürlich daher, dass ich nur unter einem Compiler für Windoof progge. Mir also keine wirklichen Sorgen machen muss zwecks Größe der Typen - klar is vielleicht ziehmlich kurzsichtig und schlampig aber selbst wenn wir vom C-Builder auf VC umsteigen würden, hätten wir wohl keine probs damit und ich kann auch de fakto davon ausgehen, dass ein int auf einem 32-Bit-System 32 bit hat (klärt mich auf, gibts nen Compiler, wo das nicht so is) und dass das Teil maximal größer wird, nich aber kleiner.Ja und deswegen möchte ich wissen, ob das Teil ein std::auto_ptr oder ein boost::smart_pointer is
Womit ich ja wissen müsste, wie diese Dinger intern aufgebaut sind. Das alles auf ein (vielleicht 3-zeichen-langen) Präfix zu reduzieren ist doch etwas waghalsig.Du arbeitest also mit den Dingern ohne zu wissen, wie sie intern aufgebaut sind? Sorry, aber mit smart-pointern KANN man nicht arbeiten, wenn man ihr kopierverhalten nicht kennt.
Wie isses, benutzt ihr p für alle Arten von Zeigern? Wenn ich ein p sehe und kein delete dazu, werd ich misstrauisch (wenn doch, übrigens auch). Klar in c++-Code verwendet man keine rohen Zeiger aber leider kriegt man nicht immer reinen C++-Code vorgesetzt.
Und was ist waghalsig daran? Ich weiß doch, dass ap ein std::auto_ptr is und xap is ne implementierunge eines referenzzählenden. In meinem Code ist das durchgängig so, und wer meinen Code liest, wirds auch recht schnell bemerken.Mich interesieren (wie schon öfters gesagt) die abstrakten Schnittstellen ('ich kann Addieren')
Mich interessiert nicht nur, dass ich addieren kann, sondern mich interessiert auch, was beim Addieren schief gehn kann. Ein std::string könnte Speicherprobs produzieren, ein int nen überlauf. Und wenn ich ne Hausnummer hab. Was bedeuted dann addieren? 23+a gibt 23a oder is ein Fehler. 23+10 gibt 2310 oder 33? Klar, steht in der Doku der Hausnummern-Klasse. Aber beides hat seine Berechtigung, also immer in der Doku nachgucken. Oder man siehts eben gleich am Typ (obwohl ich Euch natürlich Recht gebe, wenn man Hausnummern addieren will, macht man dafür ne Klasse. Dann könnte man auch den +-Op für beide Fälle überladen).
Gut, dann mach ich jetzt aus meinem strHausnummer ein z.
Ändert an der Programmsemantik nichts.Natürlich änderts nix an der Programmsemantik. Aber an der Lesbarkeit und damit auch an der Qualität des Codes. Ach so, hier steht ja irgendwo: "man hat nen Compiler". Wiederspricht sich aber irgendwie mit sonst angebrachten Argument, dass man über Variablen mit vielen Präfixen mit keinem mehr reden kann.
derived IST EIN base.
'typeid (base) == typeid (derived)'?Es ist in der Objektorientierung definiert, dass es sich um eine "IST EIN"-Beziehung handelt. Typeid hingegen ist eine eindeutige Identifizierung für einen Typ. Das is eigentlich ein klarer Unterschied.
Gleichheit ist insgesamt etwas komisch, nicht nur, was Computer anbetrifft ('das Gleiche' vs 'das Selbe').
Gleichheit ist schlicht und einfach kontextabhängig, nicht komisch. Und "das Gleiche" hat auch eindeutig ne andere Bedeutung als "das Selbe". Is nunmal so.
Und was der Mehraufwand für strenge Typisierung is, brauch ich wohl auch nich wirklich zu erklären: Es zwingt Dich, Dir gedanken zu machen, die Du Dir zwar auch ohne machen solltest, wo man aber leicht mal Leichtsinnsfehler begeht.
ausserdem sollen sich Klassen wie normale Typen verhalten, so hat mans mir zumindestens beigebracht. warum sollte ich nun trennen?
Die Regel "do it like the ints" is wie viele einfache Grundregeln schlichtweg viel zu pauschal. Klassen sollen sich nicht anders verhalten als normale Typen, da wo eine Unstimmigkeit entstehen kann (also z.B. operatoren). Aber ints haben schlichtweg keine Methoden und auch keinen derefenenzierungs-Op. Außerdem sind klassen spezialisierter als Basistypen. Gut, man könnte deswegen für jeden Basistypen ein typedef machen - je nach Zweck. Is aber imho aber unpraktisch und wenig sinnvoll, solange typedefs keine echten Typen sind.
[ Dieser Beitrag wurde am 07.03.2003 um 10:29 Uhr von kartoffelsack editiert. ]
[ Dieser Beitrag wurde am 07.03.2003 um 10:31 Uhr von kartoffelsack editiert. ]
-
Original erstellt von kartoffelsack:
Du arbeitest also mit den Dingern ohne zu wissen, wie sie intern aufgebaut sind? Sorry, aber mit smart-pointern KANN man nicht arbeiten, wenn man ihr kopierverhalten nicht kennt.Ein gewisser Grad an Unwissen ist natürlich dabei, sonst könnte ich die Abstraktionsschicht 'Smart-Pointer' in die Tonne treten, respektive den Quelltext direkt hinschreiben. Um die Kopiersemantik zu kennen, genügt es vollkommen, die Kopiersemantik zu kennen :).
Wie isses, benutzt ihr p für alle Arten von Zeigern?
Nein. Keine Präfixe.
Mich interessiert nicht nur, dass ich addieren kann, sondern mich interessiert auch, was beim Addieren schief gehn kann.
Fehlerbehandlung findet nicht im 'normalen' Quelltext statt, wenn sie nicht lokaler Art sind. Weder 'Out of Memory' noch ein Integerüberlauf sind lokale Probleme.
wenn ich ne Hausnummer hab. Was bedeuted dann addieren?
Depends. Ich möchte zB über eine Straße iterieren. Also hat 8a+1 die nächste Hausnummer zu ergeben.
Aber an der Lesbarkeit und damit auch an der Qualität des Codes.
Und wenn ich aus z dann 'street_number' mache, dann passiert was? Aha! Es könnte also für jemanden, der seine Programme in Thai abfasst sinnvoll sein, seine Variable 'z' zu nennen, wenn 'z' gerade mal Hausnummer bedeutet.
Ich finde übrigens 'z' nicht so schlecht zu lesen. Ich kann mir bloß nichts drunter vorstellen :).
Typeid hingegen ist eine eindeutige Identifizierung für einen Typ.
Warst es nicht Du, der den _genauen_ Typen wissen wollte? Immer?
Gleichheit ist schlicht und einfach kontextabhängig
Ja. Es verhält sich also nicht überall gleich und hat kein wirklich vorhersehbares Verhalten. Komisch :).
Und "das Gleiche" hat auch eindeutig ne andere Bedeutung als "das Selbe".
'Das Gleiche' hat schlichtweg überhaupt keine sinnvolle kontextfreie Bedeutung. Sind zwei grüne VW-Gölfe aus dem Jahre 1986 gleich?
[strenge Typisierung] Es zwingt Dich, Dir gedanken zu machen, die Du Dir zwar auch ohne machen solltest, wo man aber leicht mal Leichtsinnsfehler begeht.
Darf ich das so verstehen, dass man in schwächer getypten Sprachen mehr Leichtsinnsfehler wegen der Typen macht? Das glaube ich nicht. Ich kann mich wenigstens an keinen größeren Typenfehler in (deklarationsfreiem) Lisp erinneren.
-
<ot>
Original erstellt von Daniel E.:
Darf ich das so verstehen, dass man in schwächer getypten Sprachen mehr Leichtsinnsfehler wegen der Typen macht? Das glaube ich nicht. Ich kann mich wenigstens an keinen größeren Typenfehler in (deklarationsfreiem) Lisp erinneren.Ich weiß nicht ob du es so sagen wolltest, aber du behauptest implizit, dass Lisp schwach getypt ist. Lisp ist aber stark getypt.</ot>
-
Original erstellt von Daniel E.:
Eine Basisklasse hat mit Typenprüfung ähnlich viel zu tun, wie Smart-Pointer: nichts. Wenigstens sind mir keine Smart-Pointer in Ada vorgekommen und 'Basis klassen getue' meine ich auch schon in Python gesehen zu haben.ich war der meinung das vererbung und co. dazu da ist das stare typen system kontroliert zu umgehen
-
Um die Kopiersemantik zu kennen, genügt es vollkommen, die Kopiersemantik zu kennen .
Dann benutz ich das Präfix halt als Hinweis für die kopiersemantik. Da ich keine verschiedene smart-Pointer gleicher Kopiersemantik in einem Projekt verwende, entspricht sich das.
Wie isses, benutzt ihr p für alle Arten von Zeigern?
Nein. Keine Präfixe.*schluck* Mir wird schlecht, wenn ich bedenke, dass Essen.get() was anderes bedeuten könnte als Essen->get().
Und wenn ich aus z dann 'street_number' mache, dann passiert was? Aha! Es könnte also für jemanden, der seine Programme in Thai abfasst sinnvoll sein, seine Variable 'z' zu nennen, wenn 'z' gerade mal Hausnummer bedeutet.
Nachdem ich einmal in einem ganze Projekt alle Bezeichner auf Englisch übersetzen musste wegen ner neuen Kollegin, die kein Deutsch konnte, mach ichs immer auf Englich. Aber i.A. kann z natürlich sinnvoll sein, wenn man sich was drunter vorstellen kann. Und ich glaub auch nicht, dass Du diesen Punkt ernst meinst.
Warst es nicht Du, der den _genauen_ Typen wissen wollte? Immer?
Ich will den Typ so genau wissen, wie an dieser Stelle möglich.
Darf ich das so verstehen, dass man in schwächer getypten Sprachen mehr Leichtsinnsfehler wegen der Typen macht? Das glaube ich nicht. Ich kann mich wenigstens an keinen größeren Typenfehler in (deklarationsfreiem) Lisp erinneren.
Ich kenn Lisp nicht, aber ich denke, ich brauch Dir nicht zu erklären, was die Vorteile einer streng typisierten Sprache sind. Und unter schwach typisisert verstehe ich auch nicht deklarationsfrei sondern, dass der Compiler nicht verhindert, dass Du implizit schwachsinnige Casts machst.
[ Dieser Beitrag wurde am 07.03.2003 um 12:11 Uhr von kartoffelsack editiert. ]
-
Was heißt stark/schwach, statisch/dynamisch in Bezug auf Typisierung:
http://c2.com/cgi/wiki?TypingQuadrant http://www-lp.doc.ic.ac.uk/UserPages/staff/ft/alp/net/typing/strong.html
-
Original erstellt von Bashar:
Ich weiß nicht ob du es so sagen wolltest, aber du behauptest implizit, dass Lisp schwach getypt ist. Lisp ist aber stark getypt.Lisp hat in erster Linie mal ein dynamisches Typenkonzept, C++ hat ein statisches. Das macht Vergleiche etwas komplizierter.
Ich weiß nicht ob es Normen oder Standards für solche Begrifflichkeiten gibt, aber unter 'starker Typisierung' verstehe ich, dass mir Typenfehler (irgendwie definiert) abgefangen werden, und nichts Komisches passiert. De facto passiert sowas aber bei Common-Lisp nach einem '(declaim (optimize (safety 0) (speed 3)))' schon gerne mal.
Original erstellt von Dimah:
]qb]ich war der meinung das vererbung und co. dazu da ist das stare typen system kontroliert zu umgehen[/qb]Sollte das jetzt 'starre' oder 'starke' heißen?
Ich denke Vererbung ist nicht einfach nur ein grausiger Hack um Löcher in ein Typensystem zu stanzen.Original erstellt von kartoffelsack:
**Ich will den Typ so genau wissen, wie an dieser Stelle möglich.
**... wie an dieser Stelle _nötig_. Dann sind wir uns einig :).
-
Die Konzepte stark/schwach und statisch/dynamisch sind orthogonal.
Und nur weil Lisp es erlaubt, die Typprüfung auszuschalten, wird es noch nicht zu einer schwach getypten Sprache. Die Default-Einstellung ist safety 3, und das ändert man auch nicht einfach, solange die typenmäßige Korrektheit noch nicht klar ist.
-
wie an dieser Stelle _nötig_. Dann sind wir uns einig .
Ne, ne, auf mein MÖGLICH besteh ich
-
Original erstellt von kartoffelsack:
Ne, ne, auf mein MÖGLICH besteh ichdann musst du UN auch bei objekten verwenden.
und konsequenterweise auch bei methoden und funktionen.
-
Ich versteh langsam den Sinn dieser Diskussion nicht mehr. Die die es machen machens und die die es nicht machen machens nicht
. So einfach ist das. Wirklich überzeugen lässt sich in dem Punkt doch keiner...
-
Und dass das ändern länger dauert, weil man sich den Code durchgucken MUSS seh ich als Vorteil (man überlegt sich außerdem dann vielleicht vorher schon genauer, welcher Typ sinnvoll ist).
naja, du siehst es als Vorteil, der andere nicht, dass ist sehr subjektiv. Objektiv kann man aber sagen, dass es mehr Aufwand ist (egal wie positiv das Ergebniss seien könnte). Weitere Aufwands Steigerung entstehen dadurch, dass man sich auf eine Notation festlegen muss, die in dem gesammten Projekt eingehalten werden sollte und gerade bei so Abkürzungen passieren leicht Fehler.
Wenn ich ein p sehe und kein delete dazu, werd ich misstrauisch
benutzt du nur Pointer, die auf dynamischen Speicher zeigen?
Klar, steht in der Doku der Hausnummern-Klasse. Aber beides hat seine Berechtigung, also immer in der Doku nachgucken. Oder man siehts eben gleich am Typ
Hä? Wie soll man das am Typ erkennen? Vielleicht weiss ich durch deine Notation, dass CHnummer eine Instanz der Klasse CHausnummer ist, aber deswegen kann ich keinen Rückschluß auf das Verhalten der Member von CHausnummer machen.
-
Ich muss sie bei Objekten nicht verwenden! Weil:
Objekte sind nich so allgemeingültig wie ints.Ein Objekt meiner Klasse CAdresse wird Adresse heißen, und ein Zeiger drauf pAdresse. Und meine Adresse heißt: AdresseVonKartoffelsack
Ich kann aber unsigned short Member-Variable, wo ich die das Stockwerk speichere nicht "unsigned short" nennen, weil die Typinformation im ersten augenblick nicht interessiert. Deswegen heißt die Stockwerk. Und weils ne Member-Variable ist, mach ich ein m_ davor (oder von mir aus ein _ dahinter). Und weil es ein unsigned short ist, heißt sie m_ushStockwerk. Das ist problemlos lesbar und ich hab die Infos, die man hin und wieder braucht gleich dastehen. Das ist in erster Linie, dass es sich um das Stockwerk handelt, in zweiter dass es ein Member ist und in dritter der Typ (jetzt bitte nicht "dann müsstest Du ja ush_mStockwerk schreiben").
Und wie gesagt, ich mach auch bei manchen Klassen die Präfixe. Und zwar genau dann, wenn es sich um allgemeine Klassen handelt (smart-Pointer und Container)Bei den Funktionen geb ich Dir einerseits irgendwie recht, warum ichs trotzdem nicht mach hab ich schon versucht, zu erklären.
-
@king Zitier mich vollständig und lies alles durch, was ich schreibe! Gehn Euch jetzt die argumente aus?
Hab geschrieben dass man in c++ nich mit rohen Zeiger (und dyn Speicher) arbeiten sollte. Aber das geht an der Realität vorbei. Ich verwende hier z.B. ne C-Bib, die gibt mir Zeiger raus (doppelt schrecklich: Sie reserviert, ich muss freigeben). Ich packs dann natürlich gleich in nen Smart-Pointer. Aber ich arbeite mit rohen Zeigern.
Außerdem: ich seh nen Vorteil und keiner kann mir nen Nachteil nennen. Tippen ist keiner. Die Notation schlag ich nach, kann sie nach nem halben Tag und weil ich dann nicht mehr dauernd die Typen nachschauen muss hab ich die Zeit nach nem Tag wieder drinnen.
Außerdem hab ich geschrieben, dass ich eben keine Hausnummern-Klasse hab. Sondern ein string (auch ne Klasse bei der ich ein Präfix verwende) oder ein int, weil die bei meinen Anforderungen reichen.
-
Original erstellt von kartoffelsack:
Bei den Funktionen geb ich Dir einerseits irgendwie recht, warum ichs trotzdem nicht mach hab ich schon versucht, zu erklären.und ähnliche argumente die du gegen UN bei funktionen bringst, bringen wir bei normalen variablen
hier unterscheiden wir uns wirklich stark.
stockwerk
daran erkenne ich, dass es ein int-Typ ist. und ob das jetzt short, long, char,.. ist interessiert mich nicht, da ich diese information für überflüssig halte und du nicht.aber bei einem sind wir uns einig: UN bedeutet mehr aufwand (zB wenn sich der typ einer variablen ändert), oder?
-
Original erstellt von kartoffelsack:
[QB]Außerdem: ich seh nen Vorteil und keiner kann mir nen Nachteil nennen. Tippen ist keiner. Die Notation schlag ich nach, kann sie nach nem halben Tag und weil ich dann nicht mehr dauernd die Typen nachschauen muss hab ich die Zeit nach nem Tag wieder drinnen.sagmal, wir schreiben uns die ganze zeit die finger wund und du meinst 'keine nachteile'?
Nachteil?
Schreibarbeit
erschwert das lesen - du kannst lpfn oder lpsz oder pstr nicht flüssig lesen
bei klassen sowieso unmöglich UN zu verwenden, bzw. wäre es wahnsinn und würde nur alles verkomplizieren
welchen prefix hat ein std::string, welchen ein char* und welchen ein TCHAR*?
was wenn sich der typ einer variablen ändert?
der eine verwendest sCmdLine, der nächste szCmdLine der nächste pCmdLine und der nächste pstrCmdLine und der nächste strCmdLine und der nächste lpszCmdLine,...
und irgendwann weisst du, dass du die variable foo brauchst, aber du weisst nicht welches prefix sie hat. wars jetzt ein iFoo, uFoo, uiFoo, nFoo, unFoo?
und bei functions pointer wirds ja nur noch lustig.hab ich n paar seiten vorher geschrieben.
Das problem ist ja: nicht immer verwendet man die selben prefixe. zumindest nach 10 Jahren ändert man es doch irgendwann mal - und dann wirds grausig.
Ich weiß doch, dass ap ein std::auto_ptr is und xap is ne implementierunge eines referenzzählenden. In meinem Code ist das durchgängig so, und wer meinen Code liest, wirds auch recht schnell bemerken
Problem: ich lese nicht nur den code von EINEM Projekt, sondern von vielen.
sicher, wenn ich NUR dein projekt lese, kann ich mich gerne mit DEINER Notation beschäftigen, aber meistens hat man viele sourcen zu lesen...
-
Ehm Jungens, wenn ich das mal anmerken darf: Bei den etlichen Kilobytes die ihr hier schon an Text in diesen Thread gehämmert habt könnt ihr bis an euer Lebensende Präfixe verwenden. Das Argument mit der Schreibarbeit zählt also nicht mehr...
-
Bashar: 'Bei Lisp ist eben alles anders' ;).
Original erstellt von MaSTaH:
Bei den etlichen Kilobytes die ihr hier schon an Text in diesen Thread gehämmert habt könnt ihr bis an euer Lebensende Präfixe verwenden. Das Argument mit der Schreibarbeit zählt also nicht mehr...Glaubst Du ernsthaft, dass in diesem Thread _irgendein_ Diskussionsteilnehmer seine Beiträge von Hand getippt und nicht maschinell erzeugen hat lassen? Kann ich mir nicht vorstellen, denn augenscheinlich¹ enthalten sie ja keinerlei Inhalt, beziehen sich nur unwesentlich auf den Text des Vorposters(sic!) und weisen keinerlei Formen von Intelligenz auf, sondern geben stur Pseudo-Argumente in einer Form wieder, die entfernt an die deutsche Grammatik erinnert.
1): Lest ihr eigentlich noch selbst?
Ich bitte um Verzeihung, ich konnte einfach nicht widerstehen.