AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Variablen "einsparen" <-> längere Befehlszeilen. Was ist sinnvoll?
Thema durchsuchen
Ansicht
Themen-Optionen

Variablen "einsparen" <-> längere Befehlszeilen. Was ist sinnvoll?

Ein Thema von silver-moon-2000 · begonnen am 7. Feb 2012 · letzter Beitrag vom 8. Feb 2012
Antwort Antwort
silver-moon-2000

Registriert seit: 18. Feb 2007
Ort: Schweinfurt
170 Beiträge
 
Delphi XE Professional
 
#1

Variablen "einsparen" <-> längere Befehlszeilen. Was ist sinnvoll?

  Alt 7. Feb 2012, 23:26
Delphi-Version: XE
Hallo zusammen,

erstmal ein "Sorry" für den wenig aussagekräftigen Titel, aber mir fällt nichts besseres ein.
Zweitens, nochmal sorry, denn der Post ist, wie bei mir üblich, recht lang. Wer will, kann gleich zur Frage unten springen

Diesmal habe ich ausnahmsweise mal kein Problem, sondern nur eine Frage, die mich interessiert.
Es geht darum, ob man sich nicht hin und wieder Variablen einsparen kann, ohne dass die Lesbarkeit des Codes darunter leidet.
Das ist jetzt eigentlich auch kein reines Delphi Problem, sondern eher ein allgemeines programmiertechnisches Problem.

Als Beispiel nehme ich mal den neuen Thread Prämien her.

Ich will ausdrücklich sagen, dass ich niemanden in keinster Weise nicht kritisieren will, jeder hat seinen eigenen Programmierstil, das ist auch gut so.
Und jetzt habe ich eben eine Frage zu meinem...
Ich hoffe, man nimmt es mir nicht übel, wenn ich jetzt fremden Programmcode auseinanderklaube, doch die Frage stellt sich mir eigentlich regelmäßig.

Sir Rufo zum Beispiel schreibt in Antwort #5 des obengenannten Threads:
Delphi-Quellcode:
procedure TForm1.Button1Click( Sender : TObject );
var
  Dauer : integer;
  Praemie : Currency; //<-------
begin
  if TryStrToInt( Edit1.Text, Dauer ) then
    begin
      Praemie := PraemieBerechnen( Dauer );//<-------
      Edit3.Text := FloatToStr( Praemie );//<-------
    end
  else
    ShowMessage( Edit1.Text + ' ist keine gültige Zahl' );
end;
Wenn ich das ganze schreiben würde, sähe es so aus. Ich würde auf die Variable praemie verzichten.
(gut, ich würde auch auf TryStrToInt verzichten, aber das ist eine andere Baustelle )
Delphi-Quellcode:
procedure TForm1.Button1Click( Sender : TObject );
var
  Dauer : integer;
begin
  if TryStrToInt(Edit1.Text, Dauer) then
      Edit3.Text := FloatToStr(PraemieBerechnen(Dauer));//<-------
  else
    ShowMessage(Edit1.Text + ' ist keine gültige Zahl');
end;
Ich persönlich finde (natürlich ) meine Version etwas übersichtlicher, da eine Variable eingespart wird, bei der man sich, wenn man den Quellcode später wieder man ansieht, nicht fragen muss, was die eigentlich gleich wieder für eine Bedeutung hatte.
Auf der anderen Seite ist diese Befehlszeile zwar länger geworden, aber noch nicht so lang, dass man von "Spaghetticode" sprechen könnte.

Anders sähe es dann bei Edit3.Text := FloatToStr( PraemieBerechnen( StrToInt( Edit1.Text) ) ) ); aus, das zwar nochmals eine Variable einspart, aber nun wirklich doch ein wenig Denkeinsatz verlangt (vom TryStrToInt mal abgesehen).
Soll heißen, Variablen einsparen in Maßen macht meiner Meinung nach Sinn, solange man es nicht übertreibt und eine Befehlszeile quer über den Bildschirm läuft.

Zweites Beispiel, damit Sir Rufo nicht alleine leiden muss:
Popov schreibt im selben Thread (von mir auf die Stellen gekürzt, die mich interessieren):
Delphi-Quellcode:
type
  TPraemie = class
    private
      FBetriebsJahre: Word;
      function Berechnung: Currency;
    public
      property BetriebsJahre: Word read FBetriebsJahre write FBetriebsJahre;
      property Summe: Currency read Berechnung;
  end;


function TPraemie.Berechnung: Currency;
begin
  if FBetriebsJahre > 0 then
  //Prämie berechnen
end;

[...]

procedure TForm1.Button2Click(Sender: TObject);
var
  Praemie: TPraemie;
begin
  Praemie := TPraemie.Create;
  try
    Praemie.BetriebsJahre := StrToInt( Edit1.Text );
    Edit3.Text := FloatToStr( Praemie.Summe );
  finally
    Praemie.Free;
  end;
end;
Wenn ich wieder so frech bin, meine Version gegenüberzustellen, dann käme vermutlich etwas in der Art heraus:
Delphi-Quellcode:
type
  TPraemie = class
    private
      FBetriebsJahre: Byte;
    public
      function berechnePraemie(_betriebsjahre : Byte) : Currency;
  end;
[...]

function TPraemie.berechnePraemie(_betriebsjahre : Byte) : Currency;
begin
  FBetriebsjahre := _betriebsjahre;

  if FBetriebsJahre > 0 then
  //Prämie berechnen
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  Praemie: TPraemie;
begin
  Praemie := TPraemie.Create;
  try
    Edit3.Text := FloatToStr(Praemie.berechnePraemie(StrToInt(Edit1.Text)));
  finally
    Praemie.Free;
  end;
end;
In dem Fall hätte ich also ein (oder zwei) Propertys eingespart.
Mir ist schon klar, dass sich Popovs und meine Version etwas unterscheiden, dass bei mir z.B. FBetriebsjahre nicht unabhängig von berechnePrämie(...) gesetzt werden kann.
Doch diese Funktionalität wird in Popovs Programm auch nicht benötigt.

Mit anderen Worten: Während Popovs Version insgesamt etwas mächtiger ist als meine, bewältigt meine Version die gleiche Aufgabe mit weniger Variablen / Properties. Für Sir Rufo gilt das gleiche analog.

Was ich vermeiden will (aber vermutlich dennoch erreicht habe), ist der Anschein, dass ich mich über die genannten Herren stellen will, dass ich also denken würde, mein Code sei besser als der Code der anderen. Das ist absolut nicht der Fall. Ich bin mir meines Status' als (blutiger) Anfänger durchaus bewusst und respektiere das Level der Andern.
gerade deswegen habe ich es aber als Vergleich herangezogen, getreu nach dem Motto: "Wer gut ist, kann nicht schlecht sein".

Weil ich also denke, dass die anderen guten Code schreiben, bin ich interessiert daran, wie sich meine Variante dagegen herausnimmt.

Oder anders formuliert: Warum lese ich häufig in diesem und anderen Foren die von Sir Rufo und Popov geschriebenen Varianten, in denen der Code mit "mehr" Variablen/Properties umgesetzt wird, wenn meiner Meinung nach die Lesbarkeit bei "moderatem" Variablen-Sparen nicht leidet?

Sorry nochmal an alle, die sich durch den Post gequält haben
Tobias
Bitte nicht hauen , ich weiß es nicht besser
  Mit Zitat antworten Zitat
Popov
(Gast)

n/a Beiträge
 
#2

AW: Variablen "einsparen" <-> längere Befehlszeilen. Was ist sinnvoll?

  Alt 7. Feb 2012, 23:43
Was mich angeht: a.) ich bin nicht böse b.) wie du es gemacht hast ist es wahrscheinlich besser c.) mein Beispiel war auch ein wenig Jux (siehe Klasse für so eine Berechnung ) aber d.) warum die Lösung nicht etwas interessanter gestalten, und e.) ich wollte zuerst noch das Rentenalter und paar andere Angaben prüfen, hab es dann aber sein lassen. Wäre dann doch zu viel geworden.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: Variablen "einsparen" <-> längere Befehlszeilen. Was ist sinnvoll?

  Alt 8. Feb 2012, 01:02
Beim Schreiben habe ich auch kurz überlegt, ob ich den Rückgabewert in einer Variable speichern oder eben direkt an das Edit übergeben soll

Ich habe mich dann aber bewusst dafür entschieden, um die Lesbarkeit zu erhöhen.

Dieses Beispiel ist generell (für mich) ein Grenzfall für die Verwendung einer lokalen Variable, da die gesamte Routine sehr klein ist und im Wesentlichen aus dem Aufruf einer Funktion besteht.
Somit wäre auch ich geneigt diese Variable zu sparen.

Allerdings wenn die Komplexität etwas zunimmt, dann würde ich immer die lokalen Variablen benutzen, um die Lesbarkeit und hauptsächlich das Debuggen erheblich zu vereinfachen.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#4

AW: Variablen "einsparen" <-> längere Befehlszeilen. Was ist sinnvoll?

  Alt 8. Feb 2012, 01:15
Ermessenssache. Ich spare gerne Variablen, wenn ich den ihr zugewiesenen, berechneten Wert im Anschluss nur ein weiteres Mal verwende - am liebsten dann, wenn der Methodenaufruf zur Berechnung des Wertes auch einen brauchbaren Namen hat. Ab einer Schachtelung von so 3-4, manchmal 5 Ausdrücken leidet die Lesbarkeit aber zuweilen, weswegen ich dort dann gucke, dass ich semantisch sinnvoll aufteile. Einfach schon, um ggf. Zwischenschritte nachher nicht zu übersehen. Auch bei längeren Stringliteralen in so einer "Wurst".

Sobald ich einen Wert in diesem Scope auch nur 2 Mal brauche, mache ich eine Variable draus. Allein schon weil ich mich dann besser fühle, weil weniger CPU Zyklen verbraten . (Ausnahme: Aufrufe von Length() und ähnlichen, die dank Compilermagic ähnlich billig sind, und der Funktionsname klar macht, was ich da gerade tu.)

So im Schnitt komme ich pro Methode selten auf mehr als 3-6 Variablen (ohne Mehrfachverwendungen für verschiedene Aufgaben, sowas mache ich nicht, allein schon weil es eine sinnvolle "Benamsung" erschwert). Begünstigt wird das vor allem auch dadurch, dass ich meine Methoden so klein wie möglich zu halten versuche.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#5

AW: Variablen "einsparen" <-> längere Befehlszeilen. Was ist sinnvoll?

  Alt 8. Feb 2012, 06:06
Sparen tut man nix, denn wenn man wirklich Variablen 'sparen' würde, wo sind die dann alle hin?

Es geht um Lesbarkeit und Performance, und zwar in dieser Reihenfolge.

Lokale Variablen sind genau dann sinnvoll, wenn sie die Lesbarkeit erhöhen oder einen erneuten redundanten Aufruf ersparen.

Delphi-Quellcode:
// OK, denn es geht um eine Jahresprämie
JahresPraemie := BerechnungNachNiederstedtSchneydermann(X, Y, F);
Edit3.Text := FloatToStr(JahresPraemie);
//
// Auch ok, denn die Beschreibung steckt nun in der Bezeichnung des Anzeigefeldes
EdJahresPraemie.Text := BerechnungNachNiederstedtSchneydermann(X, Y, F);
//
// Auch ok, denn die Beschreibung steckt in der Bezeichnung der Berechnungsfunktion
Edit3.Text := FloatToStr(BerechneJahresPraemie (X,Y,F));
//
// Allerdings ist Edit3 ein bescheuerter Name, also wäre das hier mein Favorit
EdJahresprämie.Text := FloatToStr(BerechneJahresPraemie (X,Y,F));
Stell Dir einfach vor, Du sollst den Code vorlesen und ohne Kommentare auskommen. Stell Dir weiterhin die Frage, ob man dir auf die Schulter klopfen würde, wenn andere deinen Code lesen (und verstehen), oder ob sie sich fragen, welche merkwürdig komplexe Gehirnwindungen in deinem Schädel herumschwirren.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.153 Beiträge
 
Delphi 12 Athens
 
#6

AW: Variablen "einsparen" <-> längere Befehlszeilen. Was ist sinnvoll?

  Alt 8. Feb 2012, 08:25
Zitat:
Delphi-Quellcode:
Praemie := PraemieBerechnen( Dauer );
Edit3.Text := FloatToStr( Praemie );
Erstmal, wie Furtbichler schon sagte, wären sprechende Variablen und Komponentennamem wichtig.

Und dann kommt es auf den Einzelfall drauf an.
Wenn die beiden Zeilen länger sind, dann wäre es unglücklich, wenn man diese Variable wegläßt und beides kombiniert, da es dadurch unübersichtlicher nur wird.
Bei kurzen Zeilen wäre es problemloser möglich, ohne die Übersichtlichkeit groß zu beeinträchtigen.

Außerdem Optimiert Delphi auch selber schonmal Variablen weg.
Delphi-Quellcode:
i := 132;
x := i;
Delphi-Quellcode:
i := 132;
x := i;
i := 456;
y := i;
Hier kann die Codeoptimieren locker mal das i komplett wegoptimieren, da essich eigentlich nur um Konstanten handelt.
Bzw. Sie kann das wegoptimeren, da der Zugewiesene Wert schon in der nächsten Zeile als Eintziges verwendet wird, wenn der Compiler nun merlt, daß diese Variable in den Registern bleiben könnte dann wird keine Variable auf dem Stack erzeugt ... die ist also praktisch auch weg.

Beim zweiten Beispiel könnte die Codeoptimierung erkennen, daß sie hier aus der einen deklarieren Variable eigentlich Zwei machen könnte, welche am Ende ebenfalls wieder weg können, da hier auch wieder alles in den CPU-Registern bleiben könnte.
Oder Sie macht mal aus zwei Variablen Eine ........... dafür ist Sie ja schließlich da.


Also kurzgefasst:
Es ist nichts verwerfliches, wenn man mal mehr Variablen verwendet, wenn es so der Übersichtlichkeit und dem Codeverständnis diehnt.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#7

AW: Variablen "einsparen" <-> längere Befehlszeilen. Was ist sinnvoll?

  Alt 8. Feb 2012, 08:26
Es geht darum, ob man sich nicht hin und wieder Variablen einsparen kann, ohne dass die Lesbarkeit des Codes darunter leidet.
Ich denke, dass fast immer die Lesbarkeit leidet. Hat man Berechnungen mit mathematischen Formeln, liest es ich mit Variablen wesentlich leichter.

Zitat:
wenn man den Quellcode später wieder man ansieht, nicht fragen muss, was die eigentlich gleich wieder für eine Bedeutung hatte.
Klar, so würde ich auch denken, wenn ich meine Variablen so benennen würde, dass die Bezeichnung in keinem Zusammenhang mit der Verwendung der Variablen steht.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.021 Beiträge
 
Delphi 12 Athens
 
#8

AW: Variablen "einsparen" <-> längere Befehlszeilen. Was ist sinnvoll?

  Alt 8. Feb 2012, 08:42
Diese temporären Variablen haben allerdings auch den angenehmen Nebeneffekt, daß ihre Inhalte im Debugger lesbar sind und dies auch nach dem folgenden Funktionsaufruf bleiben.

Manchmal kommt man auch nicht drum herum, z.B. wenn der folgende Methodenaufruf einen variablen Parameter erfordert oder es mehrere überladene Methoden gibt und der Funktionsrückgabewert nicht ganz passt (und ich nicht explizit casten will).

Übrigens hat der Pascal Analyzer unter Code Reduction einen Report, in dem genau dieser Fall erkannt wird: Local identifiers that are set and referenced once
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
silver-moon-2000

Registriert seit: 18. Feb 2007
Ort: Schweinfurt
170 Beiträge
 
Delphi XE Professional
 
#9

AW: Variablen "einsparen" <-> längere Befehlszeilen. Was ist sinnvoll?

  Alt 8. Feb 2012, 20:20
Hallo zusammen,

tut mir Leid, dass ich erst jetzt antworte, aber der knappe Halbmarathon hat mich doch ziemlich geschafft.

Die Posts schön zusammenfassen tut es mMn Furtbichler
Zitat:
Lokale Variablen sind genau dann sinnvoll, wenn sie die Lesbarkeit erhöhen oder einen erneuten redundanten Aufruf ersparen.
Medium hat ebenfalls das DRY-Prinzip angesprochen. Das ist meiner Meinung nach der wichtigste Grund, Variablen überhaupt einzusetzen.

Beispiel: Das von mir viel zelebrierte Auseinanderpflücken eines Strings (schlagt mir jetzt aber bitte kein RegEx vor)
Delphi-Quellcode:
var
  temp : string;
  p1, p2 : Integer;
[...]
temp := '<a href="';
p1 := Pos(temp, MyString);
if p1 > 0 then
begin
  p1 := p1 + Length(temp);
  p2 := PosEx('"', MyString, p1);
  MyString := Copy(MyString, p1, p2 - p1);
end;
Hier die drei Variablen ersetzen zu wollen, würde definitiv in einer Menge Schreibarbeit und Kopfkratzen ausarten.

Die von Luckie, Furtbichler, Himitsu und anderen angesprochene vernünftige Benamsung von Variablen spart natürlich einen gewissen Teil dieses Kopfkratzens ein, da habt Ihr vollkommen Recht.
Heute schreibe ich auch "edAusgabePraemie" und nicht mehr "Edit3". Aber ich finde "p1" übersichtlich genug (so heißt es bei mir schon seit langer Zeit) und es muss nicht "iPosStart" heißen, damit ich später noch meinem Gedankengang folgen kann.


Während das DRY-Prinzip nach halbwegs objektiv ist, kommen wir doch mit der Lesbarkeit in einen völlig subjektiven Bereich hinein.
Ich sage (gilt ausschließlich für mich!) dass mich eine Variable, die ich nur ein einziges Mal brauche, eher irritiert, da ich nach dem DRY-Prinzip noch eine weitere Verwendungsstelle erwarte.

Aus einem aktuellen "5h-Projekt": Ich schreibe lieber
arr[i].Datei := StringReplace(Trim(SLt.Strings[2]), ' MiB', '', [rfReplaceAll]);
und nicht
Delphi-Quellcode:
temp_string := Trim(SLt.Strings[2]);
arr[i].Datei := StringReplace(temp_string, ' MiB', '', [rfReplaceAll]);
Ja, das war jetzt ein sehr einfaches Beispiel, bei dem auch Sir Rufo und Himitsu vermutlich gesagt hätten, dass es "generell [...] ein Grenzfall für die Verwendung einer lokalen Variable" sei.
Dass man das auf der anderen Seite nicht übertreiben muss, steht auch fest. Selbst ich schreibe lieber
Delphi-Quellcode:
d := Copy(SL.Strings[i], 1, 2);
m := Format('%.2d', [FindMonth(Copy(SL.Strings[i], 4, 3))]);
y := Copy(SL.Strings[i], 8, 2);
bib.book[bib.findByTitle('Bordbuch Delta VII')].Date := y + '-' + m + '-' + d;
und nicht einen unverstehbaren und unwartbaren Spaghetticode wie
bib.book[bib.findByTitle('Bordbuch Delta VII')].Date := Copy(SL.Strings[i], 8, 2) + '-' + Format('%.2d', [FindMonth(Copy(SL.Strings[i], 4, 3))]) + '-' + Copy(SL.Strings[i], 1, 2);

Die von Uwe Raabe angesprochene Auswertbarkeit im Debugger ist natürlich ebenfalls ein Vorteil, der mir auch schon das eine oder andere Mal aus der Patsche geholfen hat. (Auf der anderen Seite gibt es aber auch OutputDebugString(...), das ebenfalls gute Dienste leistet, besonders in Threads)

Es gibt wirklich Vorteile für die Verwendung von lokalen Variablen: Das DRY-Prinzip und die Debugbarkeit seien da mal genannt.

Was die bessere Lesbarkeit anbelangt:
Ich bin nach wie vor der Meinung, dass nicht jede Variable nötig ist.
Beispielsweise ist mir eine kürzere (von der Anzahl der Zeilen) Methode lieber als eine längere. Bei der kürzeren müssen zwangsläufig einige Befehle zusammengefasst werden, was die einzelne Zeile länger werden lässt.
Es ist aber für mich wichtiger, um einen Überblick zu bekommen, schnell erkennen zu können, was diese Methode macht. Dafür nehme ich in Kauf, dass ich bei der einen oder anderen Befehlszeile einen Moment länger überlegen muss (solange es wie gesagt nicht in Spaghetticode ausartet).

Ich denke, man muss sich dabei irgendwo in der Mitte treffen.

Wie immer in kurz: Ihr sagt mehrheitlich, dass die Verwendung von (lokalen) Variablen positiv gesehen werden kann, da sie der Lesbarkeit anträglich sind.


Danke und tschüss

Das sollte jetzt keine Belehrung an Euch sein, sondern eher meine selbstreflektive Zusammenfassung der Dinge, die Ihr geschrieben habt.
Tobias
Bitte nicht hauen , ich weiß es nicht besser
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:42 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz