Entwickler-Ecke

Open Source Units - Funktion, welche If then else etwas übersichtlicher macht


Tranx - So 09.01.11 20:32
Titel: Funktion, welche If then else etwas übersichtlicher macht
Hallo Leute,
habe mich immer wieder geärgert, dass dauernd diese if .. then .. else - Konstrukte in meinem Programm auftauchen. Meist waren es nur einfache Zuweisungen der Art:


Delphi-Quelltext
1:
2:
3:
4:
  if Bedingung then
    Wert := a
  else
    Wert := b;


Ich habe daher eine ganz einfache Funktion definiert, welche diese Abfrage auf eine Zeile verkürzt.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
unit Bedingung;

interface

uses
  SysUtils;

function WennDann(Bedingung: boolean; wenn, dann: Variant): variant; overload;
function WennDann(Bedingung: boolean; wenn, dann: TObject): TObject; overload;

implementation


function WennDann(Bedingung: boolean; wenn, dann: Variant): variant;
begin
  if Bedingung then
    Result := wenn
  else
    Result := dann;
end;

function WennDann(Bedingung: boolean; wenn, dann: TObject): TObject;
begin
  if Bedingung then
    Result := wenn
  else
    Result := dann;
end;

end.


Bei Zuweisungen einfacher Typen klappt das problemlos. Char könnte ebenfalls zugewiesen werden, ist jedoch nicht kompatibel zu Variant. Daher müsste da auch eine überladene Funktion geschrieben werden. Doch das benötigte ich nur zweimal in meinem Projekt.

Aufruf erfolgt wie folgt:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
var
  s : string;
  n : longint;
  t : TDateTime;
  Tabelle,
  tTable1,
  tTable2 : TTable;  

function Frage(s: string): Boolean;
begin
  Result := (messageDlg(s, mtConfirmation, [mbYes, mbNo], 0) = mrYes);
end;


// Achtung Nur ein Code-Schnipsel!!!

// Zuweisung bei einfachen Variablen:
  s := WennDann(n>0,'größer Null','nicht größer Null');  
  t := WennDann(Frage('Uhrzeit ?'),time,date);

// Zuweisung bei Nachfolgern von TObject:

  Tabelle := WennDann(Bedingung, tTable1, tTable2) as TTable;
  n := WennDann(Tabelle.RecordCount>0,Tabelle.RecordCount,-1);


Dito für andere Nachfolgeklassen.

Da das Ganze eine Funktion ist, kann auch eine folgender Konstrukt erfolgen:


Delphi-Quelltext
1:
2:
3:
4:
5:
:
:
  List1.Items.Add(WennDann(Frage('Ist der Wert ok?'),'Wert ist ok','Wert ist nicht ok');
:
:


Vielleicht ist das für Euch auch nützlich. Zugegeben, nur ein einfaches Tool. Aber meine Programme sind dadurch wirklich etwas aufgeräumter.


Moderiert von user profile iconMartok: Topic aus Algorithmen, Optimierung und Assembler verschoben am So 09.01.2011 um 20:36


jaenicke - So 09.01.11 20:40

Es gibt für diverse Typen bereits IfThen als Befehl.

Der deutliche Nachteil an deiner Variante ist, dass du Variants benutzt. Da diese sehr langsam sind, ist das nur geeignet, wenn es auf die Performance nicht ankommt. Wenn das aber sehr oft aufgerufen wird, ist das relativ langsam.

// EDIT:
Wobei zumindest keine Typumwandlungen notwendig sind, aber auch die Prüfungen dauern.

Deutlich besser geht das mit Generics, aber die gibt es erst ab Delphi 2009, mal so hingetippt:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
function IfThen<T>(Value: Boolean; TrueValue, FalseValue: T): T;
begin
  if Value then
    Result := TrueValue
  else
    Result := FalseValue;
end;


Tranx - So 09.01.11 20:48

Das mit der Performance ist mir schon klar. Doch bei den Anwendungen, welche ich meine, ist das eher zweitrangig.

In meiner Entwicklungsumgebung (bisher Delphi 5) habe ich wenig Alternativen.

//EDIT:
Zusätzlich kommt hier ein Effekt hinzu, der nicht zu vernachlässigen ist. Beim Debuggen hat man ja einenm Einstiegspunkt. Falls irgendwelche IF..THEN...ELSE nicht so funktionieren, wie gewünscht, sind sie einfach zu kontrollieren. Nur ein oder zwei Haltepunkte statt hunderter.


jaenicke - So 09.01.11 20:54

user profile iconTranx hat folgendes geschrieben Zum zitierten Posting springen:
In meiner Entwicklungsumgebung (bisher Delphi 5) habe ich wenig Alternativen.
Außer es eben für die wichtigsten Typen einzeln zu deklarieren wie es ab Delphi 6 auch in Delphi selbst passiert ist (dort für Integer, Int64, Double und string).

user profile iconTranx hat folgendes geschrieben Zum zitierten Posting springen:
Das mit der Performance ist mir schon klar. Doch bei den Anwendungen, welche ich meine, ist das eher zweitrangig.
Dann ist das auch in Ordnung, mir hat nur der Hinweis gefehlt, denn das ist sicher nicht jedem klar. ;-)

// EDIT:
Nebenbei: Ob es tatsächlich aufgeräumter ist, darüber lässt sich streiten. Ich verzichte mittlerweile zugunsten der Lesbarkeit (ein Befehl pro Zeile, ...) wieder auf IfThen, habe es aber vor ein paar Jahren auch oft benutzt. Wie auch den Konditionaloperator in Java (noch "schöner" :D).


Martok - So 09.01.11 21:40

Ich hab das mal in Open Source Units verschoben, auch wenns nur ein Fragment ist.
Passt aber besser als AOA ;)

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
habe es aber vor ein paar Jahren auch oft benutzt. Wie auch den Konditionaloperator in Java (noch "schöner" :D).
Du solltest NIEMALS ein JavaScript von mir lesen, das ist voll davon :)


Jakob_Ullmann - Sa 05.03.11 18:54

Ich finde, der ?:-Operator ist eines der sinnvollsten Dinge, die C und die Sprachen mit einer ähnlichen Syntax zu bieten haben.

Übrigens auch cool: Der ??-Operator in Vala (Weiß nicht, ob den noch andere Programmiersprachen haben, aber ich habe den bisher nur in Vala gesehen).


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
output = person ?? "<unknown>";


/* dasselbe:
 */

output = (person != null) ? person : "<unknown>";


/* oder eben:
 */

if (person != null) {

    output = person;

} else {

    output = "<unknown>";
}


jaenicke - Sa 05.03.11 19:37

Ich habe den Konditionaloperator ja auch viel und gerne benutzt, aber nur weil ich da gerade erst gelernt habe und es schön fand, dass der Code so kurz war, ihn aber niemand auf Anhieb verstanden hat...

Mittlerweile möchte ich, dass andere den Code verstehen, deshalb schreibe ich lieber sauberen und übersichtlichen Code mit ausführlichen Bezeichnern usw....


Kha - So 06.03.11 01:49

<der-muss-sein>

Die Beliebtheit von ?: muss nicht unbedingt nur mit der Prägnanz des erzeugten Quellcodes zusammenhängen (und wie so oft dürfte er eher Produkt denn Ursache unübersichtlichen Codes sein), sondern kann als eine der wenigen Möglichkeiten in C-artigen Sprachen, innerhalb eines Ausdrucks Kontrollfluss zu erzeugen (wer möchte heutzutage noch Short-Circuiting-Operatoren missen?), die Sehnsucht des Programmierers nach funktionalem/deklarativem Code (derer er sich vielleicht gar nicht bewusst ist) ausdrücken. Belege für diesen Trend auch in imperativen Sprachen wären z.B. die Ausdruckstypen in Prism [http://blogs.remobjects.com/blogs/mh/2010/02/20/p1116].

</der-muss-sein>... :mrgreen:




user profile iconJakob_Ullmann hat folgendes geschrieben Zum zitierten Posting springen:
Übrigens auch cool: Der ??-Operator in Vala (Weiß nicht, ob den noch andere Programmiersprachen haben, aber ich habe den bisher nur in Vala gesehen).
Stammt von C#.


Jakob_Ullmann - So 06.03.11 10:16

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconJakob_Ullmann hat folgendes geschrieben Zum zitierten Posting springen:
Übrigens auch cool: Der ??-Operator in Vala (Weiß nicht, ob den noch andere Programmiersprachen haben, aber ich habe den bisher nur in Vala gesehen).
Stammt von C#.


Trotzdem cooler Operator (Ich habe ihn nur leider noch nie in einem C#-Programm gesehen :oops: ).


Delphi-Laie - So 06.03.11 12:21

user profile iconTranx hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
function WennDann(Bedingung: boolean; wenn, dann: Variant): variant;
begin
  if Bedingung then
    Result := wenn
  else
    Result := dann;
end;

function WennDann(Bedingung: boolean; wenn, dann: TObject): TObject;
begin
  if Bedingung then
    Result := wenn
  else
    Result := dann;
end;

end.


Die deutschen Bezeichnungen in den Funktionen sind falsch übersetzt und damit - gelinde gesagt - irritierend, genaugenommen fehleranfällig. M.E. jedenfalls fehleranfälliger als das originale if-then-else, deren hier behauptete Unübersichtlichkeit ich nicht bestätigen kann.

if- wenn, falls, sofern
then - dann, so
else - sonst, ansonsten, anderenfalls

user profile iconTranx hat folgendes geschrieben Zum zitierten Posting springen:
Ich habe daher eine ganz einfache Funktion definiert, welche diese Abfrage auf eine Zeile verkürzt.


Wenn die Bedingung nicht allzu lang/komplex ist und der/die Befehl(e) hinter then und ggf. else ebenfalls nicht zu lang sind, die Übersichtlichkeit also gewahrt bleibt, dann packe ich derlei auch in eine Zeile bzw. dann kann man es in eine Zeile schreiben.. Einer Zusatzfunktion bedarf es also dafür nicht (unbedingt).

Ich staune, daß solche "elementaren" Befehle wie die der Verzweigung überhaupt in eine Funktion gepackt und so halbwegs substituiert werden können. Eine echte Notwendigkeit erkenne ich in dieser m.E. unnötigen Verkomplizierung allerdings nicht.