Delphi-PRAXiS
Seite 1 von 5  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Trennung von GUI und Logik, wie geht ihr vor? (https://www.delphipraxis.net/162373-trennung-von-gui-und-logik-wie-geht-ihr-vor.html)

divBy0 19. Aug 2011 15:09

Trennung von GUI und Logik, wie geht ihr vor?
 
Hallo zusammen,

in diversen Themen hier taucht ja immer wieder die Trennung von GUI und Logik auf. Mich würde es mal interessieren wie ihr dabei vor geht.

Beispiel:

Ein Formular mit zwei Edits, einem Button und einem Label.

Delphi-Quellcode:
unit uMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, uAddition, StdCtrls;

type
  TForm1 = class(TForm)
    EditZahl1: TEdit;
    EditZahl2: TEdit;
    ButtonAddition: TButton;
    LabelErgebnis: TLabel;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

end.
Eine Klasse mit einer "extrem schwierigen" Berechnung: 8-)

Delphi-Quellcode:
unit uAddition;

interface

type
  TAddition = class
    private
      FErgebnis: Integer;
    public
      function Addition(Zahl1, Zahl2: Integer): Integer;
      property Ergebnis: Integer read FErgebnis;
  end;

implementation

{ TAddition }

function TAddition.Addition(Zahl1, Zahl2: Integer): Integer;
begin
  FErgebnis := Zahl1 + Zahl2;
  Result := FErgebnis;
end;

end.
Vielen Dank schon mal für euer Mitmachen!

Stevie 19. Aug 2011 15:15

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Meine Klasse sähe so aus:
Delphi-Quellcode:
type
  TAddition = class
  private
    FErgebnis: Integer;
  public
    procedure Addition;
    property Zahl1: Integer read FZahl1 write FZahl1;
    property Zahl2: Integer read FZahl2 write FZahl2;
    property Ergebnis: Integer read FErgebnis;
  end;
und dann würde ich die Properties an die Edits und das Label binden und die Methode an den Button

divBy0 19. Aug 2011 15:45

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Ok, damit sieht dein ButtonOnClick so aus oder?

Delphi-Quellcode:
procedure TForm1.ButtonAdditionClick(Sender: TObject);
begin
  FAddition.Zahl1 := StrToIntDef(EditZahl1.Text, 0);
  FAddition.Zahl2 := StrToIntDef(EditZahl2.Text, 0);
  FAddition.Addition;
  LabelErgebnis.Caption := IntToStr(FAddition.Ergebnis);
end;
Dies sollte doch eigentlich auch vermieden werden, wegen Spaghetticode.

Stevie 19. Aug 2011 16:03

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von divBy0 (Beitrag 1118094)
Ok, damit sieht dein ButtonOnClick so aus oder?

Delphi-Quellcode:
procedure TForm1.ButtonAdditionClick(Sender: TObject);
begin
  FAddition.Zahl1 := StrToIntDef(EditZahl1.Text, 0);
  FAddition.Zahl2 := StrToIntDef(EditZahl2.Text, 0);
  FAddition.Addition;
  LabelErgebnis.Caption := IntToStr(FAddition.Ergebnis);
end;
Dies sollte doch eigentlich auch vermieden werden, wegen Spaghetticode.

Zitat:

Zitat von Stevie (Beitrag 1118088)
und dann würde ich die Properties an die Edits und das Label binden und die Methode an den Button

Das Verb binden bezieht sich in diesem Satz auch auf "die Methode an den Button" :)

Somit entsteht in dem Form 0 Code. Es gibt nur ca 4 Zeilen externen Wire up Code.

Phoenix 19. Aug 2011 16:07

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von divBy0 (Beitrag 1118094)
Ok, damit sieht dein ButtonOnClick so aus oder?

Delphi-Quellcode:
procedure TForm1.ButtonAdditionClick(Sender: TObject);
begin
  FAddition.Zahl1 := StrToIntDef(EditZahl1.Text, 0);
  FAddition.Zahl2 := StrToIntDef(EditZahl2.Text, 0);
  FAddition.Addition;
  LabelErgebnis.Caption := IntToStr(FAddition.Ergebnis);
end;
Dies sollte doch eigentlich auch vermieden werden, wegen Spaghetticode.

Nein, das sollte deshalb vermieden werden, weil das Form um himmels willen niemals im Leben nicht die Klasse TAddition kennen darf.

Es geht ja gerade darum, die Logik vom GUI zu trennen. Deswegen darf die GUI die Logik nicht kennen. Und die Logik das GUI auch nicht.

Dazwischen muss etwas geschaltet werden, das als Vermittler agiert. Also z.B. klassisches MVC: Model (Logik), View (Form), Controller (kennt beides), der Controller fehlt hier komplett und wäre dann das, was die Logik-Klasse mit ihren Properties an die ein- bzw. Ausgabefelder am Form und die Ausführung der Methode an deren Button event bindet.

SebE 19. Aug 2011 16:26

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Ich mache das immer der Art:

Delphi-Quellcode:
type
  TAdditionVisualComponent = class
    public:
      procedure resultChangeEvent(result: integer); virtual; abstract;
    end;

type
  TAddition = class
    [...]

    private:
      visualComponent: TAdditionVisualComponent;
    end;

// ---

function TAddition.Addition(Zahl1, Zahl2: Integer): Integer;
begin
[...]

if self.visualComponent <> nil then
  self.visualComponent.resultChangeEvent(Zahl1 + Zahl2);
end;
Konkrete Implementation der visuellen Repräsentation im Presenter/in der View (ich verwende eine abgewandelte Form des MVC):

Delphi-Quellcode:
type
  TAdditionVC = class(TAdditionVisualComponent);
  public:
    procedure resultChangeEvent(result: integer); override;
  end;

// ---

procedure TAdditionVC.resultChangeEvent(result: integer);
begin
  Form1.Edit1.Text = IntToStr(result);
end;
Der Aufruf des ganzen erfolgt aus der GUI über den Controller (falls vorhanden zuvor über den Presenter):
Delphi-Quellcode:
MyController.Add(StrToInt(Edit2.Text), StrToInt(Edit3.Text));
Jetzt kommt es darauf an, wie man den Controller mit den Business-Objekten verbinden möchte.
Der einfachste Fall (der Controller kennt nur ein Objekt):
Delphi-Quellcode:
type
  Controller = class;
    private:
      MyAddition: TAddition;
  end;

// ---

procedure Controller.Add(Zahl1, Zahl2: integer);
begin
  MyAddition.Addition(Zahl1, Zahl2);
end;
MyAddition
Das ist das, was ich aus dem Stehgreif auf die Schnelle zusammentragen kann.

Stevie 19. Aug 2011 16:31

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von SebE (Beitrag 1118102)
Konkrete Implementation der visuellen Repräsentation im Presenter/in der View (ich verwende eine abgewandelte Form des MVC)

Mich persönlich hat bei dem MVC/MVP Modell immer gestört, dass man für meinen Geschmack zu viel Code erzeugt und trotzdem noch statische Abhängigkeiten hat

Das ist auch ansatzweise an deinem Beispiel sichtbar.

Progman 19. Aug 2011 16:35

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
"Wie mache ich aus einer trivialen Aufgabe ein extrem kompliziertes Konstrukt"
So wäre meine Kurzbeschreibung zu dem, was ich bisher hier im Thema gelesen habe :-D
Aber soll jeder machen, wie er's für richtig hält :P

Florian Hämmerle 19. Aug 2011 16:42

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von Progman (Beitrag 1118105)
"Wie mache ich aus einer trivialen Aufgabe ein extrem kompliziertes Konstrukt"
So wäre meine Kurzbeschreibung zu dem, was ich bisher hier im Thema gelesen habe :-D
Aber soll jeder machen, wie er's für richtig hält :P

So wie ich es verstanden habe, möchte der TE an einem einfachen Beispiel die Herangehensweise erlernen. Da bringt es nichts, gleich komplexe Beispiele zu bringen. Lieber vom kleinen dann aufs große übertragen :)
Könnte noch sehr interessant werden, vor allem dann mit X-Plattform. Da bezahlt man dann sehr teuer, wenn man es nicht schön getrennt hat ;)

Stevie 19. Aug 2011 16:42

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von Progman (Beitrag 1118105)
"Wie mache ich aus einer trivialen Aufgabe ein extrem kompliziertes Konstrukt"
So wäre meine Kurzbeschreibung zu dem, was ich bisher hier im Thema gelesen habe :-D
Aber soll jeder machen, wie er's für richtig hält :P

Wie gut, dass er uns hier ein einfaches Beispiel gegeben hat und nicht eine komplette Warenwirtschaft und dann gefragt hat, hey, zeigt mir das mal ...

Dass man dann mit dem "Ach, bei so nem trivialen Beispiel..." kommen kann, war klar ;)

SebE 19. Aug 2011 16:48

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Mich persönlich hat bei dem MVC/MVP Modell immer gestört, dass man für meinen Geschmack zu viel Code erzeugt und trotzdem noch statische Abhängigkeiten hat

Das ist auch ansatzweise an deinem Beispiel sichtbar.
Das muss man wirklich zugeben. Die Menge an Code wächst enorm!
Bei großen Projekten wirkt sich das irgendwann nicht mehr so stark aus - und kann auch nicht umgangen werden.
Man sollte sich (bei großen Projekten) immer die Option offen halten, die GUI einfach auszutauschen (durch HTML-Oberfläche) oder zu erweitern (unterschiedliche Anzeigen gleichzeitig - sinnvoll: keine Ahnung; möglich: ja).

Mich stört beim "klassischen MVC", wie man es im WWW an jeder Ecke erklärt bekommt, dass die Trennung zwischen GUI und Model nicht stark genug ist (vor allem die Richtung View --> Model).
Beipsiel (durchgezogener unterer Pfeil):
http://de.wikipedia.org/wiki/Model_View_Controller

Zusätzlich verwende ich immer einen Presenter zwischen View (GUI) und Controller, denn es gibt Code, der weder in den Controller noch in die View (Formularcode) gehört. Weiterer Vorteil: mein Controller muss die konkrete GUI (oder deren Anzahl) nicht kennen.

