Einzelnen Beitrag anzeigen

Maekkelrajter

Registriert seit: 8. Mär 2017
Ort: Köln
118 Beiträge
 
Delphi 11 Alexandria
 
#1

Trennung von GUI und Logik

  Alt 28. Apr 2019, 15:17
Seit vielen Jahren, um nicht zu sagen Jahrzehnten programmiere ich hobbymäßig und vorwiegend für den Eigenbedarf. Das begann 1987 mit dem 64er (Basic, Assembler). Es folgte der Amiga (Basic, GFA-Basic, Assembler) und schließlich diverse PCs ( Assembler,TP 6 , BP 7, Delphi 1, 2, 4, 10). Meist waren das kleinere Anwendungen, für die natürlich vorher kein Konzept erstellt wurde, sondern nach Erstellung der Infrastruktur (GUI, IO-Routinen) mit möglichst wenig Zeitaufwand die gewünschte Funktionalität implementiert wurde. Immer wieder kam es allerdings vor, dass gerade solche q&d hingerotzte Sachen dann im Laufe der Zeit immer weiter wuchsen, um nicht zu sagen wucherten. Dabei versuchte ich natürlich immer, gewisse Mindeststandards einzuhalten, was Strukturierung und Modularisierung betraf, sodass ich auch nach Jahren weitgehend die Übersicht behielt. Da ich das Ganze, wie gesagt, hobbymäßig betreibe, konnte ich auch viel Zeit mit 'Refactoring' verbringen, wobei sowohl GUI als auch der Programmcode immer wieder optimiert und 'verschönert' , soll heißen 'profimäßiger' ( oder was ich dafür hielt) gestaltet wurde. Dennoch fürchte ich, ein professioneller Entwickler würde beim Anblick mancher meiner Sources einen Schreikrampf erleiden, aber damit kann ich leben. Denn für mich ist der Hauptzweck erfüllt: Die Funktionalität ist wunschgemäß, die Optik ist ansprechend und das GUI funktional und gut bedienbar. Ich kann das Programm nutzbringend für mich einsetzen und nicht nur IT-Laien damit schwer beeindrucken
Wie sicher mancher schon ahnt, bin ich auch nicht der Großmeister der OOP.
Daher rührt auch mein aktuelles Problem. In meinem aktuellen Projekt möchte ich eine weitgehende Trennung von GUI und Logik durchführen. Mich stört vor allem die grotesk aufgeblähte Deklaration des Hauptformulars, das einen großen Teil der Logik in den OnClick - Handlern bzw. deren Implementation enthält. Bei eienem großen Teil von ihnen ließ sich der Code leicht in separate Units bzw. Klassen auslagern, was das Ganze schon erheblich übersichtlicher macht. Aber jetzt sollen doch Nägel mit Köpfen gemacht und sämtliche Logik aus der Mainform - Deklaration und -Implementierung entfernt werden.
Ein Problem sind für mich die Routinen, die während der oft sekunden- oder gar minutenlangen Dauer ihrer Ausführung auf Komponenten des Hauptformulars zugreifen und etwa Zählerstände in TLabels oder Textausgaben in TMemos aktualisieren, was als Lebenszeichen der Anwendung, quasi als Fortschritts-Anzeige, und auch zur Information des Anwenders unerläßlich ist.

Beispiel:
Delphi-Quellcode:
unit DemoForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Memo1: TMemo;
    // 128 Deklarationen
    procedure Button1Click(Sender: TObject);
    // 100 Event- Handler
  private
    { Private-Deklarationen }
    // 116 Deklarationen (schon teilweise reduziert)
  public
    { Public-Deklarationen }
    // 2 Deklarationen
  end;

var
  Form1: TForm1;

implementation


//Beispiel: Durchsuche eine iTunes Mediathek mit 10000 Tracks nach Tracks ohne Albumcover (Pseudocode)

procedure TForm1.Button1Click(Sender: TObject);
  var i: Integer;
begin
  {
  for i := 1 to 10000 do
    begin                                                                                                                               
      label1.caption:= inttostr(i);                                              // erhöhe den Zählerstand im Label                                     
      If Track(i)  ohne Albumcover Then Memo1.lines.add(Titel +  Artist + Album) // Wenn einer gefunden, Track (Titel, Artist, Album) im Memo ausgeben
    end;
  }

end;

end.
Wie schaffe ich es nun, den Code aus dem OnClick - Handler auszulagern und dennoch Zugriff auf Form1 zu ermöglichen?

Auf globale Instanz - Variable Form1 zugreifen?
Jeder ausgelagerten Prozedur/ Methode Form1 als Parameter übergeben?
Ausgelagerte Methoden in Klasse zusammenfassen und in deren Constructor Form1 einer Feldvariablen (z.B. 'FMainform') zuweisen?
Windows-Messages?
Oder was ganz anderes?

Was käme da als halbwegs saubere Lösung in Frage? (außer alles in die Tonne kloppen und von vorne anfangen)

Gruß LP
  Mit Zitat antworten Zitat