![]() |
Problem mit Komponentennamen bei abgeleiteten Formularen
Hallo,
wenn man selbst erstellte (Standard)formulare über die Objektablage vererbt, erhält man auch die Komponenten und deren Namen im neuen Formular. Wie handhabt man dann die Komponentenbezeichnungen? Das Ganze mal als Beispiel mit Edits. Ich sehe momentan nur die Möglichkeit im Vorfahrformular die Edits mit allgemeinen Namen zu versehen, wie Edit1, Edit2, Edit3,... usw. Dadurch wird der Sourcecode nicht gerade übersichtlich. Sobald "sprechende" Namen vergeben werden habe ich quasi eine kleine Dokumentation im Vorfahrformular (edKDNR, edKDName, edKDOrt,...). Wenn mein Nachfahrformular dann eine Artikelstammdatenverwaltung ist heißt mein Edit für die Artikelnummer nicht edARTNr sondern auch edKDNR! Muss ich mit einer der beiden Methoden leben oder kann man die Namen im Nachfahrformular ändern? F.F. |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Dann klatsch auf den Vorfahr nur das drauf, was auch wirklich in den Nachfahren benutzt wird.
Unterscheiden sich die Edit-Felder in der Benennung, dann unterscheiden diese sich zumeist auch in den anderen Eigenschaften, wie Breite, Maximale Stellenanzahl, erlaubte Zeichen etc. |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Man kann sich auch eigene Variablen erstellen.
Delphi-Quellcode:
und dann im OnCreate
private
edKDNR: TEdit;
Delphi-Quellcode:
Oder
edKDNR := edARTNr;
Delphi-Quellcode:
und im OnCreate
published
edKDNR: TEdit;
Delphi-Quellcode:
.
edARTNr.Name := 'edKDNR';
Man wird vielleicht erschrecken, aber Delphi hat da einen Automatismuß, welcher auf published-Felder losgeht. Danach kann man dann ganz einfach edKDNR.Text verwenden. Sobald ein Feld im Owner einer TComponent genauso heißt, wie die Komponente (um)benannt wird, dann wird dieses Feld (egal welchen Types - Delphi prüft da leider nicht) gesetzt. Die Variable mit dem alten Komponentennamen wird auf nil gesetzt und in die andere Variable kommt die Instanz dieser Komponente. ( Auf diese Weise befüllt die VCL auch die Variablen/Felder mit den Komponenten, welcher über eine DFM erstellt werden. ) |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Also das Vererben von Formularen wird allgemein überschätzt.
In der Praxis sind die Formulare so unterschiedlich und so speziell an ihre Aufgabe angepasst, dass es kaum etwas zu vererben gibt. Wenn du also ein Basis-Formular hast und dann auf dem abgeleiteten Formular feststellst, dass dir die Namen der Controls nicht so richtig in Konzept passen, dann stimmt das Konzept der Vererbung eben nicht. Neben Formularen gibt es ja auch noch Frames. Ein Frame ist nur ein Teilstück eines Formulars. Es macht wesentlich mehr Sinn Teile eines Formulars in mehreren Formularen wiederverwenden zu können. Zusammengefasst Vererben von Formularen -> schlechte Technik für die Praxis, don't use it Frames -> korrekt angewandt zu empfehlen |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Wir haben so im Programm ein paar vererbte Formulare.
Da sind aber fast nie irgendwelche Eingabekomponenten drinnen, sondern nur Grundfunktionen dieser Formulare, wie z.B. das Speichern der Fensterposition oder die Darstellung/das Aussehn und bei Einem ist eine Menüleiste drin, welche in allen Nachfahren enthalten ist. Ansonsten sind nahezu alle Formulare und Komponenten (Edits und Co.) erstml grundsätzlich vererbt, falls man mal was Grundsätzliches an allen Formularen ändern will/muß und dafür wäre dann nur eine einzige Änderung an einer Stelle nötig. (bei über 100 Formularen, welche sich hier und da verstecken, ist das schon eine Erleichterung ... abgesehn von doppeltem/mehrfachem Code, wenn man das überall einzeln verbauen würde) |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Zitat:
Um das Look & Feel zu beeinflussen gibt es auch die Möglichkeit eine zentrale Komponenten-Factory zu verwenden:
Delphi-Quellcode:
Man spart sich so den Ballast der abgeleiteten Formulare und kann flexibler reagieren.
TComponentFactory = class(TObject)
public class function CreateComponent(AClass:TFormClass; Owner:TComponent):TComponent;virtual; class function CreateForm(AClass:TFormClass; Owner:TComponent):TCustomForm;virtual; class function CreateMdiForm(AClass:TFormClass; Owner:TComponent):TCustomForm;virtual; class function CreateModalForm(AClass:TFormClass; Owner:TComponent):TCustomForm;virtual; class function CreateGlobalForm(AClass:TFormClass):TCustomForm;virtual; // Owner ist Application end; |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Und dann kannst du damit keinen FormDesigner nutzen.
|
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Ich bin ein glühender Verfechter von Templates, auch wenn diese zu Projektbeginn noch manchmal recht mager ausgestattet sind. Im Laufe der Projekts kommt alles was für alle Nachfahren zu gebrauchen ist alles dort hinein, Imagelisten, allgemein gehaltene Popupmenus, die erwähnten Speicher- und Wiederherstellungsfunktionen für Form und Komponenten etc.
Edit und ähnliches tauchen erst in später als hiervon abgeleitete speziellere Templates auf, dann zum Beispiel wenn Angebote, Auftragsbestätigungen, Lieferscheine und Rechnungen so ähnlich sind dass alles gemeinsame auf diesem Template abgefackelt werden kann. Angenehm wird ein solches vorgehen wenn im Nachhinein Änderungen im Verhalten oder Layout gewünscht sind, und sei es dass über ein for i := ... Componentcount Aussehen oder Verhalten umgestellt werden. (Eine nachträglich gewünschte Mehrsprachigkeit zur Laufzeit über eine Datenbank umschaltbar wird dann zu einen 2 Stunden Aufwand). |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Zitat:
P.S.: zu "schlechter Technik" sage ich nur : absoluter Blödsinn. |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Bei mir sieht die Form Hierarchie z.B. so aus: TForm ->
1. Ableitung : Damit alle Forms ISO-konform sind wird hier direkt eingebaut, dass ESC jede Form schliesst. Und die Koordinatn sollen im FormClose gespeichert und im FormCreate gelesen werden. Das ist die 1. Ableitung von TForm. nächste Ableitungen : hier setzt die erste Verzweigung ein. Je nachdem, ob das ein reines Ausgabe-Form ist oder auch Eingaben gemacht werden können, werden nach und nach weitere Eigenschaften eingebaut. Z.b. Edit für Ku.Nr. Mit der Einführng des Ku.Nr.-Edits im Programm-Kontext wird natürlich direkt gleich schon die Logik für das Auffinden eines Kunden eingebaut. D.h. die Taste, die die Suchfunktion aufruft, einen Suchbutton für die Maus-Bevorzuger, das Lesen der entspr. Datensätze aus der DB in den geeigneten Events etc. Nun brauche ich z.B. eine Kunden-Statistik, eine Kundenrechnung, eine Kunden-Rechnungsliste usw. Für alle diese Fälle habe ich dann eben diverse Formulare, die einen gemeinsamen Vorfahr haben. Und sogar dieser Vorfahr weiss ja bereits von seinem entfernten Vorfahr, wie und wann er seine Koordinaten abzuspeichern hat. Es wäre Wahnsinn, all das bei jeder Form extra zu machen. Positiver Nebeneffekt : wenn ich einen Tipfehler mache, dann ist der sehr schnell aufzufinden, weil eben je nachdem wo der sich bemerkbar macht, ziemlich schnell klar ist, wo der sein muss. Oder bei Änderungen : sagen wir mal, irgendwem gefällt die Formfarbe nicht und er will schwarz auf Lila. :shock: Jetzt hiesse es : alle Forms von Hand einzeln ändern, bei mir würde es reichen, die allererste Form dementsprechend zu ändern. Das Letzte ist auch der entscheidende Unterschied : TForm ist TForm und Basta. Das unterliegt normalerweise nicht meinem Einfluss. Eine einzige dazwischengeschaltete Form-Ableitung (selbst wenn sie nichts macht) hebelt das komplett aus und gibt einem die volle Kontrolle (siehe Bsp. Form-Farbe). Shmia soll mal bitte irgendein Szenario nennen, wo die Form-Vererbung sich negativ bemerkbar macht. 8-) Zumal es ja auch noch inherited; +Co. gibt. Will ich irgendetwas vom Vorfahr nicht in abgeleiteter Form haben, dann lasse ich das eben weg. |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Zitat:
Irgendwann müssen die alten Rechnungen und alle abh. Daten auch mal gelöscht werden. Also gibt es dazu ein Formular. Das Problem ist nur solange der Löschvorgang läuft ist das Programm blockiert. Ausserdem muss das Löschen nachts laufen und nicht während der Arbeitszeit. Also soll das Formular mit allen seinen Abhängigkeiten in ein neues Projekt verpflanzt werden. Diese Wartungsanwendung läuft dann z.B. zeitgesteuert direkt auf einem Server. Wenn das betreffende Formular abgeleitet ist (womöglich sogar mehrfach) dann höre ich schon die ![]() Die tiefe Vererbungshierarchie zieht einen ganzen Rattenschwanz von Abhängigkeiten nach sich, die man in dem neuen Projekt nicht brauchen kann. Vererbung ist eben mit Vorsicht zu geniesen und es gibt auch andere Techniken im OOP. ![]() ![]() ![]() Um zum Beispiel die Formularposition in einer Inidatei oder Registry zu speichern, sollte man den Code nicht in einem Basisformular ablegen. Stattdessen gibt es eine eigene Klasse (abgeleitet von TComponent) die diese Dienstleistung für das Formular erbringt. Andere Formulare benötigen z.B. die Ausgabe von Log-Info die dann in einer Logdatei gesammelt werden oder über's Netzwerk verschickt werden. Auch das gehört nicht in eine Basisklasse eine Formulars. Mal angenommen man würde die beide Funktionalitäten mit Vererbung lösen wollen:
Code:
Was aber, wenn man beides will?
TForm <--- TFormWithPos (Formular, dass sein Position speichern/laden kann)
TForm <--- TLogForm (Formular mit Logausgabe) |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Zitat:
Sowas würde bei mir eine entsprechende Service-Anwendung (auf dem Server) erledigen - eigentlich sogar der DB-Server selber - auf jeden Fall aber nicht blockierend für die Anwendung. |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Zitat:
Zitat:
Das hat also nichts mit vererbten Formularen zu tun. 8-) Wichtiger ist das : Zitat:
Es handelt sich um einen Vorgang, den man unterbrechen kann (wenn man will). |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Zitat:
Zum Beispiel sollen auf bestimmten Formularen Benutzerrechte durchgesetzt werden. Der angemeldete Benutzer hat bestimmte Rechte (oder er hat sie nicht). Entsprechend den Rechten werden dann bestimmte Controls dekativiert oder unsichtbar geschaltet. Wie sieht dann wohl die Hierarchie der Form-Klassen aus? Tiefe Hierarchien führen in die Sackgasse; sie erschweren Änderungen und verstosen gegen das ![]() Ich weiss nicht, ob man einem erfahrenen Programmierer wie Dir noch etwas beibringen kann; ich hab's zumindest versucht. ![]() |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Wenn ich von TForm einen Formulartyp ableite, von dem ich dann alle meine Formulare ableite, hindert mich nichts daran, öfters benutzte Funktionalitäten in dieses abgeleitete Formular zu integrieren - gegebenenfalls mit entsprechenden published boolean Schaltern.
Tiefe Hierarchien sind gar nicht nötig, aber zumindest eine vorgeschaltete Hierarchiestufe, in der ich alle Erweiterungen einbauen kann, die sich im Laufe des Projekts ergeben, ist sehr sinnvoll und spart in der Regel viel Arbeit. Natürlich kann man für jede Zusatzfunktionalität eine neue nicht-visuelle Komponente erstellen, die man auf die Formulare klatscht - Nur wenn ich eine Menge Funktionalität habe, die in allen oder den meisten Formularen vorhanden sein soll, ist das unnötig mühsam, unübersichtlich und auch fehleranfällig: irgend einem neugeschriebenen Formular fehlt dann irgend eine Funktionalität, weil der Programmierer auf die entsprechende Komponente vergessen hat, und das fällt vielleicht erst auf, wenn die neue Programmversion schon an viele Kunden verteilt worden ist - oder man muss in den Routinetests vor der Auslieferung für jedes einzelne Formular das Vorhandensein aller Features, die automatisch vorhanden sein sollten und bei Vererbung auch automatisch vorhanden sind, separat überprüfen, was den Testaufwand wieder beträchtlich erhöht. Es könnte auch ein Programmierer in einem der bestehenden Formulare eine dieser nichtvisuellen Komponenten irrtümlich löschen - einmal an der Entfernen-Taste ankommen und so eine Komponente ist ohne Rückfrage und ohne dass es sonst weiter auffällt, weg - dann ist in der Folge das Verhalten in dem einen Eingabeformular inkonsistent. |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Zitat:
![]() Das ergibt den kleinen Bruder eines sog. ![]() Hast du schon mal ![]() ![]() Falls ja, dann wirst du gemerkt haben, dass man solche grossen Klassen, die alle möglichen Funktionalitäten beherbergen (weils anscheinend so bequem ist) nicht mehr richtig testen kann. Ich kann nur empfehlen: Lest das Buch "Clean Code" von Robert C. Martin ( ![]() ![]() |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Code:
Das solltest Du versuchen, Embarcadero zu erklären:) Die haben nämlich alles mögliche in ihre TForm-Klasse eingebaut.
du kannst doch nicht alles Mögliche in eine (Form-)Klasse einbauen.
Und Du würdest Dich schön bedanken, wenn Du für jede einzelne Funktionalität, die im TForm integriert ist, eine extra Komponente auf die Form legen müsstest. |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
@shima
wo soll denn jetzt genau das Problem mit den vererbten Formularen sein und wo verstösst da was gegen CleanCode? Niemand hat hier behauptet ein GodFatherFormular zu bauen, dass alle nur irgendwie erdenklichen Funktionen enthalten soll, die evtl. nur irgendein Formular benutzt. Aber was spricht dagegen alle Formulare von einer BasisForm abzuleiten in der das implementiert ist, was alle Formulare in der Anwendung benötigen? Jetzt kommen x weitere Formulare, die einzelne Datensätze bearbeiten, die alle die Funktionen Save, Reset und Cancel beherrschen müssen. Warum sollte ich da nicht ein EditBasisFormular anlegen von dem ich dann alle Edit-Formulare ableite? Sollte man tatsächlich dann für alle x Formulare die Funktionalitäten (Buttons) coden? Das ist dann aber nicht wirklich DRY. Jetzt kommen noch x Listen-Formulare, die müssen alle die Funktionalität Bearbeiten, Drucken, Exportieren, Löschen, etc. enthalten. Und wo du schon von UnitTests sprichst, die Funktionalität selber sollte ja eh nicht im Formular sitzen, sondern nur von diesem aufgerufen werden. Also selbst für das Speichern der Form-Position sollte der Code nicht in der Basis-Form liegen, sondern lediglich von dieser aufgerufen werden. |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Zitat:
|
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Es kommt wohl darauf an, wie komplex das gehandhabt wird. Wenn die Formularpositionen z.B. einfach in einer ini-Datei gespeichert werden, spricht wohl nichts dagegen, das direkt im der Form-Unit zu erledigen.
Bei komplexeren Anwendungen, bei denen wir die Formularpositionen, Farben und Schriftarten Benutzer- und Bildschirmgrössenabhängig zusammen mit einer Reihe von anderen erweiterten Formulareigenschaften in eigenen Tabellen der Anwendungsdatenbank speichern, haben wir das in eine eigene Unit ausgelagert. Datenbankzugriffe und dergleichen haben in einer generischen TMyForm-Unit wirklich nichts verloren. |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
@Hansa
ich mache es es zwar auch nicht so aber einfache Aufrufe wie Store/RestoreBoundsRect ließen sich so durch Unittausch/umdeklaration oder bedingte Kompilierung recht einfach auf ein anderes Storage verlegen. |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Zitat:
Es gibt aber nur ganz wenig was alle Formulare teilen können. Sollte es eine visuelle Gemeinsamkeit vor einigen Formularen geben (z.B. Panel mit Ok- und Abbrechen-Button) dann lässt sich das viel flexibler mit Frames handhaben. Der Baukasten der OOP beinhaltet mehr als nur Vererbung! Es gibt daneben auch Composition, Dependency Injection und Abstract Factorys. Wenn ich z.B. eine Factory benütze um bestimmte Dinge in allen Formularen einzustellen anstatt abzuleiten dann bin ich einfach freier bei zukünftigen Änderungen. Ein Klasse abzuleiten bedeutet immer auch eine gewisse Zementierung der Methoden. Die Basisklasse kann kaum noch geändert werden weil unter Umständen hunderte Formulare davon abhängen. Da aber Formulare immer auch Hotspots für Veränderungen sind ist es wichtig, dass man hier Vererbung vermeidet um die Möglichkeiten zur Veränderung offen zu halten. Die Klasse TForm ist schon von sich aus richtig "fett"; es gibt sehr viele Methoden und Properties. Solche Klassen sollte man nicht zusätzlich durch weitere Ableitungen aufblasen. Kleine Klassen die nach dem Baukastenprinzip zusammengesetzt werden lassen mehr Freiheit für Veränderungen. Zitat:
![]() |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Zitat:
Und das "nur ganz wenig", was Formulare gemeinsam brauchen, das stellt sich folgendermassen dar : gleiches Aussehen : betrifft Koordinaten, Fonts, diverse Controls (z.B. Schliessen-Button u.ä.)Auch speichern des aktuellen Standes. gleiche Bedienung : Tastatur : ein Tasten-Bedienung ! Wie gesagt : ISO-konform und nicht nach M$-"Standard". Also Esc zum schliessen und nicht Alt-F4. Ähnliches gilt für Tab/Shift-Tab, Suchtaste muss immer dieselbe sein etc. Betrifft OnKeyDown,OnKeyPress + Co. Maus : selbes Spielchen. Die Mausevents können zentral implementiert werden. Dann gehts noch um Speicherfreigaben und anderes. In meiner eigenen Ur-Form gibts auch noch ein OnClose mit
Delphi-Quellcode:
Besser, so was ist automatisch schon eingebaut.
Action := caFree;
Und sollte irgendwo was nicht passen, dann besteht die Erhöhung dieser "Flexibilität" nur darin, das
Delphi-Quellcode:
wegzulassen. Dann kann man ja alles wieder einfach neu bzw. anders definieren.
inherited;
Allerdings muss ich es mit Marco Cantu halten. In Köln auf den Delphi-Tagen habe ich länger mit dem diskutiert. Wir mussten leider feststellen, dass "even experienced Developers don't know, how to use repository, perhaps they simply ignore that" 8-) |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Formvererbung?
Komisch, das erinnert mich irgendwie an die OOP und das Vererben von billigen Klassen/Komponenten. Ja OK, das ist natürlich ganz schlim und sowas macht keiner. Prozeduren gehören in eine Unit und nicht in eine Klasse. Vererbter Code ist schlecht, denn ändert man mal was am Vorfahren, dann sind auch gleich alle Nachfahren futsch ... darum besser garnicht erst vererben und jedesmal alles neu schreiben. |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Das Ableiten von Formularen in der Objektablage mag ja für ein Login-Form oder ein About-Form noch in Ordnung gehen. Die Formulare in der Objektablage werden durch die Versionverwaltung nicht erfasst; das führt zu Problemen wenn man den Sourcecode weitergibt. Wer immer nur auf dem gleichen Rechner arbeitet der kennt das Problem nicht. Verwenden, also Kopieren von Formularen aus der Objektablage ist dagegen problemlos. Zitat:
|
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Zitat:
Wenn ich bestimmte Features einheitlich in allen meinen Formularen haben will, dann ist die Ableitung meiner Formulare von einem Vorfahr, der alle diese Features beinhaltet, die ADÄQUATE Vorgangsweise. natürlich gibt es auch andere Möglichkeiten, man kann Frames definieren, man kann Helper-Komponenten auf alle Formulare ziehen, man kann sich mit einer Factory behelfen etc. etc. Alle diese Möglichkeiten würde ich auch ins Auge fassen, wenn es in Delphi nicht zum Glück die einfachste und beste Lösung, nämlich die Vererbung, geben würde. Zitat:
|
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Zitat:
Die Vererbung zu benutzen um sich das Leben einfacher zu machen aber gleichzeitig hinten die Vasen wieder zu zertrümmern ist nicht konsequent. Schreibt man sich dafür eine entsprechende Logik (Unit) kann man diese hervorragend wiederverwenden, per Unit-Test prüfen und braucht sich keine Gedanken mehr darum machen. |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Dennoch kann man diese Funktionalität in das Formular einbauen.
Und sei es nur die Schnittstelle dafür. Also z.B. wie beim Popupmenü oder dem CustomHint, ein Property, wo man sonstwas anhängen könnte und dessen Aufruf an den entsprechenden Stellen integriert wurde. Oder man baut den Aufruf überall direkt ein, zu einer globalen Klasse/Funktion, welche dann das Speichern übernimmt. |
AW: Problem mit Komponentennamen bei abgeleiteten Formularen
Natürlich lässt sich jede Aufgabe nahezu beliebig weiter zerlegen. Dann habe ich eine Unit, die weiss, dass Daten in ein ini-File geschrieben werden sollen, die ruft dann eine unit auf, die ihr sagt, wie die Ini-Datei heissen soll, danach eine Unit, die weiss, welche Daten geschrieben werden sollen etc.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:32 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz