Entwickler-Ecke
Sonstiges (Delphi) - Sauberes Programmieren
freedy - Mo 25.10.04 13:24
Titel: Sauberes Programmieren
Hallo Forum!
Ich habe zwar schon probiert, einen Artikel über die Suche zu finden, hab aber leider keine Treffer erzielt.
Ich verwende Funktionen, die Variablen übergeben bekommen. Nehmen wir einfach mal an, die Funktion xy bekommt drei Variablen:
xy(a, b, c);
Mit den Werten a und c muss ich auch sonst umgehen. Die Variable b hingegen ist nur ein Dummy, damit ich die Funktion bzw. Prozedur ausführen kann.
Natürlich meldet Delphi beim Compilieren:
[Hinweis] dateiname.pas(218): Auf 'b' zugewiesener Wert wird niemals benutzt
Wie löst ihr solche Probleme?
freedy
PS: Die Prozedur xy() kann ich leider nicht umschreiben, weil b manchmal auch nicht als Dummy fungiert.
MrSaint - Mo 25.10.04 13:30
Also wenn du den Parameter "b" auch nur manchmal brauchst, kannst du daran nix optimieren... Lass den Compiler einfach meckern, das geht net besser...
MrSaint
jasocul - Mo 25.10.04 13:42
Diese Compiler-Meldungen kannst du in die Tonne treten.
Sobald du mit Try-Except-Blöcken arbeitest, fängt der Compiler noch mehr an rumzuspinnen. Bemängelt dann Variablen, die gar nicht benutzt werden, obwohl das einfach falsch ist.
freedy - Mo 25.10.04 14:19
Aber macht das Sinn, alles in die Tonne zu kloppen? Hm... *grübel*
Wir versuchen halt, unser Projekt möglichst sauber und nach Delphi-StyleGuide zu proggen.
D.h. für uns:
- keine Hinweise
- keine Warnungen
- keine Fehler (klar, sonst würd's ja nicht zu compilieren sein)
Gruß
freedy
jasocul - Mo 25.10.04 14:26
Es spricht nichts dagegen, die Hinweise zu prüfen. Nur stimmen die halt nicht immer.
Ansonsten kann ich nur empfehlen, die Prozeduren so zu halten, dass du von vornherein den Überblick behältst.
Stübi - Mo 25.10.04 14:30
Bei uns gilt auch ganz klar die Regel Keine Hinweise und Warnungen, jedoch ist das Firmenintern und ich darf auch nur Englische coments geben :cry:
Wie du das für die handhaben willst musste selbst wissen.
Gruss Stübi
Motzi - Mo 25.10.04 14:45
Also in 98% aller Fälle sind Warnungen und Hinweise durchaus gerechtfertigt. Sollte es dennoch mal passieren, dass der Compiler einen Fehler/eine Warnung ausgibt obwohl man genau weiß, dass diese an dieser Stelle überflüssig ist, so kann man die Hinweise und Warnungen per Compiler-Schaltern an diesen Stellen deaktivieren. Siehe dazu in der OH unter $HINTS bzw $WARNINGS
jasocul - Mo 25.10.04 14:46
Ich geb euch jetzt mal ein Beispiel:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| try Screen.Cursor := crHourGlass; sl := TStringList.Create; ... finally Screen.Cursor := crDefault; sl.Free; end; |
Da bekomme ich eine Warnung, dass die Variable sl nicht initialiert wurde.
Soll ich sowas ernst nehmen???
Motzi - Mo 25.10.04 14:49
Das hat einen ganz einfachen Grund... was passiert, wenn VOR der Zeile:
Delphi-Quelltext
1:
| sl := TStringList.Create; |
eine Exception auftritt? Richtig, er geht weiter in den finally-Teil und in diesem Fall wäre sl definitiv nicht initialisiert. Daher erzeugt man normalerweise zuerst das Objekt und öffnet erst dann den try-finally Block.
.Chef - Mo 25.10.04 14:50
Ich versuch ja auch immer, alles ohne Meldungen hinzukriegen. Aber zum Beispiel habe ich öfters "Combining signed and unsigned values. Widened both operants." (oder so). Unter einigem Aufwand würde man diese Meldungen zwar wegkriegen, aber der Übersichtlichkeit des Codes ist nicht geholfen, wenn man z.B. um jedes Length() noch ein Cardinal() schreibt.
Gruß,
Jörg
heinze - Mo 25.10.04 14:52
Mal kleiner Anfängeridee
Quelltext
1: 2: 3:
| b:=b+1-1; //oder am schlus der function b:=0; |
freedy - Mo 25.10.04 14:53
jasocul hat folgendes geschrieben: |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| try Screen.Cursor := crHourGlass; sl := TStringList.Create; ... finally Screen.Cursor := crDefault; sl.Free; end; |
|
deshalb würde ich das auch so schreiben:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| sl := TStringList.Create; try Screen.Cursor := crHourGlass; ... finally Screen.Cursor := crDefault; sl.Free; end; |
Er erreicht auf jeden Fall den finally-Block. Von daher gibt es auch keine Fehlermeldung.
jasocul - Mo 25.10.04 14:58
Es sei denn, ich bekomme einen Fehler bei Create.
jojo-sp - Mo 25.10.04 15:08
Das läuft auf ein Zeit paradoxon hinaus, man kann die Vergangenheit nicht verändern! :-)
Aber ich hab auch so ein paar nette hinweise. Ich habe die Variable Hres lokal initialisiert, sie wird aber als "[Warnung] MainUnit.pas(76): Variable 'HRes' wurde wahrscheinlich nicht Initialisiert" ausgespuckt.
uall@ogc - Mo 25.10.04 15:09
dann macht man da sauch so:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| s1 := nil; try Screen.Cursor := crHourGlass; sl := TStringList.Create; ... finally Screen.Cursor := crDefault; if assigned(s1) then sl.Free; end; |
jasocul - Mo 25.10.04 15:12
Das wäre dann wirklich die sauberste Lösung.
freedy - Mo 25.10.04 15:30
Die Lösung von uall@ogc ist auf jeden Fall kleverer als meine... dann werde ich wohl heute mal eine Extraschicht einlegen müssen. :wink:
Ich bin ja bisher immer davon ausgegangen, dass Fehler, die in einem Create passieren, dort auch abgefangen werden. Klar, meine Prozedur läuft dann auch schief. Macht also Sinn.
Gruß
freedy
Nagelbrett - Mo 25.10.04 15:41
wobei man sich das if Assigned(sl) .. im finally dann auch sparen kann, da bei Aufruf von Free sowieso auf nil geprüft wird und es dann ja doppelt gemoppelt wäre
uall@ogc - Mo 25.10.04 15:48
hm jo
Motzi - Mo 25.10.04 19:39
3 Sachen: erstens überprüft Free (wie bereits erwähnt) intern sowieso ob der Self-Pointer nil ist, zweitens liefert ein Konstruktor sowieso nil zurück wenn eine Exception auftritt und 3tens was für ein Objekt willst du im finally-Teil freigeben wenn dieses gar nicht erst erstellt wurde weil eine Exception im Konstruktor aufgetreten ist?
Wenn es dir also darum geht auf Exceptions im Konstruktor zu reagieren müsste es so ausschaun:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| try aObject = TMyClass.Create(..); try ... finally aObject.Free; end; except .. end; |
AndyB - Mo 25.10.04 20:10
Motzi hat folgendes geschrieben: |
zweitens liefert ein Konstruktor sowieso nil zurück wenn eine Exception auftritt |
Das macht er nicht. Er spring direkt zum nächsten Finally oder Except, womit die Variable uninitialisiert bleibt.
Motzi - Mo 25.10.04 20:21
AndyB hat folgendes geschrieben: |
Motzi hat folgendes geschrieben: | zweitens liefert ein Konstruktor sowieso nil zurück wenn eine Exception auftritt |
Das macht er nicht. Er spring direkt zum nächsten Finally oder Except, womit die Variable uninitialisiert bleibt. |
Hast recht.. hatte das irgendwie anders in Erinnerung.. :?
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!