HMVC: Das Schichtmuster für die Entwicklung starker Client-Ebenen

Die Aufgabe, die Client-Ebene einer n-Tier-Webarchitektur zu entwerfen und zu entwickeln, fordert Entwickler häufig heraus. Dies gilt insbesondere für die Web-Welt, in der die Vielzahl von Servern, Bereitstellungsplattformen und Protokollen die Herausforderung zu Kopfschmerzen macht. Ein Architekt auf Client-Ebene muss eine Reihe von Fragen beantworten:

  • Wie soll ich meine GUI strukturieren?
  • Wie werden Benutzer mit meiner GUI interagieren?
  • Wie soll ich serverseitige / Transportdatenformate von meiner GUI trennen?
  • Wie sollte ich solide Mechanismen für die Ereignisverwaltung, Anwendungsflüsse und Widgetsteuerung bereitstellen?

Um einige dieser Schlüsselprobleme zu verstehen, müssen wir zwischen der Präsentationsschicht (oder Client-Schicht ) und der GUI-Schicht unterscheiden . Die GUI-Ebene behandelt eine kleine Teilmenge der gesamten Präsentationsschicht, nämlich die UI-Widgets und die unmittelbaren Auswirkungen von Benutzeraktionen - beispielsweise a JTextFieldund seine ActionListener. Die Präsentationsschicht muss sich neben der Bereitstellung von GUI-Diensten auch mit Anwendungsflüssen und Serverinteraktion befassen. Die Begriffe Präsentationsschicht und Client-Schicht werden in diesem Artikel synonym verwendet.

Framework-basierter Ansatz

Um das mit der Erstellung einer robusten Client-Ebene verbundene Risiko zu verringern, haben Entwickler verschiedene Frameworks und Entwurfsmuster mit unterschiedlichem Erfolg erstellt. Das Model-View-Controller (MVC) -Paradigma bleibt eines der beständigeren Muster. Der traditionelle MVC-Bereich ist jedoch nicht ausreichend, wenn es um die Steuerung von GUI-Elementen (Widgets) geht. MVC behandelt die Komplexität von Datenverwaltung, Ereignisverwaltung und Anwendungsabläufen nicht. Als Anpassung der MVC-Triade versucht das HMVC-Paradigma (Hierarchical-Model-View-Controller), einige der oben genannten Probleme zu lösen. Dieses Muster haben wir im Laufe unserer Feldarbeit entwickelt. HMVC bietet eine leistungsstarke und dennoch leicht verständliche Methode für das geschichtete Design zur Entwicklung einer vollständigen Präsentationsschicht.Während MVC ein effizientes Framework für die Entwicklung der GUI-Interaktion bietet, skaliert HMVC es auf die gesamte Client-Ebene. Einige wichtige Vorteile einer verantwortungsbasierten, mehrschichtigen Architektur sind:

  • Definierte Intralayer-Kommunikation und Isolierung von höheren Schichten
  • Definierte Zwischenschichtkommunikation mit minimaler Kopplung
  • Lokalisierung der Exposition gegenüber Code von Drittanbietern

In diesem Artikel wird die Anwendung des HMVC-Entwurfsmusters bei der Entwicklung einer Java-basierten Client-Tier-Infrastruktur erläutert.

Hinweis : Der gesamte Quellcode für diesen Artikel kann als Zip-Datei aus dem Abschnitt Ressourcen unten heruntergeladen werden.

Modellansichts-Controller - MVC

Entwickler verwenden MVC in Smalltalk hauptsächlich zum Implementieren von GUI-Objekten. Zahlreiche GUI-Klassenbibliotheken und Anwendungsframeworks haben das Muster wiederverwendet und übernommen. Da das MVC-Paradigma ein elegantes und einfaches Mittel zur objektorientierten Lösung von UI-bezogenen Problemen bietet, ist seine Popularität gerechtfertigt. MVC bietet klar definierte Rollen und Verantwortlichkeiten für seine drei Bestandteile - Modell, Ansicht und Controller. Die Ansicht verwaltet das Bildschirmlayout - das ist, mit was der Benutzer interagiert und auf dem Bildschirm sieht. Das Modell stellt die dem Objekt zugrunde liegenden Daten dar, z. B. den Ein-Aus-Status eines Kontrollkästchens oder die Textzeichenfolge aus einem Textfeld. Ereignisse bewirken, dass sich die Daten im Modell ändern. Der Controller legt fest, wie der Benutzer mit der Ansicht in Form von Befehlen interagiert.

Schicht MVC - HMVC

Das HMVC-Muster zerlegt die Client-Schicht in eine Hierarchie von Eltern-Kind-MVC-Schichten. Die wiederholte Anwendung dieses Musters ermöglicht eine strukturierte Client-Tier-Architektur, wie in Abbildung 1 dargestellt.

Der mehrschichtige MVC-Ansatz stellt eine ziemlich komplexe Client-Schicht zusammen. Einige der wichtigsten Vorteile der Verwendung von HMVC zeigen die Vorteile der Objektorientierung. Eine optimal geschichtete Architektur:

  • Reduziert die Abhängigkeiten zwischen verschiedenen Teilen des Programms
  • Ermutigt zur Wiederverwendung von Code, Komponenten und Modulen
  • Erhöht die Erweiterbarkeit und erleichtert die Wartbarkeit

Verwenden Sie HMVC, um eine Client-Tier-Architektur zu entwerfen

Obwohl Sie die Aufgabe möglicherweise als entmutigend empfinden, können Sie die Entwicklung einer Präsentationsschicht für eine Anwendung effektiv verwalten, indem Sie eine intelligente Entwicklung in Ihre Strategie integrieren - dh indem Sie ein robustes und skalierbares Muster verwenden, das einen Teil des Risikos reduzieren und eine fertige Designgrundlage, auf der aufgebaut werden kann.

Es gibt drei Schlüsselaspekte bei der Entwicklung auf Clientebene:

  • GUI-Layoutcode : Widget-Layout und Erscheinungsbild des Bildschirms
  • GUI-Funktionscode : Validierungen und Benutzerereigniserfassung
  • Anwendungslogikcode : App-Flows, Navigation und Serverinteraktion

Das HMVC-Entwurfsmuster fördert die Zerlegung der Client-Ebene in entwickelte, unterschiedliche Ebenen für die Implementierung von GUI- und Anwendungsdiensten. Eine musterbasierte Architektur führt zur Standardisierung. Das HMVC-Muster standardisiert die Präsentationsschicht (User-Service) von Webanwendungen. Die Standardisierung in der Präsentationsebene trägt dazu bei:

  • Konsistenz der Benutzeroberfläche : Das Framework unterteilt eine visuelle Entität (Ansicht) in Bereiche mit spezifischen, konsistenten Verantwortlichkeiten und Funktionen.
  • Standardisierte Interaktion : Die Interaktion zwischen den verschiedenen Unterkomponenten innerhalb der Präsentationsschicht ist klar definiert und bietet anpassbare Basisklassen.
  • Wartbarer Code : Die Verwendung eines Musters führt zu wartbarem Code, der eine flexible und erweiterbare Codebasis für die Entwicklung von Anwendungen bietet.
  • Unterstützung des Anwendungsflusses: Das Framework strukturiert den Präsentationsservice in verschiedene Ebenen und ermöglicht die Kommunikation zwischen und innerhalb von Schichten. Eine solche Struktur bietet eine starke und geordnete Möglichkeit, Anwendungslogik und -fluss zu implementieren.

Design-Prinzipien

Das HMVC-Muster bietet eine klare Abgrenzung der Verantwortung zwischen den verschiedenen Komponenten und Schichten. Standarddesignmuster (abstrakte Fabriken, Verbundwerkstoffe, Verantwortungskette, Fassade usw.) können verwendet werden, um ein stabiles Design bereitzustellen.

Abbildung 2 zeigt einige Schichten und Schlüsselkomponenten des HMVC-Musters. Die horizontalen Ebenen geben die Hierarchie innerhalb der Anwendung an. Die vertikalen Schichten beziehen sich auf die Komponenten der MVC-Triade. Innerhalb einer Ebene trägt der Controller die Gesamtverantwortung für die Verwaltung der Modell- und Ansichtskomponenten. Beispielsweise steuert der GUIFrame-Controller das GUIFrame-Modell und den GUIFrame (die Ansicht). Die gestrichelten Linien zwischen Modell, Controller und Ansicht innerhalb einer Ebene kennzeichnen klar definierte Schnittstellen für die Kommunikation. Diese Interaktion wird durch erreicht AppEvents. Für die Intralayer-Kommunikation existiert eine Eltern-Kind-Controller-Hierarchie, und die gesamte Intralayer-Kommunikation kann nur über diesen Pfad geleitet werden. Controller interagieren über AppEvents.

Aussicht

Ein Benutzer interagiert mit der Ansicht, dem sichtbaren Teil der Anwendung. HMVC abstrahiert Ansichten auf verschiedenen Ebenen, um eine saubere Methode zum Entwerfen der GUI bereitzustellen. Auf der höchsten Ebene befindet sich ein GUIContainer mit dem zugehörigen Controller. Der Container enthält im Wesentlichen potenziell mehrere Ansichten, die als GUIFrame (s) bezeichnet werden. Jeder GUIFrame ist eine visuelle Einheit, mit der ein Benutzer interagiert. Das Framework definiert einen GUIFrame als aus mehreren Unterteilen zusammengesetzt, dh einem Menü-GUIPane, einem Navigations-GUIPane, einem Status-GUIPane und einem zentralen Inhalts-GUIPane (siehe Abbildung 3). In den meisten gängigen Webanwendungen erwarten Entwickler normalerweise, dass mehrere GUIFrames unwahrscheinlich sind. In erster Linie muss sich der Content GUIPane ändern. Der Bereich Content GUIPane wird als der wichtigste Teil des GUIFrame angesehen. Hier findet der größte Teil der Benutzerinteraktion statt.Das Framework geht davon aus, dass die effiziente Steuerung mehrerer Content-GUIPanes ausreicht, um einen sehr großen Teil der Benutzererfahrung bereitzustellen.

Abbildung 3 zeigt ein typisches GUI-Frontend. Es zerfällt in mehrere Teile (dh GUIPanes). Wir können die MVC-Triade auf jedes der Erstellungsfenster anwenden und eine Hierarchie erstellen, wobei der GUIFrame aus den GUIPanes Menü, Status, Nav und Inhalt besteht. Abhängig von der Komplexität des Codes in jeder Komponente können wir einem GUIPane einen unabhängigen Controller und ein Modell zuweisen oder nicht. Zum Beispiel ist es aufgrund seiner Einfachheit und des Fehlens eines wirklichen Bedarfs an ausgefeilter Steuerung nicht erforderlich, dass der Status GUIPane über einen eigenen Controller verfügt. Wir können uns dafür entscheiden, dass der GUIFrame-Controller stattdessen den Status GUIPane ausführt. Da der Content GUIPane jedoch ein wichtiger Aktivitätsbereich ist, können wir ihm einen separaten Controller und ein separates Modell zuweisen. Basierend auf der MVC-Triade hat ein GUIFrame das zugehörige Controller- und Datenhaltermodell.ebenso wie der Content GUIPane. Die GUIFrame-Ebene hat den GUIContainer als übergeordnete Triade. Der GUIContainer ist ein unsichtbarer Teil der Architektur. Es kann möglicherweise mehrere GUIFrames enthalten.

Ein entscheidender Aspekt des Entwurfs ist die Isolierung des Swing-spezifischen Codes - dh der Swing-Komponenten und ihrer Listener (siehe Abbildung 2) - innerhalb der untersten Stufe der Hierarchie. Zur Veranschaulichung bilden Swing-Widgets hauptsächlich das Content GUIPane. Dies ist keine Designbeschränkung. Ein Nav GUIPane könnte auch eine Swing-Komponente haben, wie zum Beispiel a JTree. Daher ist der Content GUIPane auch für die Verpflegung von Swing-Events wie ActionEvents verantwortlich. In ähnlicher Weise wird ein ActionEventdurch Klicken auf a JMenuItemim Menü GUIPane erzeugtes Element vom Menü GUIPane selbst gehört. Somit fungiert ein GUIPane als Listener für Swing-Events. Das betroffene GUIPane kann anschließend mithilfe von Ereignissen auf Anwendungsebene weitere Dienste von seinem Controller anfordern. Dies ermöglicht die Lokalisierung von Swing-spezifischem Code.

Regler

Der Controller verwendet das Modell, um die Auswirkungen von Benutzerereignissen auf die Ansicht mit dem Modell zu koordinieren. Es ist auch auf den Logikfluss ausgerichtet. HMVC definiert Ebenen innerhalb der GUI und ermöglicht die verteilte Steuerung von Ereignissen über eine Eltern-Kind-Hierarchie von Controllern. Innerhalb einer Ebene ist der Controller der oberste Befehlshaber, der die Anwendungsflüsse und Benutzerereignisantworten koordiniert. Das Entwurfsmuster der Verantwortungskette implementiert die Controller, wobei sie Ereignisse weiterleiten, die sie nicht berücksichtigen können.

Wenn beispielsweise durch Klicken auf eine Schaltfläche in einem Content-GUIPane das Menü-GUIPane geändert werden muss, wird das ActionEventvom Content-GUIPane selbst abgefangen (da es der Listener für Swing / AWT-Ereignisse ist). Das ContentGUIPane würde anschließend eine Navigationsanforderung an den ContentGUIPane-Controller senden, die es wiederum an seinen übergeordneten Controller, den GUIFrame-Controller, weiterleiten würde. Dies ist darauf zurückzuführen, dass die Änderung im Menü-GUIPane nur auf einer höheren Ebene vorgenommen werden kann, da sich das Inhalts-GUIPane und das Menü-GUIPane in der Hierarchie auf derselben Ebene befinden (beide sind in einem GUIFrame enthalten).

Eltern-Kind-Beziehung

Eine absolute und klar definierte Eltern-Kind-Beziehung wird zwischen einem GUIContainer-Controller auf der obersten oder übergeordneten Ebene und seinem untergeordneten GUIFrame-Controller hergestellt. Ebenso besteht eine Eltern-Kind-Beziehung zwischen einem GUIFrame-Controller und einem GUIContent Pane-Controller. Der Controller innerhalb jeder Ebene ist nur für Aktionen verantwortlich, die auf seinen Einflussbereich beschränkt sind - dh das Modell und die Ansicht auf dieser Ebene. Für alle anderen Dienste muss der Controller Aktionen an sein übergeordnetes Element weiterleiten.

Kommunikation

Wenn ein Controller sein Ereignis nicht verarbeiten kann, signalisiert das Muster der Verantwortungskette dem Controller, das Ereignis an sein übergeordnetes Element weiterzuleiten. Controller kommunizieren miteinander über AppEvents- dies können normalerweise Navigationsereignisse, Datenanforderungsereignisse oder Statusereignisse sein. Navigationsereignisse sind normalerweise solche, die das Erscheinungsbild der Ansicht ändern. Wenn Sie beispielsweise JMenuItemim Menü GUIPane auf klicken, das das aktive Content GUIPane ersetzt, nimmt das Navigationsereignis die Änderung vor. Der Anwendungsentwickler müsste diese Ereignisse identifizieren und einige grundlegende Stereotypen erstellen.

Controller können auch über Datenereignisse kommunizieren. Wenn eine Inhalts-GUIPane Daten in einigen JTextFieldObjekten anzeigen muss , erstellt die Inhalts-GUIPane ein Datenereignis. Das Content GUIPane würde es dann an seinen Controller weiterleiten, der es bei Feststellung, dass es sich um ein Datenereignis handelt, an das zugehörige Modell delegieren würde. Das Modell würde anschließend eine Aktualisierungsanforderung an das Content GUIPane weiterleiten, wodurch ein sauberer und genau definierter Kommunikationspfad bereitgestellt wird.

Verantwortung

Der Controller hat mehrere Verantwortlichkeiten. Es muss beispielsweise auf Navigationsereignisse auf Anwendungsebene und Datenanforderungsereignisse reagieren. Als Reaktion auf Navigationsereignisse bietet eine Steuerung eine Anwendungsflusslogik, z. B. Ändern von Bildschirmen oder Deaktivieren / Aktivieren von Optionen. Bei Datenanforderungsereignissen delegiert der Controller die Anforderung an ein zugeordnetes Modellobjekt.

Modell

Ansichtsentitäten wie GUIContainer, GUIFrame (s) und GUIContent Pane (s) sind Modelle zugeordnet. HMVC sieht Modelle auf jeder Hierarchieebene vor, es ist jedoch Sache des Anwendungsdesigners, diese tatsächlich zu implementieren. Das GUIContainer-Modell enthält normalerweise Daten oder Informationen, die sich auf die gesamte Anwendung auswirken, während das GUIFrame-Modell Informationen enthält, die sich nur auf den Status eines GUIFrame beziehen. Das Modell enthält oder enthält die Datenobjekte, die in einer Ansicht angezeigt oder bearbeitet werden sollen. In der Regel empfängt das Modell eine delegierte Datendienstanforderung von der Steuerung, ruft die Daten ab und benachrichtigt die zugehörige Ansicht über die Verfügbarkeit neuer Daten.