Delphi-PRAXiS
Seite 3 von 3     123   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Fluent Design und Records (https://www.delphipraxis.net/201758-fluent-design-und-records.html)

Schokohase 25. Aug 2019 20:13

AW: Fluent Design und Records
 
@stahli

Das Besondere am Fluent Interface ist kein Ersatz für
Delphi-Quellcode:
Result := CreateSomeInterface;
Result.DoSomething('withParameter');
Result.DoSomethingOther;
Result.ConvertEverythingTo;
sondern das hier
Delphi-Quellcode:
ResultA := CreateSomeInterface; // IFoo
ResultB := ResultA.DoSomething('withParameter'); // IBar
ResultC := ResultB.DoSomethingOther; // IOther
ResultD := ResultC.ConvertEverythingTo; // string
Natürlich ist es möglich das alle ResultX vom gleichen Typ sind und dann auch auf die gleiche Instanz verweisen, aber sie müssen es eben nicht.

Und die eingebaute Code-Formatierung formatiert das so (wenn man einen Zeilenkommentar anhängt)
Delphi-Quellcode:
Result := CreateSomeInterface() // IFoo
  .DoSomething('withParameter') // IBar
  .SoSomethingOther() // IOther
  .ConvertEverythingTo(); // string

Mavarik 26. Aug 2019 12:44

AW: Fluent Design und Records
 
Es gibt mehrere Gründe den Sourcecode "so" zu schreiben.

Beispiel SQL:

Delphi-Quellcode:
  TCRUDSearch.&For(fPerson).Where('NAME').LIKE(LastName.Trim)
  {}         .begin_Optional(FirstName.Trim <> '')
  {}            ._AND.Where('VORNAME').LIKE(FirstName.Trim)
  {}         .end_Optional.OrderBy('NAME')
  {}         .OrderBy('VORNAME ASC')
  {}         .Limit(100)
  {}         .Start(SearchResult);
Wie üblich die
Delphi-Quellcode:
{}
, damit der Formatter das nicht zerstört.
Nicht nur das ich mit diesem Interface keine Tippfehler mehr im "SQL-Source-Text" habe, ich kann auch mit dem "begin Optional(Statement)" je nach Kondition des Statements einen anderen SQL Code erzeugen.

oder halt sowas:

Delphi-Quellcode:
    TFMXFluentCreator<TDayLBL>.CreateDefault(FDayLBL[i-1],LConfig)
    {}                        .FontSize(FFontSize)
    {}                        .Skip(LConfig.Trim <> '',2).FontColor(LDisplayDay.Color).FontBold(LDisplayDay.Bold)
    {}                        .Text(FDays[i-1])
    {}                        {$IFNDEF NOHints}
    {}                          .Skip((LDisplayDay.Hint = '')).Hint(LDisplayDay.Hint)
    {}                        {$ENDIF}
    {}                        ;
Ich empfehle hierzu mein CodeRage Video. Auch wenn hier leider noch von Fluid und nicht Fluent gesprochen wird. // Danke Stefan hab es in ALLEN Sourcen renamed...

Hier gibe es wie bei meine SQL Creator (begin/end) ein Skip Command mit dem man 1-N der nächsten Fluent-Aufrufe überspringen kann je nach Kondition.
Per LConfig kann ich Aufruf die ich beliebig vordefinieren kann, zusätzlich abrufen.

Wenn man ListBoxItems im Source erzeugen möchte ist das eine fürchterliche Tipperei, besonders durch die TWhateverbezeichner.Value {$SCOPEDENUMS ON}.

Da sieht es doch schon deutlich einfacher aus, wenn man

Delphi-Quellcode:
TFMXFluentCreator<TListBoxItem>.RegisterDefault(Procedure (LBI : TFMXFluentCreator<TListBoxItem>)
  begin
    LBI.Style('listboxitembottomdetail')
       .Height(49)
       .Parent(ListBox1)
       .ItemMore.OnClick(Procedure (Sender : TObject)
          begin
            AViewModel.Edit((Sender as TListBoxItem).TagString);
            Translate.SetFocus;
          end,false);
  end);
schreiben kann..

Grüsse Mavarik :coder:

dummzeuch 26. Aug 2019 14:03

AW: Fluent Design und Records
 
Zitat:

Zitat von HolgerX (Beitrag 1443168)
Hmm..

Zitat:

Zitat von dummzeuch (Beitrag 1443161)
Zitat:

Zitat von peterbelow (Beitrag 1443150)
Stell Dir mal vor, Du mußt sowas debuggen, dann ist es nicht mehr so schön...

Einfach vernuenftig formatieren ...
Delphi-Quellcode:
Result := CreateSomeInterface
  .DoSomething('withParameter')
  .DoSomethingOther
  .ConvertEverythingTo
... und schon ist das kein Problem mehr. Und lesbarer ist es (IMHO) auch.
(Ob der OP das dann allerdings immernoch "schön" findet?).

So etwas ist immer gefährlich....

Was ist, wenn es beim '.DoSomething('withParameter')' kracht oder etwas geliefert wird, was in '.DoSomethingOther' zur Exception führt?

Wenn ich das in einer Zeile schreibe, wie kann ich dann im Debugger erkennen, wo es geknallt hat?

In der Regel ja. Deshalb die Formatierung mit einem Aufruf pro Zeile.
Zum Debuggen wäre natürlich eine Variable einfacher:

Delphi-Quellcode:
Result := CreateSomeInterface;
Result := Result.DoSomething('withParameter');
Result := Result.DoSomethingOther;
Result := Result.ConvertEverythingTo;
Aber das versaut das "schöne" dann komplett. ;-)

(Vorausgesetzt, es ist durchgehend derselbe Interface-Typ, denn wie Schokohase schon schrieb: Das ist nicht notwendigerweise der Fall. Wenn nicht, muesste man auch noch jede Menge Variablen deklarieren, was noch viel mehr Tipperei ist.)

Ich habe einige wenige solcher Konstruktionen, bei denen diese Kaskade einen Funktionsaufruf mit zig Parametern ersetzt hat. Die Lesbarkeit hat es auf jeden Fall verbessert.

Uwe Raabe 26. Aug 2019 14:43

AW: Fluent Design und Records
 
Zitat:

Zitat von dummzeuch (Beitrag 1443315)
Zum Debuggen wäre natürlich eine Variable einfacher

Macht sich auch besser im Watch-Fenster oder bei Ctrl-F7.

Es ist halt immer ein Kompromiss zwischen "schön" bzw. lesbar und leichter zu debuggen.

Zitat:

Zitat von dummzeuch (Beitrag 1443315)
Wenn nicht, muesste man auch noch jede Menge Variablen deklarieren, was noch viel mehr Tipperei ist.

Na ja, unter Rio hält sich das ja noch in Grenzen:
Delphi-Quellcode:
begin
  var ResultA: IFoo := CreateSomeInterface; // IFoo
  var ResultB: IBar := ResultA.DoSomething('withParameter'); // IBar
  var ResultC: IOther := ResultB.DoSomethingOther; // IOther
  var ResultD: string := ResultC.ConvertEverythingTo; // string
end;
Ach ja, früher galt with auch als richtig cool, weil man da soviel Tipperei spart.

stahli 26. Aug 2019 15:03

AW: Fluent Design und Records
 
Solche Zwischenschritte in einzelne Variablen zu speichern stört mich gar nicht. Ich finde, das erhöht sogar die Übersichtlichkeit deutlich.

Das mache ich auch schon mal bei etwas komplizierteren Berechnungen (Winkel o.ä.). Da nehme ich gern in Kauf, mal eine Variable anzulegen.

Einzig, eine ständige Wiederholung der gleichen Variable würde ich u.U. gern vermeiden, wenn es dafür eine abgekürzte Darstellung/Schreibweise gäbe (Alternative zum with).
Meine Klassen würde ich dafür aber nicht umbauen.


In Bezug auf "Tipparbeit vermeiden" fallen mir da ganz andere Themen ein, die ich wirklich wichtig fände und wo die IDE wirklich keine Hilfe ist.

Mavarik 26. Aug 2019 15:39

AW: Fluent Design und Records
 
Naja sagen wir mal so...

Für ein Interface, Klasse oder Record das man so verwendet/erstellt bietet es sich natürlich an, einen Unittest zu schreiben, dann braucht man i.d.R. auch nicht debuggen oder eher selten.

Mavark :coder:

Uwe Raabe 26. Aug 2019 15:53

AW: Fluent Design und Records
 
Zitat:

Zitat von mavarik (Beitrag 1443336)
bietet es sich natürlich an, einen unittest zu schreiben, dann braucht man i.d.r. Auch nicht debuggen oder eher selten.

:lol:


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:39 Uhr.
Seite 3 von 3     123   

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