---

Was ich für wichtig und keine leichte Aufgabe halte, ist die richtige Positionierung der "echten Verbindungen". Es muss ja eine bidirektionale Verbindung aufgebaut werden (View <--> Model).
- Wer kennt wen ab wann.
- Sollen Verbindungen verändert werden (Edit-Feld soll ein den Wert eines anderes Business-Objektes repräsentieren)?

Luckie 19. Aug 2011 17:14

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von Phoenix (Beitrag 1118100)
Zitat:

Zitat von divBy0 (Beitrag 1118094)
Ok, damit sieht dein ButtonOnClick so aus oder?

Delphi-Quellcode:
procedure TForm1.ButtonAdditionClick(Sender: TObject);
begin
  FAddition.Zahl1 := StrToIntDef(EditZahl1.Text, 0);
  FAddition.Zahl2 := StrToIntDef(EditZahl2.Text, 0);
  FAddition.Addition;
  LabelErgebnis.Caption := IntToStr(FAddition.Ergebnis);
end;
Dies sollte doch eigentlich auch vermieden werden, wegen Spaghetticode.

Nein, das sollte deshalb vermieden werden, weil das Form um himmels willen niemals im Leben nicht die Klasse TAddition kennen darf.

So würde ich das aber auch lösen. Wie sähe denn deine Lösung aus?

shmia 19. Aug 2011 17:16

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Der Ruf nach mehr Einfachheit und weniger Schreibarbeit ist aber schon berechtigt.
Ich vereinfache dazu meine Klassen auf das Minimum:
Delphi-Quellcode:
type
  TCalculator = class
  public
    procedure Addition;
    procedure Subtraktion;
    Zahl1: Integer;
    Zahl2: Integer;
    Ergebnis: Integer;
  end;
Wenn diese Hilfsklasse sowieso nur im Kontext des Formulars benützt wird, wozu dann diese schreibträchtigen Properties einbauen?
Im Gegenzug scheue ich mich aber auch nicht, relativ kleine und einfache (Hilfs-)Klassen in meinem Formular zu benützen.
Ich ersetze Properties durch public Variablen aber nur dann, wenn ich mir sicher bin, dass ich die Klasse nur hier an Ort und Stelle benötige.
Klassen, die weiter ins Programm reichen werden weiterhin "anständig" programmiert.

Neumann 19. Aug 2011 17:19

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Für diesen einfachen Fall zu umständlich.

Delphi-Quellcode:
type
   TAddition = class
   private
     
   public
     function Add(wert1,wert2:integer; var Ergebnis:integer):boolean;
     
   end;
Implemaentation

Function Taddition.Add;
begin
  Ergebnis:=wert1+wert2;
  result:=(wert1<>0) and (wert2<>0);
end;
Result zeigt dann ob was sinnloses gemacht wurde oder kann auf einen Konvertierungsfehler hinweisen.

Die Sache mit privaten Feldern, Methoden sowie Properties macht nur dann Sinn, wenn man Werte zwischenspeichen will.

FredlFesl 19. Aug 2011 17:23

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Weiss nich, mit MVC hab ich mich noch nie beschäftigt.

Ich würde einfach dafür sorgen, das mein Formular nur den Code (Logik, Bedingungen etc.) enthält, der für die GUI erforderlich ist (Prototyping).

Die Funktionalität erfolgt komplett in eigenen Klassen. Ziel ist es, das jede GUI-Aktion mit genau einem Methodenaufruf abgebildet werden kann.

Bisher habe ich sehr selten einen Fall gehabt, bei dem die Funktionsklassen zwischendurch der GUI Bescheid geben müssen, außer vielleicht bei einem Fortschrittsbalken. Wenn das der Fall sein sollte, arbeite ich mit dem Vistor-Pattern, Callbacks oder Notification-Events (meistens Letzteres). Und wenn ich faul bin (oder mit Threads arbeite) gerne auch mit Windows-Messages. Dann läuft die Anwendung zwar nie unter Linux, aber WTF.

Es ist etwas altbacken und pragmatisch, aber schlußendlich das Resultat jahrzehntelangen Programmierens mit dem Zweck des einigermaßen effektiven Geldverdienens auf freiberuflicher Basis. Da ich große Unternehmen zufrieden gestellt habe, kann es so falsch nicht gewesen sein.

Der große Künstler bin ich nicht, aber dafür bin ich sehr schnell und meine Anwendungen sind mittlerweile sehr robust und leicht wartbar. Da ich zudem die für mich wichtigsten Gedanken vom 'Clean Code' verfolge, bin ich eigentlich mit meinem Gegurke zufrieden.

Wenn ich mich mal dabei ertappe, rumzufrickeln, schlägt mir das spätestens bei der ersten fundamentalen Anforderungsänderung gnadenlos ins Gesicht.
Zitat:

Zitat von shmia (Beitrag 1118112)
Ich ersetze Properties durch public Variablen aber nur dann, wenn ich mir sicher bin, dass ich die Klasse nur hier an Ort und Stelle benötige.

Ich verwende diese Form für 'data transfer objects', sonst nicht.

SebE 19. Aug 2011 17:25

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von Luckie (Beitrag 1118111)
Zitat:

Zitat von Phoenix (Beitrag 1118100)
Zitat:

Zitat von divBy0 (Beitrag 1118094)
Ok, damit sieht dein ButtonOnClick so aus oder?

Delphi-Quellcode:
procedure TForm1.ButtonAdditionClick(Sender: TObject);
begin
  FAddition.Zahl1 := StrToIntDef(EditZahl1.Text, 0);
  FAddition.Zahl2 := StrToIntDef(EditZahl2.Text, 0);
  FAddition.Addition;
  LabelErgebnis.Caption := IntToStr(FAddition.Ergebnis);
end;
Dies sollte doch eigentlich auch vermieden werden, wegen Spaghetticode.

Nein, das sollte deshalb vermieden werden, weil das Form um himmels willen niemals im Leben nicht die Klasse TAddition kennen darf.

So würde ich das aber auch lösen. Wie sähe denn deine Lösung aus?

(fett durch mich)
Dann hast du aber die Aufgabe nicht gelöst, um die es hier geht.

Allgemein:
Eine saubere Trennung erreicht man nur durch Abstraktion. Dass diese Mehraufwand beim Schreiben verursacht, sollte hier nicht das Thema sein.

Luckie 19. Aug 2011 17:34

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Na ja, Getter und Setter sind schon sinnvoll. Dann kann man bei einer Division prüfen, ob nicht der Divisor 0 ist und entsprechend eine Exception werfen. Gut könnte man jetzt auch bei der Division machen. Aber das ist ja sowieso nur hypothetischer Code und es geht ja eigentlich um die Bindung der Klasse an die GUI.

@SebE: Wie würdest du denn das lösen? Bringt doch mal konkrete Lösungsvorschläge.

SebE 19. Aug 2011 17:48

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
@Luckie:
Das steht doch in meinem ersten Beitrag auf Seite 1.

Ich mache eben aus 4 Zeilen Quellcode ~80 und verteile die dann auf 3 bis 4 Dateien.
Klingt schrecklich, aber wenn man ein Beispiel mit 500 Zeilen nimmt, wird der Overhead auch nicht mehr.
Bei dem wirklich winzigen Ausgangsprogramm würde ich auch dringlichst von MVC und Co abraten, da absolut überdimensioniert.
Aber wir wollen hier ja das Grundproblem im Allgemeinen lösen.

Wenn ich kurz abschweifen darf:
Wie würdet ihr folgendes lösen (Trennung spielt eine Rolle)?
Ihr habt eine Liste von gleichartigen Elementen, welche dynamisch erstellt werden und durch anklicken von Listeneinträgen (welche die Elemente für den User repräsentieren) ausgewählt werden. Dabei werden die Attribute der Elemente in visuellen Komponenten angezeigt (Edit, Combos, ...).

Also: beliebig mehrere Business-Objekte und nur eine Ein-/Ausgabe-Maske.
Welche zentrale Einheit übernimmt die Steuerung, was wann angezeigt wird.

EDIT: Vielleicht kann man sich vorstellen, dass wir das Ausgangsprogramm durch weitere Operationen (welche in der genannten Liste stehen) erweitern.
Wir haben sozusagen 4 Objekte (TAdditio, TSubtraction, TMultiplication, TDivision) aber nur 3 Edit-Felder.
Wir benötigen den Button nicht, da durch das Klicken in die Liste das Ergebnis sofort erechnet werden kann.

PS: "Sauber" in meinen Augen, wäre eine Lösung, welche den Operationslisten-SelectIndex nicht abfragt.

Stevie 19. Aug 2011 17:54

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von SebE (Beitrag 1118124)
Wenn ich kurz abschweifen darf:
Wie würdet ihr folgendes lösen (ob mit/ohne Trennung spielt erst einmal keine Rolle)?
Ihr habt eine Liste von gleichartigen Elementen, welche dynamisch erstellt werden und durch anklicken von Listeneinträgen (welche die Elemente für den User repräsentieren) ausgewählt werden. Dabei werden die Attribute der Elemente in visuellen Komponenten angezeigt (Edit, Combos, ...).

Die Properties des SelectedItem des Listen Controls an die anderen Controls binden. (siehe VirtualTreeviewSample oder Sample5 in meinem svn Repository)

Zitat:

Zitat von SebE (Beitrag 1118124)
EDIT: Vielleicht kann man sich vorstellen, dass wir das Ausgangsprogramm durch weitere Operationen (welche in der genannten Liste stehen) erweitern.
Wir haben sozusagen 4 Objekte (TAdditio, TSubtraction, TMultiplication, TDivision) aber nur 3 Edit-Felder.
Wir benötigen den Button nicht, da durch das Klicken in die Liste das Ergebnis sofort erechnet werden kann.

Entweder die entsprechenden Rechen routinen auf die Listen Items binden oder ein Objekt haben mit den 4 Operationen, welche abhängig vom ausgewählten Operator durchgeführt werden (das wär dann eher die ComboBox + Button Lösung)

SebE 19. Aug 2011 18:01

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Ja, dass ist eine gute Lösung.
Ich kenne diese aus C# in Verbindung mit WPF.
Geht das auch nativ? Ich bin leider schon einige Zeit aus Delphi raus.
Falls nicht: Hast du dennoch eine "hand-made-Lösung"?

Stevie 19. Aug 2011 18:06

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Nativ wie gesagt mit meiner Library ab Delphi 2010. Das Prinzip dahinter ist aber genauso mit Delphi 7 realisierbar (halt mit einigen Abstrichen bzgl der RTTI und Generics z.B.)

Eingangsbeispiel mal mit meinen DataBindings realisiert im Anhang

divBy0 19. Aug 2011 18:14

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Ob die Klasse jetzt trivial ist oder nicht sollte egal sein. Mir geht es einfach um die perfekte Trennung zwischen GUI und Logik und dafür sollte eine solche einfache Klasse doch ausreichen, oder brauchen wir ein "größeres" Beispiel.

Die Antworten zu dem Thema zeigen mir aber auch, dass es anscheinend nicht so einfach zu sein scheint bzw. die Herangehensweisen stark auseinander gehen.

Stevie 19. Aug 2011 18:21

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von divBy0 (Beitrag 1118133)
Die Antworten zu dem Thema zeigen mir aber auch, dass es anscheinend nicht so einfach zu sein scheint bzw. die Herangehensweisen stark auseinander gehen.

Mein Vorgehen lehnt sich halt an MVVM an, wie es WPF vormacht. Zwischen dem View und dem ViewModel gibt es keine Abhängigkeit, die View wird quasi einfach nur oben drauf gesteckt und mit den Bindings festgetackert. Ich will nicht sagen, dass das revolutionär in Delphi ist, aber ich hab es in der Form noch nicht gesehen, die meisten Ansätze laufen auf MVC/MVP hinaus. Und das ist mir nicht entkoppelt genug und produziert zu viel Code.

divBy0 19. Aug 2011 18:27

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
@Stevie: In deinem Beispiel fehlt DSharp... Ist das deine Binding-Lösung? Wo kann ich mir die Unit runterladen?

SebE 19. Aug 2011 18:31

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
@Stevie:
Die Trennung ist wirklich stark, da diese komplett von der "Framework-Magic" übernommen wird.

Meine Lösung entspricht weitgehend meiner Lösung auf Seite 1 mit dem Zusatz:
Delphi-Quellcode:
procedure List.SelectIndexChange(...);
begin
  TOperation(Form1.List1.SelectedItem).SetVisualComponent(MyVisualAttributes);
end;

// ---

type
  TVisualAttributes = class
    op1, op2: TEdit;
    result: TEdit;
    [...]
  end;
TAddition, TSubtraction, ... sind von TOperation abgeleitet.
In TOperation.SetVisualComponent(vc) wird die visuelle Komponente im Business-Objekt ersetzt und es werden alle ChangeEvents aufgerufen:

Delphi-Quellcode:
procedure TOperation.SetVisualComponent(vc: TVC);
begin
self.visualComponent := vc;

if vc <> nil then begin
  resultChangeEvent(...); // hier muss man sich überlegen,
                          // ob die Werte (Zahl1, Zahl2) vorhanden sind bzw. sein sollen.
                          // Sonst: nach SetVisualComponent
                          // TOperation(Form1.List1.SelectedItem).Execute aufrufen
  end;
end;

Stevie 19. Aug 2011 18:35

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von divBy0 (Beitrag 1118138)
@Stevie: In deinem Beispiel fehlt DSharp... Ist das deine Binding-Lösung? Wo kann ich mir die Unit runterladen?

Hab mal meine Sig angepasst ;)

SebE 19. Aug 2011 18:39

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Mein Vorgehen lehnt sich halt an MVVM an, wie es WPF vormacht. Zwischen dem View und dem ViewModel gibt es keine Abhängigkeit, die View wird quasi einfach nur oben drauf gesteckt und mit den Bindings festgetackert. Ich will nicht sagen, dass das revolutionär in Delphi ist, aber ich hab es in der Form noch nicht gesehen, die meisten Ansätze laufen auf MVC/MVP hinaus. Und das ist mir nicht entkoppelt genug und produziert zu viel Code.
Dass ich auch der Meinung bin, dass MVC nicht genug entkoppelt, habe ich bereits geschrieben - man muss eben seine eigenen Architekturen (-Muster) erstellen.

In C# würde man die Bindings mit XAML herstellen.
Mir persönlich geht das aber zu weit - ich möchte im Code nachvollziehen können, was wann wo verbunden wird.
Das "schlimmste" ist in meinen Augen, dass man Methoden, Objekte (analog Properties) mit Zeichenketten ausweist.
Delphi-Quellcode:
TBinding.Create(add, 'Zahl1', MainForm.edNumber1, 'Text');
Delphi-Quellcode:
DoPropertyChanged('Ergebnis');
Es werden die Elemente der Programmiersprache nicht mehr als Symbole vestanden bzw. angesprochen.
Kann ich mich nicht mit anfreunden.
Aber die Idee dahinter finde ich super.

Stevie 19. Aug 2011 18:55

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von SebE (Beitrag 1118143)
Das "schlimmste" ist in meinen Augen, dass man Methoden, Objekte (analog Properties) mit Zeichenketten ausweist.
Es werden die Elemente der Programmiersprache nicht mehr als Symbole vestanden bzw. angesprochen. Kann ich mich nicht mit anfreunden.

Absolut korrekt. Das ist auch mein persönlich größter Kritikpunkt - daher ja auch mein sehnlicher Wunsch nach property references.

Übrigens auch in .Net wird mit strings gearbeitet. Der Pluspunkt gegenüber der Delphi Lösung ist halt, dass das XAML auch geprüft wird. Aber wenn du beim NotifyPropertyChanged deine Property falsch schreibst, biste genauso gekniffen (außer du nutzt Prism, wo das durch das keyword notify geregelt wird :love:)

Phoenix 19. Aug 2011 18:56

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von SebE (Beitrag 1118143)
Mir persönlich geht das aber zu weit - ich möchte im Code nachvollziehen können, was wann wo verbunden wird.

Aber genau darum geht das doch das entkoppeln. Das es eben genau nicht mehr im Code steht sondern lediglich noch Deklarativ geschieht.

Wenn Du das im Code machst, produzierst Du zum einen wieder viel mehr Code (der neue Fehler enthalten kann), zum anderen verlierst Du genau die Flexibilität, die solche Binding-Mechanismen gerade erlauben sollen.

Der Trick ist doch genau der, Elemente austauschen zu können, die nichts voneinander wissen. Code muss zwangsläufig auf beiden Seiten die Details kennen, um sie aneinander zu koppeln. Deklaratives binding hingegen erlaubt es Dir, sowohl die View als auch das Model auszutauschen, ohne dass es hier zu einer Code-Änderung an irgend einer anderen Stelle kommen muss.

Das ist ja auch genau das Problem an MVC: Der Controller muss View und Model kennen, um sie aneinander zu docken.
MVVM-Patterns hingegen abstrahieren selbst das Model (reine Business-Logik) noch einmal mit UI-Logik (Erlaubte Aktionen, Dargestellte Werte etc.), und nur die View bindet sich deklarativ ans ViewModel.

Deswegen funktioniert auch sowas wie das hier: http://jsfiddle.net/rniemeyer/aDahT/ mit so ungeheuer wenig Code.

bernerbaer 19. Aug 2011 19:13

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
OOP bis zum "Gehtnichtmehr"! Delphi ist für mich ein RAD-Tool und OOP ist kein Dogma. Es gibt nun einfach Dinge, die im praktischen Entwickleralltag sinnlos sind. Eine strikte Trennung von GUI und Anwendungslogik ist in Delphi nicht immer zwingend und verhindert manchmal sogar die Übersichtlichkeit und Lesbarkeit des Codes bei kleinen Projekten. Leider habe ich den Link nicht mehr gefunden, aber irgendwer hat mal ein Horrorbeispiel in OOP für ein Hello-Word Programm geschrieben (vielleicht kennt ja hier jemand das Beispiel). Also meine Ansatz: Auslagerung in externe Klassen nur dann wenn es Sinn macht und/oder die Lesbarkeit des Codes verbessert.

stahli 19. Aug 2011 19:24

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Das stimmt, aber um so größer und komplexer ein Projekt werden wird, um so wichtiger wird eine Trennung.
Es ist eine Frage des Frameworks, wie komfortabel die Bindung der beiden Ebenen realisiert werden kann.
Die Erstellung der Datenebene und der GUI-Ebene für sich sollte jeweils einfacher und übersichtlicher werden.

SebE 19. Aug 2011 19:27

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von Phoenix (Beitrag 1118148)
Aber genau darum geht das doch das entkoppeln. Das es eben genau nicht mehr im Code steht sondern lediglich noch Deklarativ geschieht.

Wenn Du das im Code machst, produzierst Du zum einen wieder viel mehr Code (der neue Fehler enthalten kann), zum anderen verlierst Du genau die Flexibilität, die solche Binding-Mechanismen gerade erlauben sollen.

(fett durch mich)
Punkt 1: stimmt absolut.
Punkt 2: Ich weiß gerade nicht, was ich von Hand nicht machen könnte, was mir Bindings erlauben.

Zitat:

Zitat von Phoenix (Beitrag 1118148)
Der Trick ist doch genau der, Elemente austauschen zu können, die nichts voneinander wissen. Code muss zwangsläufig auf beiden Seiten die Details kennen, um sie aneinander zu koppeln. Deklaratives binding hingegen erlaubt es Dir, sowohl die View als auch das Model auszutauschen, ohne dass es hier zu einer Code-Änderung an irgend einer anderen Stelle kommen muss.

Beim Verbinden muss immer Information offen gelegt werden.
Beim Binding muss man angeben, welche Property verwendet werden soll.
Ich mache das mit Abstraktionen, die das - und nur das - enthalten, was der Benutzer der konkreten Implementierung wissen darf.
Schnittstellen muss man immer angeben.

Klar ist es mehr Aufwand, aber so viel auch wieder nicht: nach dem Anpassen der Schnittstelle, die richtigen Objekte erzeugen.
Vorteil: der Compiler sagt mir, wenn ich falsche Informationen beziehen möchte.

Zitat:

Zitat von Phoenix (Beitrag 1118148)
Das ist ja auch genau das Problem an MVC: Der Controller muss View und Model kennen, um sie aneinander zu docken.

(fett durch mich)

Dass der Controller das Model kennen muss, ist eigentlich kein Problem (meine Controller rufen nur Model-Methoden auf).
Für den markierten Teil wird ein Presenter eingefügt, von dem der Controller auch nur die Abstraktion kennt.

Meine Architektur:
Model: klar!
Controller: wählt zu Beginn den Presenter/die View aus; bestimmt, was die Anwendung kann; leitet Anweisungen an Model
Presenter: UI-Logik (Weiterleiten von Eingaben); Formatierung der Ausgabe ;Erzeugen von UI-Objekten auf Anfrage des Controllers (auf Anfrage des Models)
View: Leitet Eingabe-Events an den Presenter weiter; sieht trollig aus

divBy0 19. Aug 2011 19:30

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von Stevie (Beitrag 1118132)
Nativ wie gesagt mit meiner Library ab Delphi 2010. Das Prinzip dahinter ist aber genauso mit Delphi 7 realisierbar (halt mit einigen Abstrichen bzgl der RTTI und Generics z.B.)

Eingangsbeispiel mal mit meinen DataBindings realisiert im Anhang

Das Beispiel funktioniert bei mir aber nicht. Der Button löst keine Addition aus.

Memory Leaks gibt's auch:

---------------------------
Unexpected Memory Leak
---------------------------
An unexpected memory leak has occurred. The unexpected small block leaks are:



1 - 12 bytes: Unknown x 1

21 - 28 bytes: TList<System.TMethod> x 1

29 - 36 bytes: TEventHandlerInstance x 1

45 - 52 bytes: TEventHandler<DSharp.Bindings.TPropertyChangedEven t> x 1

69 - 76 bytes: TNotificationHandler<TEventHandler<DSharp.Bindings .TPropertyChangedEvent>> x 1



The sizes of unexpected leaked medium and large blocks are: 52012


---------------------------
OK
---------------------------

Stevie 19. Aug 2011 19:31

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von bernerbaer (Beitrag 1118149)
OOP bis zum "Gehtnichtmehr"! Delphi ist für mich ein RAD-Tool und OOP ist kein Dogma. Es gibt nun einfach Dinge, die im praktischen Entwickleralltag sinnlos sind. Eine strikte Trennung von GUI und Anwendungslogik ist in Delphi nicht immer zwingend und verhindert manchmal sogar die Übersichtlichkeit und Lesbarkeit des Codes bei kleinen Projekten. Leider habe ich den Link nicht mehr gefunden, aber irgendwer hat mal ein Horrorbeispiel in OOP für ein Hello-Word Programm geschrieben (vielleicht kennt ja hier jemand das Beispiel). Also meine Ansatz: Auslagerung in externe Klassen nur dann wenn es Sinn macht und/oder die Lesbarkeit des Codes verbessert.

Wer schonmal an einem Projekt gearbeitet hat, wo trotz Mockups plötzlich die Entscheider der Meinung war, dass der Workflow für den Benutzer ja so mal garnicht geht und man das ganze doch ganz anders bedienen und darstellen muss, wird geflucht haben, wenn er dann überall in irgendwelchen Control Events rumfrickeln durfte, um das alles anzupassen, wenn er nicht strikt getrennt hat.

SebE 19. Aug 2011 19:34

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von bernerbaer (Beitrag 1118149)
OOP bis zum "Gehtnichtmehr"! Delphi ist für mich ein RAD-Tool und OOP ist kein Dogma. Es gibt nun einfach Dinge, die im praktischen Entwickleralltag sinnlos sind. Eine strikte Trennung von GUI und Anwendungslogik ist in Delphi nicht immer zwingend und verhindert manchmal sogar die Übersichtlichkeit und Lesbarkeit des Codes bei kleinen Projekten. Leider habe ich den Link nicht mehr gefunden, aber irgendwer hat mal ein Horrorbeispiel in OOP für ein Hello-Word Programm geschrieben (vielleicht kennt ja hier jemand das Beispiel). Also meine Ansatz: Auslagerung in externe Klassen nur dann wenn es Sinn macht und/oder die Lesbarkeit des Codes verbessert.

(fett von mir)

Der Thread heißt "Trennung von GUI und Logik".
Wenn du uns zeigen kannst, wie man ohne Vererbung diese gewünschte Trennung vollziehen kann, bin ich sofort ruhig.
Bis dahin sage ich: Wieder am Thema vorbei.
Was nützt es dem TE, wenn er es wissen will, oder wirklich benötigt?
Ein Problem wegzureden, löst es nicht.

Zitat:

OOP bis zum "Gehtnichtmehr"!
Ein Muss, wenn du mit C# programmierst!

Stevie 19. Aug 2011 19:35

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von divBy0 (Beitrag 1118153)
Zitat:

Zitat von Stevie (Beitrag 1118132)
Nativ wie gesagt mit meiner Library ab Delphi 2010. Das Prinzip dahinter ist aber genauso mit Delphi 7 realisierbar (halt mit einigen Abstrichen bzgl der RTTI und Generics z.B.)

Eingangsbeispiel mal mit meinen DataBindings realisiert im Anhang

Das Beispiel funktioniert bei mir aber nicht. Der Button löst keine Addition aus.

Memory Leaks gibt's auch

Liegt wohl daran, dass im svn nicht die aktuellste version liegt, ich bin gerade dabei neuste Änderungen einzuchecken. Dazu gehört u.a. ActionBinding. Versuchs später oder morgen früh nochmal.

Zitat:

Zitat von bernerbaer (Beitrag 1118149)
OOP bis zum "Gehtnichtmehr"! Delphi ist für mich ein RAD-Tool und OOP ist kein Dogma. Es gibt nun einfach Dinge, die im praktischen Entwickleralltag sinnlos sind. Eine strikte Trennung von GUI und Anwendungslogik ist in Delphi nicht immer zwingend und verhindert manchmal sogar die Übersichtlichkeit und Lesbarkeit des Codes bei kleinen Projekten. Leider habe ich den Link nicht mehr gefunden, aber irgendwer hat mal ein Horrorbeispiel in OOP für ein Hello-Word Programm geschrieben (vielleicht kennt ja hier jemand das Beispiel). Also meine Ansatz: Auslagerung in externe Klassen nur dann wenn es Sinn macht und/oder die Lesbarkeit des Codes verbessert.

Nicht böse gemeint, aber du gehörst scheinbar auch zu der Sorte Delphi Entwickler, die meint, nur weil man Buttons, Edits und Listboxen aufs Form streuen kann und mitm Doppelklick die nötige Logik ins Event klimpern kann, muss man das auch so machen und alles andere wäre dogmatisch. Natürlich kann man auch nen Hello World Programm over engineeren, aber genau dafür sind nunmal simple Beispiele da. Wer's an sowas nicht lernt, dem brauchste garkein echten Usecase geben.

divBy0 19. Aug 2011 19:35

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Also ich will es unbedingt wissen und benötigen wird man es so oder so... :mrgreen:

stahli 19. Aug 2011 19:38

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von SebE (Beitrag 1118156)
Der Thread heißt "Trennung von GUI und Logik".
Wenn du uns zeigen kannst, wie man ohne Vererbung diese gewünschte Trennung vollziehen kann, bin ich sofort ruhig.
Bis dahin sage ich: Wieder am Thema vorbei.

Was meinst Du damit?

SebE 19. Aug 2011 19:42

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Also ich will es unbedingt wissen und benötigen wird man es so oder so...
Dann hast du die Wahl: zwei Lösungen wurden vorgestellt (mehr kenne ich auch nicht):
- Nativ ohne Framework-Einsatz (mein Code sollte einen Einblick gegeben haben, wo die Knackpunkte liegen)
- "magische Lösung", bei der vieles versteckt wird und das Projekt schön klein bleibt.

Wenn du es unbedingt (aus Bildungsgründen) zu Fuß machen möchtest, schaue dir folgende Pattern an:
Observer, Visitor, Proxy

Progman 19. Aug 2011 19:43

AW: Trennung von GUI und Logik, wie geht ihr vor?
 
Zitat:

Zitat von Stevie (Beitrag 1118154)
Wer schonmal an einem Projekt gearbeitet hat, wo trotz Mockups plötzlich die Entscheider der Meinung war, dass der Workflow für den Benutzer ja so mal garnicht geht und man das ganze doch ganz anders bedienen und darstellen muss, wird geflucht haben, wenn er dann überall in irgendwelchen Control Events rumfrickeln durfte, um das alles anzupassen, wenn er nicht strikt getrennt hat.

Aber was ist mit einem solchen "dreiteiligen" (ich nenns mal so) Programmieren, wenn 1 Woche vor Deadline der Entscheider meint, dass auf der Oberfläche noch einige Bedienelemente sein müssen, die dann Fenster erscheinen lassen, wo der User was eingeben/einstellen kann? In der normalen RAD-Programmierung geht das ruckzuck. Nach diesem "Model" müsste ich alle drei Teile erweitern und zusehen, dass ich die auch exakt wieder verbinde. Resultat wäre doch sicherlich ein Code-Chaos, wo man bei eventuell nötigen Änderungen gar nicht mehr durchblickt :lol:
Ich programmiere seit über 25 Jahren und bin der Meinung, dass hier extremst ubers Ziel hinausgeschossen wird. Das riecht verdammt nach OOP-Fetischismus *gg*


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:15 Uhr.
Seite 1 von 5  1 23     Letzte »    

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