Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Designstruktur eines Funktionsgenerators (https://www.delphipraxis.net/181194-designstruktur-eines-funktionsgenerators.html)

Headbucket 24. Jul 2014 07:33

Designstruktur eines Funktionsgenerators
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo zusammen,

ich bin gerade dabei einen Funktionsgenerator zu entwerfen. Dabei kann ich mich leider nicht wirklich entscheiden, wie ich ihn am elegantesten aufbaue. Es soll später mal ein solides Produkt werden und vllt auch hier und da mal um Funktionen erweitert werden. Von daher muss die Struktur von Anfang an klar sein.

Ich habe mein jetziges grobes Design mal unten angehängt. Es entspricht der Designvariante mit einem PageControl.
Ganz grob die Funktionen:
Es soll verschiedene Modi (Wellenformen) geben, wie z.B. Sinus, Rauschen, Sweep, usw. Je nach gewählter Wellenform sollen natürlich unterschiedliche Regler angezeigt werden, wie z.B. Amplitude, Frequenz und Offset für Sinus. Start- und Endfrequenz für Sweep, usw. Ebenso soll sich auch das "Display" und die Anzeigen darin verändern.
Man kann die Parameter sowohl im Display (sind Editfelder), wie auch über die Regler unter dem Display ändern. Wenn ich im Display also z.B. 1000 Hz einstelle soll der Regler auch auf 1000 Hz rutschen.

Designvarianten, die mir bisher in den Kopf gekommen sind:

Mit Hilfe von PageControl/Tabs
Beim der Wahl eines Modi wird ein bestimmtes Tab unter dem Display aktiviert. Die Reiter des PageCOntrol werden mit Hilfe von "TabVisible := false" ausgeblendet. Das gleiche könnte ich nun auch mit dem Display machen.
Vorteil: Ich kann alles im Design-Editor entwickeln.
Nachteil: Es könnte irgendwann eventuell etwas unübersichtlich werden

Mit Hilfe von vielen Frames
Ich erstelle für jeden Modi jeweils ein Frame für die Anzeige und für die Einstellungen und lade diese beim Aufruf des Modi.
Vorteil: Es wird alles etwas besser getrennt und vllt übersichtlicher?
Nachteil: Ich habe für einen Dialog im Programm sehr viele Frames, was das Gesamtprojekt sehr aufbläht.

Alle Elemente dynamisch erzeugen
Ich lasse den Design-Editor links liegen und erzeuge alles dynamisch mit Quellcode. Hier könnte ich natürlich auch alles in eine Unit packen oder in viele verschiedene.
Vorteil: Alles ist ordentlich angeordnet
Nachteil: unübersichtlicher Programmcode

Wahrscheinlich gibt es auch noch ein paar weitere Methoden, an welche ich im Moment nicht denke.
Mich würde nun einfach interessieren, wie ihr ein solches Programm entwickeln würdet. Wieviele Units würdet ihr verwenden? Wie würdet ihr das Design umsetzen?
Es kann halt gut sein, dass noch der ein oder andere Modi dazukommt. Hier muss ich also flexibel bleiben.

Vielen Dank schonmal!

Headbucket

Sir Rufo 24. Jul 2014 08:54

AW: Designstruktur eines Funktionsgenerators
 
Warum sollte das Projekt mit Frames aufgebläht werden?

Im Gegenteil, du entzerrst und lässt Luft ab wenn du nicht alles in ein Formular packst.

Wenn sich bestimmte Teile auf allen Frames wiederholen, dann bau dir ein Basis-Frame von dem du die anderen ableitest.

PS: Zudem würde ich jede Form und jeden Frame immer von einer/m Basis-Form/Frame ableiten.

Dejan Vu 24. Jul 2014 09:00

AW: Designstruktur eines Funktionsgenerators
 
Tabsheets sind schon mal blöd, denn ab ca. 7 Funktionen wird das schnell unübersichtlich. Besser ist hier eine TreeView (auf der linken Seite) und Frames auf der rechten Seite. Pro Knoten ein Frame. Nun kannst Du deine Funktionen auch gruppieren, d.h. die Übersichtlichkeit erhöhen.

Die einzelnen Frames kannst du dann individuell programmieren, was die Übersichtlichkeit erhöht.

Ich würde allerdings noch einen Schritt weiter gehen, und jedem Funktionsgenerator eine Klasse spendieren, wobei jede Klasse eine Liste von Parametern exportiert. Die Parameter sind z.B. vom Typ 'Schalter/Boolean' und 'Wert/Double'. Vielleicht noch zusätzlich ein Auswahlfeld (Funktion 'A', 'B', 'C', 'D'). Ein einziges Frame übernimmt die Darstellung der Parameterliste, z.B. als untereinanderliegende Controls (CheckBox, Combo/Radiogroup und Slider/Eingabefeld). Da jeder Parameter auch Eigenschaften wie Min, Max, Caption, Default etc. exportiert, kannst Du das sehr elegant und vor allen Dingen uniform darstellen. Bei der individuellen Programmierung in Frames passiert es hingegen schnell, das sich das Layout der einzelnen Regler doch unterscheidet (weil man irgendwo eine Verbesserung vornimmt und die dann nicht auf alle Frames ausweitet z.B.)

Das Schöne an so einem Entwurf ist, das die Klasse selbst seine Position innerhalb des Treeviews angeben könnte. Weiterhin kannst Du jede Klasse in eine DLL packen und so deine Applikation beliebig -auch nachträglich- erweitern.

Statt mit abstrakten Klassen würde ich das mit Interfaces realisieren, dann könnte man weitere Funktionen auch mit anderen Programmiersprachen zur Verfügung stellen, so etwa:
Delphi-Quellcode:
Type
  IParameter = interface
    Property Caption : String;
    Property Value : OleVariant read get_Value write set_Value;
  end;

  IBooleanParameter = interface (IParameter)
  end;

  ISelectionParameter = interface (IParameter)
    Property SelectionList : IList read get_SelectionList;
  end;

  IDoubleParameter = interface (IParameter)
    Property Min : Double read...;
    Property Max : Double read ...;
    Property Default : Double read...;
  end;

  IFunction = interface
    property Name : String;
    property Parameter : IParameterList;
    function Value (X : Double) : Double;
  end;
Syntaktisch 100% ist das nicht, weil ich lange nichts mit Delphi gemacht habe. Als abstrakte Klasse geht es auch, nur dann bist Du an Delphi gebunden (was ja nicht per se schlecht ist).

Zitat:

Zitat von Sir Rufo (Beitrag 1266511)
Warum sollte das Projekt mit Frames aufgebläht werden?

Weil man doch nicht alles in eine Form schmeißen soll. SRP, OCP. Frames sind das visuelle Pendant zu einer Klasse. Pro Funktion eine Klasse => pro Funktion ein Frame. Stringentes Design, finde ich.

Ich sehe das eher als Übung, denn als ausgewachsenens Projekt. Die von mir vorgeschlagene Architektur ist etwas überkandidelt für diese Aufgabe, aber das Pattern eines erweiterbaren Pluginsystems sowie das Pattern eines Parameterlistenrenderers (der, der die Controls bastelt) ist für viele Aufgabenstellungen geeignet.

Ebenso wie das stringente Arbeiten mit Frames (Frame <-> Klasse).

Finde ich.

Sir Rufo 24. Jul 2014 10:03

AW: Designstruktur eines Funktionsgenerators
 
Zitat:

Zitat von Dejan Vu (Beitrag 1266512)
Zitat:

Zitat von Sir Rufo (Beitrag 1266511)
Warum sollte das Projekt mit Frames aufgebläht werden?

Weil man doch nicht alles in eine Form schmeißen soll. SRP, OCP. Frames sind das visuelle Pendant zu einer Klasse. Pro Funktion eine Klasse => pro Funktion ein Frame. Stringentes Design, finde ich.

Mein Kommentar war als Gegenfrage zur Aussage:
Zitat:

Zitat von Headbucket (Beitrag 1266500)
Mit Hilfe von vielen Frames
Ich erstelle für jeden Modi jeweils ein Frame für die Anzeige und für die Einstellungen und lade diese beim Aufruf des Modi.
Vorteil: Es wird alles etwas besser getrennt und vllt übersichtlicher?
Nachteil: Ich habe für einen Dialog im Programm sehr viele Frames, was das Gesamtprojekt sehr aufbläht.

Und dann schrieb ich weiter dazu:
Zitat:

Zitat von Sir Rufo (Beitrag 1266511)
Im Gegenteil, du entzerrst und lässt Luft ab wenn du nicht alles in ein Formular packst.


Namenloser 24. Jul 2014 10:29

AW: Designstruktur eines Funktionsgenerators
 
Also ich würde auf jeden Fall für jeden Funktionsgeneratortyp (Sinus, Rechteck, wasauchimmer) eine Klasse erstellen. So kann man das dann schön erweitern. Zu jeder dieser Klassen sollte es jeweils eine GUI-Schwesterklasse geben, die z.B. von TControl abgeleitet ist und die ganzen Steuerelemente beinhaltet. Man kann die Steuerelemente im Code erzeugen, oder natürlich auch ein im Designer erstelltes Frame zurückliefern. Ich selber habe unter Delphi bisher eher von Hand von TCustomControl abgeleitet und die Steuerelemente dann per Code erzeugt, weil ich daaaamals 2006 unter Turbo Delphi mal Frames ausprobiert hatte und irgendwie Probleme mit Windows-Scroll-Messages hatte, die nicht ankamen. Seitdem habe ich Frames dann gemieden... (zumal mir nach wie vor keine aktuellere Delphi-Version zur Verfügung stand/steht... in neueren Versionen gibt es das Problem glaube ich nicht mehr, unter Freepascal ebenfalls nicht).

Generell orientere ich mich immer am MVC-Pattern. Ist für mich aber auch kein Dogma... Ich finde es hier z.B. schwierig, sinnvoll in drei Klassen zu unterteilen und würde, wie bereits beschrieben, nur eine Unterteilung in zwei Klassen vornehmen. Die gleiche Entscheidung hab ich bei unserem (ehemaligen) Praktikumsprojekt, das ich jetzt noch weiterentwickeln darf, übrigens auch gemacht, und bisher hat sich das bewährt.

Man kann es natürlich auch so wie Dejan Vu machen. Ich denke, das lohnt sich vor allem, wenn man vorher schon weiß, dass man es nur mit ganz bestimmten Parametertypen zu tun haben wird. Wenn die „Plugins“ dagegen sehr unterschiedliche Arten von Einstellungen haben, besteht imo die Gefahr, dass man Ende tendenziell die komplette VCL in Form von Interfaces neu erfindet.

Dejan Vu 24. Jul 2014 16:07

AW: Designstruktur eines Funktionsgenerators
 
Zitat:

Zitat von Sir Rufo (Beitrag 1266521)
Mein Kommentar war als Gegenfrage zur Aussage:

[x] Ich werde zu alt.

Headbucket 25. Jul 2014 07:21

AW: Designstruktur eines Funktionsgenerators
 
Vielen Dank, dass ihr euch die Zeit genommen habt, mir zu antworten.

Dann hat sich mein Gefühl mit den Tabsheets also bestätigt. So richtig wohl habe ich mich damit nämlich nicht gefühlt, weshalb ich den Thread ja überhaupt erst erstellt habe. So werde ich die Sache wohl mit separaten Klassen in verschiedenen Frames umsetzen. Wenn es Sinn macht, werde ich diese von Basisframes ableiten.

Ich werde mir auch nochmal die Umsetzung mit Interfaces anschauen, was ja von Dejan Vu vorgeschlagen wurde. Hier bin ich allerdings noch nicht ganz fit, weshalb ich das wohl mal nebenbei als Übung machen werde.

MVC habe ich mir auch mal als Lesezeichen gespeichert und werde es mir bei nächster Gelegenheit mal anschauen.

Danke nochmal und schon mal ein schönes Wochenende!

Grüße
Headbucket

Dejan Vu 25. Jul 2014 07:41

AW: Designstruktur eines Funktionsgenerators
 
Zitat:

Zitat von Namenloser (Beitrag 1266529)
Wenn die „Plugins“ dagegen sehr unterschiedliche Arten von Einstellungen haben, besteht imo die Gefahr, dass man Ende tendenziell die komplette VCL in Form von Interfaces neu erfindet.

Das Plugin-Konzept bildet das Model ab, nicht die View. Insofern kommt die VCL hier nicht ins Spiel. Bei den Einstellmöglichkeiten ist die Anzahl der abzubildenden Datentypen/Einstellmöglichkeiten überschaubar
  • Zahlenwert
  • Boolean
  • Text
  • Einfachauswahl
  • Mehrfachauswahl
  • Komplexe Daten/Record
Wesentlich mehr fällt mir hier nicht ein. Beim letzten Punkt muss man etwas komplexer werden, da dann auch die Editoren über ein erweiterbares Pluginsystem erstellt werden. Ist aber alles keine Hexerei.

Namenloser 25. Jul 2014 12:53

AW: Designstruktur eines Funktionsgenerators
 
Ich habe das so verstanden, dass du zur Laufzeit automatisch die View dazu generieren willst, also für jede Text-Eigenschaft ein Edit etc.

Wenn es nicht so gemeint war, sehe ich aber auch nicht wirklich den Vorteil, denn dann kann ich doch von der View genau so gut direkt auf die Properties des Models zugreifen.

Dejan Vu 25. Jul 2014 14:14

AW: Designstruktur eines Funktionsgenerators
 
Zitat:

Zitat von Namenloser (Beitrag 1266655)
Ich habe das so verstanden, dass du zur Laufzeit automatisch die View dazu generieren willst, also für jede Text-Eigenschaft ein Edit etc.

Wenn es nicht so gemeint war, sehe ich aber auch nicht wirklich den Vorteil, denn dann kann ich doch von der View genau so gut direkt auf die Properties des Models zugreifen.

Doch doch, das war schon so gemeint. Der Renderer besteht dann aus 5 (6, wenn man komplex wird) kurzen IF-Anweisungen. Nur programmierere ich die VCL nicht neu.

Delphi-Quellcode:
Function GetControlForParameter (aParameter : IParameter) : TControl;
Begin
  if aParameter is IBooleanParameter then
    result := TCheckBox.Create(nil)
  else if aParameter is IDoubleParameter then begin
    result := TScrollBar.Create(nil);
    // Set min/max etc.
    end
  else ...
Als ich schrieb 'insofern kommt die VCL hier nicht ins Spiel', meinte ich die Implementierung der Parameter, Funktionsgeneratoren etc. Das war von mir missverständlich ausgedrückt. Trotzdem ist es sehr einfach umzusetzen und kompakt, da es keine strukturellen Wiederholungen im Code der View gibt.

Namenloser 25. Jul 2014 18:51

AW: Designstruktur eines Funktionsgenerators
 
Das, was du an Interfaces definierst, entspricht halt ziemlich genau dem, wie auch die VCL schon aufgebaut ist (Checkbox – Boolean, Edit – String etc...). In sofern ist es schon mal in gewisser Weise eine Dopplung, auch wenn das eine View und das andere Model ist. Dazu kommt, dass die GUI so irgendwann unübersichtlich werden wird, wenn es mehr als eine Hand voll Einstellungen gibt. Dann wird die Frage kommen, ob man die Einstellungen nicht irgendwie gruppieren kann, und dann wird z.B. IPropertyGroup eingeführt, was eigentlich nur eine GroupBox-Repräsentation ist, und damit wandert Darstellungsfunktionalität ins Model, die dort eigentlich nichts verloren hat. Und an manchen Stellen will man vielleicht keine GroupBox sondern lieber TabSheets, und dann gibt es dafür auch wieder ein extra Interface. Verstehst du jetzt was ich mit VCL nachbauen meine?

Phoenix 25. Jul 2014 19:05

AW: Designstruktur eines Funktionsgenerators
 
Total OT: Ich hab grad tatsächlich erstmal "Fusionsgenerator" gelesen und an einen Fusionsreaktor gedacht, und mich dann gewundert warum wir solche Themen hier in der DP haben... :roll:
Man sollte nicht Krank und mit Kopfschmerzen noch 'mal kurz' vor den Rechner sitzen...

Sir Rufo 25. Jul 2014 19:29

AW: Designstruktur eines Funktionsgenerators
 
Ich würde eine Plugin-Schnittstelle sehr einfach halten:
  • Ausgabe des Generators
  • Name
  • Icon für den Button
  • Bild für die Anzeige
  • ...
und dem Plugin würde ich ein Handle übergeben, wo das Plugin seine Bedienoberfläche hinmalen kann, wie auch immer das Plugin das für richtig hält.

Dejan Vu 25. Jul 2014 20:24

AW: Designstruktur eines Funktionsgenerators
 
Zitat:

Zitat von Phoenix (Beitrag 1266676)
...und an einen Fusionsreaktor gedacht,...

Mit Plugin-Schnittstelle, wo man die unterschiedlichen Fusionsreaktortypen andocken kann. Mit Hot-Plug zur Laufzeit.

Zitat:

Zitat von Sir Rufo (Beitrag 1266677)
wo das Plugin seine Bedienoberfläche hinmalen kann, wie auch immer das Plugin das für richtig hält.

Dann hätten wir wieder eine kunterbunte UI, wo der eine Checkboxen verwendet, aber der andere einen Wippschalter etc.
Zitat:

Zitat von Namenloser (Beitrag 1266675)
Das, was du an Interfaces definierst, entspricht halt ziemlich genau dem, wie auch die VCL schon aufgebaut ist (Checkbox – Boolean, Edit – String etc...).

Das ist es gerade *nicht*. Das eine ist das Model, das andere die View. Ich definiere ja nur z.B. eine Selektion (eine Auswahl aus einer Liste). Wie das dargestellt wird, ist dem Funktionsgenerator ja schnurz (Combo, Radiogroup). Genauso verhält es sich mit einem Double. Soll das eine Maskedtextbox werden? Von mir aus? Ein Slider? Auch gut, ist eh Sache der View. Das Plugin hat damit nichts am Hut.
Zitat:

Dazu kommt, dass die GUI so irgendwann unübersichtlich werden wird, wenn es mehr als eine Hand voll Einstellungen gibt...IPropertyGroup eingeführt, was eigentlich nur eine GroupBox-Repräsentation ist,
Sehr gut. Das Konzept von MVC. Ich bin damit doch von der konkreten Darstellung (VCL, FMX, HTML etc.) vollkommen unabhängig. Und wenn ich morgen DevExpress einsetze, sehen die Property-Sheets aller Funktionsgeneratorn gleich aus. Ich habe nur eine Stelle im Code, wo ich das anpassen muss. Was will man mehr?
Zitat:

Und an manchen Stellen will man vielleicht keine GroupBox sondern lieber TabSheets, und dann gibt es dafür auch wieder ein extra Interface. Verstehst du jetzt was ich mit VCL nachbauen meine?
Nein. Denn ich habe genau das gerade gemacht: Property-List auf der einen Seite (Model und Viewmodel) und GUI-Elemente auf der anderen Seite (Control-Renderer). Der Control-Renderer (also das, was Du mit 'VCL nachbauen' meinst, umfasst etwas mehr als die von mir skizzierten IF-Blöcke. Die VCL hat meines Wissens nach ein paar Zeilen mehr.

Richtig ist aber auch, dass das Ganze nur dann Sinnvoll ist, wenn die Einstellungen nicht zu komplex sind. Bis ca. 15 Parameter sind ok. Gruppen und Tabs bekommt man aber noch problemlos hin. Wie gesagt, ich habe das gerade gemacht und es ist herrlich einfach und elegant: Es ist ein Reporting-Framework, wo man eigentlich nur die Query sowie die Datentypen der Parameter angeben muss, sofern diese nicht aus einem Repertoire aus vordefinierten und registrierten Parametern kommen: 'select * from Tabelle where KundenNummer =:KundenNr' extrahiert die 'KundenNr' definiert ein 'ICustomerNumberProperty'. Das zugehörige ViewModel (hier wäre das ein Frame) ist auch hinterlegt und -bupps- fertig ist der Report. Bei 'select * from Foo where Bar =:Bar' muss man 'Bar' entsprechend deklarieren (z.B. Selection of 'BarFoo, FooBar, Slartibartfass') und fertig ist das Teil.

Hier wäre das eine DLL, die eine Liste von Einstellungen exportiert und der Rest ist wie gehabt. Programmier das mal, ist wirklich super.

Sir Rufo 25. Jul 2014 20:58

AW: Designstruktur eines Funktionsgenerators
 
Was ist denn so schlimm daran, wenn da irgendwelche Controls im Plugin verwendet werden?

Wenn es dem Entwickler gefällt und der Kunde kauft ... wen soll das stören?
Mich, der das Grundsystem anbietet, wohl kaum.

Wenn es den Kunden stört, kauft der Kunde nicht oder bekundet sein Kaufinteresse, wenn das Design stimmt.

Man kann auch überregulieren ... Können kann man schon, müssen muss man aber nicht.

Namenloser 25. Jul 2014 21:28

AW: Designstruktur eines Funktionsgenerators
 
Zitat:

Zitat von Dejan Vu (Beitrag 1266678)
Zitat:

Zitat von Namenloser (Beitrag 1266675)
Das, was du an Interfaces definierst, entspricht halt ziemlich genau dem, wie auch die VCL schon aufgebaut ist (Checkbox – Boolean, Edit – String etc...).

Das ist es gerade *nicht*. Das eine ist das Model, das andere die View. Ich definiere ja nur z.B. eine Selektion (eine Auswahl aus einer Liste). Wie das dargestellt wird, ist dem Funktionsgenerator ja schnurz (Combo, Radiogroup). Genauso verhält es sich mit einem Double. Soll das eine Maskedtextbox werden? Von mir aus? Ein Slider? Auch gut, ist eh Sache der View. Das Plugin hat damit nichts am Hut.

Aber nicht immer ist für den gleichen Parametertyp das gleiche Control die beste Wahl. Vielleicht hast du zwei Int-Parameter, aber für den einen bietet sich eher ein Slider an und für den anderen eher ein SpinEdit. Was von beiden dargestellt werden soll, muss entweder im Interface angegeben werden (das wäre dann die Dopplung und Vermischung von interner und äußerer Darstellung), oder dein „Renderer“ muss sehr viele Spezialfälle beinhalten. Aber ob er jemals so intelligent wird wie ein menschlicher Designer?

Und es wird noch schwieriger dadurch, dass unterschiedliche Plattformen unterschiedliche Bedienkonzepte brauchen. Eine Smartphone-App willst du nicht so bedienen wie deinen Desktop-Client.

BUG 26. Jul 2014 00:28

AW: Designstruktur eines Funktionsgenerators
 
Zitat:

Zitat von Namenloser (Beitrag 1266681)
Was von beiden dargestellt werden soll, muss entweder im Interface angegeben werden (das wäre dann die Dopplung und Vermischung von interner und äußerer Darstellung), oder dein „Renderer“ muss sehr viele Spezialfälle beinhalten. Aber ob er jemals so intelligent wird wie ein menschlicher Designer?

Oder man hat eine zusätzliche Beschreibung für das Plugin: rein deklarativ, vielleicht in XML oder JSON, vom Benutzer konfigurierbar.

Zitat:

Zitat von Sir Rufo (Beitrag 1266677)
und dem Plugin würde ich ein Handle übergeben, wo das Plugin seine Bedienoberfläche hinmalen kann, wie auch immer das Plugin das für richtig hält.

Auch das kann man als Ausgabeelement vorsehen, damit sture Plugin-Entwickler nicht irgendwann anfangen, sich durch deine Fensterlisten zu hangeln.
Im gleichen Moment würde ich aber davon abraten, diese Schnittstelle unnötigerweise zu benutzen, damit man von Verbesserungen der Bedienelemente bei Update das Hauptprogramms profitieren kann.

Wenn man einen Schritt weiter gehen möchte: Auch die Control-Elemente könnten durch Plugins erweiterbar sein; dann kann man die besser geeignete Anzeige gleich mit allen anderen Plugins benutzen. Die könnten dann auf die oben genannte Handle-Schnittstelle aufbauen.


EDIT: OK ... für die beschriebene Funktionalität ist das vielleicht ein bisschen viel Aufwand. Wenn man aber komplexere Sachen auslagern möchte, ist das imho ein vernünftiger Weg. Dabei könnte man z.B. in Betracht ziehen, dass die Plugins für die Schnittstelle zum Fusionsreaktor eventuell von jemandem geschrieben wird, der mit der graphischen Darstellung nichts am Hut haben will.

Dejan Vu 26. Jul 2014 06:07

AW: Designstruktur eines Funktionsgenerators
 
Sir Rufo hat es auf den Punkt gebracht: 'überregulieren oder nicht'.

Will ich ein System, das leicht erweiterbar ist und vor allen Dingen stringent im Design, sollte ich dem Plugin nicht das Design der UI überlassen (irgendwie naheliegend). Ich erkaufe mir die schnelle Erweiterbarkeit mit Einschränkungen hinsichtlich des Designs, die aber gerade gewollt sind. In meinem Beispiel des Reporting-Frameworks war es so, das ich den Zeitraum der Auswertung (Von-Bis) immer an einer bestimmten Stelle im Frame haben wollte, darunter die Filial-Combo etc. Weiterhin gibt es für den Zeitraum ein bestimmtes Control, das mir sehr elegant erlaubt, einen Tag, die KW, Monat, Quartal etc. auszuwählen.

Wenn ich ein System designen will, bei dem das Hauptaugenmerk auf der UI liegt, wäre ich ja schön blöd, das so zu machen.

Nun ist es so, das ich bei einem Funktionsgenerator eher zu Szenario #1 tendiere, denn erstens sind die Einstellungen eher einfach, zweitens werden sie von keinem UI-Fetischisten bedient und drittens habe ich vielleicht Controls, die live-Änderungen sehr intuitiv durchführen und da wäre es wirklich von Vorteil, wenn diese Controls auch stringent genutzt werden. Weiterhin fände ich es wirklich elegant, wenn z.B. die Frequenz immer an oberster Stelle steht, gefolgt von Modularisierungseinstellungen, dann Optionen etc.

Nehmen wir als Gegenbeispiel ein Plugin-Framework für Analysen von Maschinensteuerungen, Logdateien etc. Also eine Wollmilchsau, die Eier legt und selber aufisst. Dort gibt es Kraut und Rübern, Äpfel und Birnen, will sagen, graphische und tabellarische Eingaben, Parameter, Auswertungen etc. Da wäre mein Konzept vollkommen fehl am Platz. Ich habe damals ein Interface verwendet, das ein Frame/Panel für Einstellungen geliefert hat. Das wurde dann beim Anklicken des Baumknotens auf die rechte Seite geklatscht. Eine Methode 'Execute' startet die Analyse und stellt die Ergebnisse in einem zweiten Frame/Panel dar. Ich war damit mehr oder minder an Delphi gebunden, aber mangels Alternativen in dem Laden war das nicht weiter schlimm.

Zitat:

Zitat von Namenloser (Beitrag 1266681)
Aber nicht immer ist für den gleichen Parametertyp das gleiche Control die beste Wahl. Vielleicht hast du zwei Int-Parameter, aber für den einen bietet sich eher ein Slider an und für den anderen eher ein SpinEdit.

Das sind im Fall #1 konstruierte Fälle, die in der Realität nicht auftreten. Vermutlich. Aber wenn die Ebene der Darstellung doch tangiert wird (Combo vs. Radiogroup) dann hat man vermutlich zuerst eine ensprechende Eigenschaft des Parameters, den man in der UI abbilden muss. Z.B. hier die Tatsache, ob der Wert punktgenau angegeben werden muss, oder eher ungefähr ('exact' vs. 'approximate'). Ein Notch Filter würde mir da spontan einfallen: Den regle ich nach Gehör/Gefühl. Hier ist ein Slider sinnvoll.
Wir haben hier also -entgegen deiner Annahme- wieder eine klare Trennung zwischen Funktion (Eigenschaft des Wertes:Exact vs. Approx) und Darstellung (Slider vs. Textbox/Spinedit)

Wenn ich jedoch Mühe habe, einem UI-Metapher eine entsprechende Eigenschaft eines Parameters anzudichten, sollte ich das Konzept überdenken. Ich kann mir z.B. keine Eigenschaft eines Parameters vorstellen, der steuert, ob ein Eingabefeld oder ein Spinedit genommen werden soll. Ist diese Freiheit gewollt?

Abschließend sei vielleicht noch angemerkt, das wir hier über einen Funktionsgenerator reden und nicht über ein komplettes konfigurierbares MVC-Konzept, das vielleicht nur mal am Rande.

Headbucket 1. Aug 2014 14:28

AW: Designstruktur eines Funktionsgenerators
 
Zitat:

Zitat von Dejan Vu (Beitrag 1266691)
Abschließend sei vielleicht noch angemerkt, das wir hier über einen Funktionsgenerator reden und nicht über ein komplettes konfigurierbares MVC-Konzept, das vielleicht nur mal am Rande.

:)
Ich möchte abschließend nochmal schreiben, wie ich es nun realisiert habe: Ich habe mir zunächst das MVC-Konzept angeschaut und empfand das auch als sehr übersichtlich. Ich hatte es oft unbewusst auch schon so gemacht. Bei meinem Funktionsgenerator fallen Steuerung und Präsentation allerdings zusammen.

Ich habe nun eine Basisklasse "GeneratorDataBase". Von dieser leite ich dann für jede Betriebsart verschiedene Unterklassen ab (GeneratorDataSine, GeneratorDataSweep, usw.).
Dann habe ich noch ein DisplayFrameBase mit dazugehörigen Ableitungen und ein SettingsFrame mit Ableitungen.

Die aktuellen Daten werden immer in der "GeneratorDataBase" gespeichert. Bei einer Änderung wird ein Event ausgelöst -> die geänderten Daten werden gespeichert und die Frames aktualisiert.

Das ganze funktioniert wunderbar und ist bis jetzt auch extrem übersichtlich. Eine Speicherung verschiedener Presets im XML ist auch schon drin.

Grüße
Headbucket


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:50 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