Warum sollte eine Formvererbung vermieden werden?


9

Ich erinnere mich, wie ich VB4 gelernt und eine Schaltfläche auf ein Formular gezogen, auf diese Schaltfläche doppelklickt und Code in den Ereignishandler eingegeben habe, mit dem ich gerade magisch gesegnet worden war. Als ich von QBASIC kam, war ich begeistert von dem "V" in "VB". Der visuelle Designer war buchstäblich das Beste seit geschnittenem Brot.

Natürlich können Sie das alles programmgesteuert tun, aber die Magie des "V" war so ansprechend, dass Sie einfach nicht anders konnten, als diesen Knopf zu ziehen. Wir wurden ermutigt, diesen Weg zu gehen.

Aber dann habe ich vor ein paar Jahren angefangen, etwas über C # und das .net-Framework zu lernen, und war fasziniert von der Art und Weise, wie alles, was ich zu wissen glaubte, gerade aus dem Fenster gegangen war. In VB6 steckt viel Magie , die in .net vollständig enthüllt ist: Nehmen wir InitializeComponentszum Beispiel Konstruktoren und die Methode. In letzterem finden Sie alle Steuerinstanzen, die Sie aus der Toolbox gezogen haben, alle Ereignisse, die Sie registriert haben, und die Eigenschaften, die Sie im Designer festgelegt haben.

Und das ist in Ordnung ... ich denke. Es ist nur so, dass ich das Gefühl habe, nicht zu "besitzen", was los ist. Dieser Code, den ich nur über den Designer ändern kann, nervt mich zum Teufel. Jedes Mal, wenn Sie eine Schaltfläche mit der Aufschrift "Ok" von einem Formular in ein anderes kopieren (manchmal zusammen mit dem Bruder "Abbrechen"), duplizieren Sie tatsächlich Code, und das ist eine Sünde, nicht wahr? DRY, wiederhole dich nicht, sagt der Papst .

Abgesehen von Religionen und Denkschulen sollten wir bei aller Objektivität nicht stattdessen Formen von Basisformen ableiten und die Schaltfläche "Ok" (und alle ihre Freunde) auf der Basisform leben lassen? So etwas wie ein, FormBasevon dem a abgeleitet ist DialogFormBase; Alle Klassen in kürzester Zeit erstellt ... durch Eingabe von Code. Die Schaltflächen werden abhängig davon erstellt, wie die Klasse instanziiert wird (dh ein Konstruktor-Enum-Argument bestimmt, welche Schaltflächen erstellt werden sollen). Die Steuerelemente werden in einer Anordnung von geteilten Bedienfeldern und Flusslayout-Bedienfeldern angeordnet, die in das Formular als eingefügt werdenContentdas passt in das Hauptinhaltsfenster. Ist es nicht das, was ASP.net mit Masterseiten und Inhaltsplatzhaltern macht? Ich würde ein Formular ableiten, wenn ich eine neue "Masterseite" benötige, aber diese neue "Masterseite" stammt immer noch von einer Basisformularklasse, sodass die visuellen Elemente in der gesamten Anwendung konsistent sind.

Für mich ist das viel mehr Wiederverwendung von Code als alles andere, was ich jemals mit dem Designer in WinForms gemacht habe, und es war nicht einmal schwer, und Code ist nicht mit einer 200-Zeilen-Methode überfüllt, über die ich keine Kontrolle habe Wenn Sie Kommentare dort platzieren, wo ich möchte, werden sie nicht von einem Designer überschrieben. Ich denke, es ist nur eine Frage der Muster und der Architektur, was mich zu diesem Link geführt hat: Das beste Design für Windows-Formulare mit gemeinsamen Funktionen , bei dem mir klar wurde , dass ich genau richtig war, mit Ausnahme der Antwort dort, legt genau nahe, was ich bin zu tun, aber es ist die Beratung gegen Form Vererbung , weil der Designer - Überlegungen. Das ist der Teil, den ich nicht verstehe .Aufgrund von Überlegungen zur Codestruktur, insbesondere in Bezug auf die Vererbung von Formularen und Steuerelementen, die ich nicht als gut zu vermeiden sehe , bricht sie den Designer .

Wir können nicht alle nur faul sein, also welcher Teil fehlt mir?


Ich verstehe nicht Wollen Sie damit sagen, dass wir keine visuellen Designer verwenden und den gesamten GUI-Code von Hand schreiben sollten?
Euphoric

Wo war vor .NET der Code, der alle auf dem Formular gezogenen Objekte kontrollierte?
JeffO

1
@JeffO Nach dem alten Code zu urteilen, mit dem ich mich befasst habe, würde ich direkt auf dem Formular sagen, irgendwo zwischen Ad-hoc-Inline-SQL und Geschäftslogik. Punkt ist, WinForms ist .net; Wenn der Designer also gut mit dem arbeitet, was heutzutage nach "schlechtem Code" und "schlechten Codierungsgewohnheiten" riecht und tatsächlich bricht, wenn Sie anfangen, Dinge zu strukturieren, sage ich, lassen Sie den Designer fallen und behandeln Sie Formulare als das, was sie sind (Klassen!). . und wie unterscheidet sich das Codieren einer UI-Ebene in C # überhaupt vom Codieren einer UI-Ebene in ExtJS? Es ist "langweilig", das in WinForms zu tun, weil "hey schau, es gibt einen Designer"? Ist das Codieren einer ExtJS-Benutzeroberfläche mühsam?
Mathieu Guindon

Ich werde einen anderen Benutzer zitieren: CodeCaster; Ein Event-Handler soll die GUI mit Ihrer Geschäftslogik verbinden. Wenn Sie ein Textfeld zur Eingabe des Benutzernamens und eine Schaltfläche zum Hinzufügen haben, sollte durch Klicken auf die Schaltfläche Hinzufügen lediglich _userRepository.AddUser (UsernameTextbox.Text) aufgerufen werden. Sie möchten keine Geschäftslogik in Ereignishandlern. stackoverflow.com/questions/8048196/…
Pieter B

@Pieter fügt das nicht eine DAL-Abhängigkeit in Ihre Präsentationsebene ein?
Mathieu Guindon

Antworten:


9

Ich werde Sie mit einem anderen Paradigma ablehnen: Bevorzugen Sie die Komposition gegenüber der Vererbung.

Selbst wenn Sie anfangen, GUI-Code von Hand zu schreiben und die Vererbung verwenden, um Verhalten und Grafiken zwischen Formularen auszutauschen, treten dieselben Probleme wie beim normalen OOP-Design auf. Nehmen wir an, Sie haben DialogForm mit OK / Abbrechen-Schaltflächen und GridForm mit Raster. Sie leiten alle Dialoge von DialogForm und alle Formulare mit Grid von GridForm ab. Und dann finden Sie heraus, dass Sie mit beiden Form wollen. Wie würden Sie es lösen? Wenn Sie die Formularvererbung verwenden, gibt es keine Möglichkeit, diese zu lösen. Wenn Sie jedoch UserControls verwenden, können Sie GridControl einfach in Ihr Formular einfügen und fertig. Sie können Designer weiterhin mit UserControls verwenden, sodass Sie keine Zeit damit verschwenden müssen, langwierigen GUI-Code zu schreiben.


Nun, das Basisformular hat lediglich einen SplitContainer mit festem Panel2, der ein FlowLayoutPanel enthält, das aufgerufen wird BottomPanelund das allgemeine Verhalten von Ok / Abbrechen / Anwenden / Schließen hostet. Panel1 enthält einen SplitContainer mit festem Panel1 (zum Hosten allgemeiner Beschriftungen für "Anweisungen" oder Menüs, Symbolleisten, was auch immer oben angezeigt wird) und Panel2 mit einem geschützten Panel namens MainContent; Jede tatsächliche Implementierung entscheidet, wie sie gefüllt wird. Alle Inhalte können in die Implementierung eingefügt werden, und ja, dies kann eine Benutzersteuerung sein, die mit dem Designer erstellt wurde, um Zeit zu sparen, ein guter Punkt. Aber was ist mit dem Formular selbst?
Mathieu Guindon

Das Problem hier ist die Skalierung. Wenn Sie sich mit 10 Formularen bewerben, ist es keine große Sache, ein einziges gemeinsames Formular zu haben. Die Probleme beginnen, wenn Sie eine Anwendung mit Dutzenden oder Hunderten von Formularen haben. Dann haben Sie Formulare, die gemeinsame Teile haben, aber nie genug, um ein Basisformular zu erstellen. In diesem Fall kann es vorkommen, dass Sie ein anderes Layout oder andere Schaltflächen verwenden möchten, aber alles andere gleich lassen möchten. Und dann beginnen die Probleme.
Euphoric

2
Das Problem mit der Skalierung besteht nicht, wenn Sie ein halbwegs anständiges Design haben. Wir haben ein Projekt, in dem ich mit einigen hundert Formularen arbeite. Wir verwenden die Formularvererbung stark, um Konsistenz und allgemeine Funktionalität bereitzustellen, und wir hatten nie Probleme damit.
Mason Wheeler

2
@ MasonWheeler Ich hatte genau entgegengesetzte Erfahrung. Wir haben versucht, die Formularvererbung in einer unserer Anwendungen zu verwenden, und jedes Mal, wenn wir nur geringfügige Änderungen an den Basisformularen vorgenommen haben, ist das Ganze zusammengebrochen und wir mussten alle anderen Formulare manuell reparieren. Außerdem verhält sich Designer seltsam, wenn Sie mit geerbten Formularen arbeiten.
Euphoric

1
@Euphoric: Welcher Designer? Wir verwenden Delphi und sein Designer funktioniert gut mit geerbten Formularen. Und wieder haben Sie diese Probleme nicht, wenn Sie ein gutes Design haben . Wenn Sie nichts planen, wird natürlich alles spröde und kaputt, wenn Sie es berühren, aber das unterscheidet sich nicht von jedem anderen Code.
Mason Wheeler

2

Vieles davon hängt mit dem Technologie-Stack der Wahl zusammen.

WinForms und WPF können beide .NET UI-Frameworks sein, unterscheiden sich jedoch stark darin, wie Sie das Endziel erreichen. Bestimmte Paradigmen bewegen sich gut zwischen Technologien, andere jedoch nicht, und Sie sollten nicht versuchen, ein Paradigma zu erzwingen, nur weil Sie der Meinung sind, dass es in jedem Framework existieren soll. Es gibt einen Grund, warum MVVM auf WPF / SL ausgerichtet ist und MVC in ASP.NET ein von WebForms usw. getrenntes Konzept ist. Bestimmte Technologien funktionieren mit bestimmten Paradigmen besser.

Beachten Sie, dass generierter Code im Allgemeinen aus Ihren DRY-Bedenken entfernt werden sollte. Obwohl dies in einigen Fällen anwendbar ist, sollte es meistens ignoriert werden. DRY-Konzepte sollten sicherlich ein Schwerpunkt außerhalb Ihrer Präsentationsebene bleiben, aber auf der Präsentationsebene ist generierter Code häufig ein Nebenprodukt des Frameworks, in dem Sie arbeiten. Dies bedeutet nicht, dass Sie DRY-Prinzipien in Ihrem Ansatz nicht anwenden können, sondern bleiben vorsichtig. Könnten Sie ein Basisformular erstellen und auf unbestimmte Zeit davon erben? Ja. Können Sie Komponenten bei Bedarf jedes Mal per Drag & Drop auf ein neues Formular ziehen? Ja. Konzentrieren Sie sich auf das Endziel, vermeiden Sie potenzielle Fehler, vereinfachen Sie die Umgestaltung nachgelagert und skalieren Sie, während Sie innerhalb der Grenzen des Technologie-Stacks Ihrer Wahl arbeiten.


0

Sie können die Vererbung verwenden, sofern Sie Ihre Felder korrekt kapseln und entsprechend füllen. Wenn Sie die Vererbung verwenden möchten, würde ich vorschlagen, das Basisformular und ein entsprechendes Modell für dieses Formular zu verwenden und für jede Ableitung sowohl das Formular als auch das Modell abzuleiten.

Eine weitaus bessere Alternative wäre, gruppierte Steuerelemente in einem oder mehreren UserControl-Steuerelementen zu gruppieren. Sie brauchen nur ein wenig Logik, um die relevanten Daten darin abzulegen.


0

Ich stimme Mason Wheeler voll und ganz zu, obwohl in drei Jahren vielleicht sogar er selbst seine Meinung geändert hatte.

Ich versuche nach Alternativen für die Migration von ausführbaren Delphi-Dateien zum WEB zu suchen.

Bisher habe ich mich für UNIGUI entschieden, weil ich die Formularvererbung weiterhin verwenden kann. Ich möchte, dass Delphi Mixins wie Dart hat, da ich dadurch weniger Vorfahren habe. Ich bin jedoch der Meinung, dass die Leute in MVC viel mehr Code schreiben als mit Visual Form Inheritance, da der Großteil der Navigation die Validierungsregeln im Datenmodul (applyupdates), SQL-Filterkriterien, das Durchsuchen des Client-Datasets aufruft und alles in 5 oder 6 geschrieben ist Bilden Sie Vorfahren.

Sogar das "Mit MVC wird es für Sie einfacher sein, Delphi im Feature zu belassen" funktioniert für mich nicht als Argument, da die Leute OOP eingeladen haben, alles sind Klassen, Eigenschaften, Methoden. Ich brauche also nur einen Übersetzer. Wirklich konnte keinen Vorteil finden, vielleicht für Websites, die viel weniger kompliziert sind, aber sich in einer täglichen Basis ändern.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.