Da moderne Browser immer leistungsfähiger werden und umfassende Funktionen bieten, ist die Entwicklung vollständiger Webanwendungen in JavaScript nicht nur realisierbar, sondern wird auch immer beliebter. Basierend auf Trends in HTTP Archive ist die Größe des bereitgestellten JavaScript-Codes im Laufe des Jahres um 45% gestiegen.
Da JavaScript immer beliebter wird, sind unsere clientseitigen Anwendungen wesentlich komplexer als zuvor. Für die Anwendungsentwicklung ist die Zusammenarbeit mehrerer Entwickler erforderlich. Im neuen Zeitalter von Webanwendungen ist es entscheidend, gut zu wartenden und wiederverwendbaren Code zu schreiben. Die Chrome-App mit ihren zahlreichen clientseitigen Funktionen ist da keine Ausnahme.
Designmuster sind wichtig, um verwaltbaren und wiederverwendbaren Code zu schreiben. Ein Muster ist eine wiederverwendbare Lösung, die auf häufig auftretende Probleme im Softwaredesign, in unserem Fall, beim Schreiben von Chrome-Apps, angewendet werden kann. Wir empfehlen Entwicklern, die Anwendung in eine Reihe unabhängiger Komponenten gemäß dem MVC-Muster zu entkoppeln.
In den letzten Jahren wurde eine Reihe von JavaScript MVC-Frameworks entwickelt, z. B. backbone.js, ember.js, AngularJS, Sencha und Kendo UI. Auch wenn sie alle ihre einzigartigen Vorteile haben, folgen alle einer Form von MVC-Muster, um Entwickler zu ermutigen, strukturierteren JavaScript-Code zu schreiben.
MVC-Muster – Übersicht
MVC bietet architektonische Vorteile gegenüber Standard-JavaScript: Es hilft Ihnen, besser organisierten und damit leichter zu wartenden Code zu schreiben. Dieses Muster wurde in mehreren Sprachen und Generationen von Programmierern verwendet und ausgiebig getestet.
MVC setzt sich aus drei Komponenten zusammen:
Modell
Modell ist der Ort, an dem die Datenobjekte der Anwendung gespeichert werden. Das Modell hat keine Kenntnisse über Ansichten und Controller. Wenn sich ein Modell ändert, werden die Beobachter in der Regel darüber informiert, dass eine Änderung aufgetreten ist.
Um dies besser zu verstehen, verwenden wir die To-do-Listen-App, eine einfache, einseitige Web-App, die Ihre Aufgabenliste verfolgt.
Das Modell stellt Attribute dar, die mit den einzelnen Aufgabenelementen verknüpft sind, z. B. Beschreibung und Status. Neu erstellte Aufgaben werden in einer Instanz des Modells gespeichert.
Ansehen
In der Ansicht sehen Sie, was die Nutzer sehen und wie sie mit der App interagieren. Die Ansicht besteht aus HTML, CSS, JavaScript und häufig Vorlagen. Dieser Teil Ihrer Chrome-App hat Zugriff auf das DOM.
In der obigen Webanwendung für die Aufgabenliste können Sie beispielsweise eine Ansicht erstellen, in der Ihren Nutzern die Liste der To-do-Elemente ansprechend präsentiert wird. Nutzer können auch ein neues Aufgabenelement über ein Eingabeformat eingeben. Allerdings weiß die Ansicht nicht, wie das Modell aktualisiert werden soll, da dies die Aufgabe des Controllers ist.
Controller
Der Controller ist der Entscheidungsträger und der Kleber zwischen Modell und Ansicht. Der Controller aktualisiert die Ansicht, wenn sich das Modell ändert. Außerdem werden der Ansicht Ereignis-Listener hinzugefügt und das Modell aktualisiert, wenn der Nutzer die Ansicht ändert.
Wenn der Nutzer in der Web-App für die Aufgabenliste prüft, ob ein Element als erledigt markiert ist, wird der Klick an den Controller weitergeleitet. Der Controller ändert das Modell, um das Element als abgeschlossen zu markieren. Wenn die Daten dauerhaft sein müssen, werden auch asynchrone Daten auf dem Server gespeichert. Bei umfangreichen clientseitigen Webanwendungsentwicklung wie Chrome-Apps ist es außerdem von entscheidender Bedeutung, die Daten im lokalen Speicher dauerhaft zu speichern. In diesem Fall speichert der Controller die Daten auch im clientseitigen Speicher wie der FileSystem API.
Es gibt verschiedene Varianten des MVC-Designmusters, z. B. MVP (Model–View–Presenter) und MVVP(Model–View–ViewModel). Selbst beim sogenannten MVC-Designmuster selbst gibt es eine gewisse Abweichung zwischen dem traditionellen MVC-Muster und der modernen Interpretation in verschiedenen Programmiersprachen. In einigen MVC-basierten Frameworks werden beispielsweise Änderungen in den Modellen von der Ansicht beobachtet, während in anderen die Aktualisierung der Ansicht vom Controller durchgeführt wird. Dieser Artikel konzentriert sich nicht auf den Vergleich verschiedener Implementierungen, sondern auf die Trennung von Belangen und deren Bedeutung für das Schreiben moderner Webanwendungen.
Wenn Sie noch mehr erfahren möchten, empfehlen wir das Onlinebuch von Addy Osmani: JavaScript-Designmuster lernen.
Zusammenfassend lässt sich sagen, dass das MVC-Muster Anwendungsentwicklern Modularität bietet und Folgendes ermöglicht:
- Wiederverwendbarer und erweiterbarer Code.
- Trennung von Ansichtslogik von Geschäftslogik.
- Ermöglichen Sie gleichzeitige Arbeit zwischen Entwicklern, die für verschiedene Komponenten (z. B. die UI-Ebene und Kernlogik) verantwortlich sind.
- Einfachere Pflege.
MVC-Persistenzmuster
Es gibt viele verschiedene Möglichkeiten, Persistenz mit einem MVC-Framework zu implementieren, die jeweils unterschiedliche Vor- und Nachteile haben. Wählen Sie beim Schreiben von Chrome-Apps die Frameworks mit MVC- und Persistenzmustern aus, die sich für Sie natürlich anfühlen und den Anforderungen Ihrer Anwendung entsprechen.
Modell hat seine eigene Persistenz – ActiveRecord-Muster
Das ActiveRecord-Muster ist sowohl in serverseitigen Frameworks wie Ruby on Rails als auch in clientseitigen Frameworks wie Backbone.js und ember.js beliebt. Es übernimmt die Verantwortung für die Persistenz des Modells und wird normalerweise über die JSON API implementiert.
Die Einführung eines separaten Konzepts für die Store and Adapter API ist eine etwas andere Herangehensweise als bei der Verwaltung der Persistenz eines Modells. Speicher, Modell und Adapter (in einigen Frameworks als Proxy bezeichnet) arbeiten Hand für Hand. Ein Speicher ist das Repository, das die geladenen Modelle enthält. Außerdem bietet er Funktionen zum Erstellen, Abfragen und Filtern der darin enthaltenen Modellinstanzen.
Ein Adapter oder ein Proxy empfängt die Anfragen von einem Speicher und wandelt sie in geeignete Aktionen für Ihre persistente Datenschicht (z. B. die JSON API) um. Dies ist beim Design moderner Webanwendungen interessant, da Sie oft mit mehr als einer persistenten Datenschicht wie einem Remoteserver und dem lokalen Speicher eines Browsers interagieren. Chrome-Apps bieten sowohl die Chrome Storage API als auch die HTML5 fileSystem API für clientseitigen Speicher.
Vorteile:
- Nutzerfreundlich und leicht verständlich.
Nachteile:
- Schwer zu testen, da die Persistenzebene in die Objekthierarchie „verankert“ ist.
- Es ist schwierig, dass verschiedene Objekte unterschiedliche nichtflüchtige Speicher verwenden (z. B. FileSystem APIs, indexDB oder serverseitig).
- Die Wiederverwendung von „Model“ in anderen Anwendungen kann zu Konflikten führen, z. B. die gemeinsame Nutzung einer einzelnen Kundenklasse für zwei verschiedene Ansichten, die jeweils an verschiedenen Orten gespeichert werden sollen.
Controller hat Persistenz
In diesem Muster enthält der Controller einen Verweis sowohl auf das Modell als auch auf einen Datenspeicher und ist dafür verantwortlich, das Modell beizubehalten. Der Controller reagiert auf Lebenszyklusereignisse wie Laden, Speichern und Löschen und gibt Befehle zum Abrufen oder Aktualisieren des Modells an den Datenspeicher aus.
Vorteile:
- Der Test ist einfacher und der Controller kann an einen fiktiven Datenspeicher übergeben werden, für den Tests geschrieben werden.
- Dasselbe Modell kann für mehrere Datenspeicher wiederverwendet werden, indem einfach Controller mit unterschiedlichen Datenspeichern erstellt werden.
Nachteile:
- Die Pflege von Code kann komplexer sein.
AppController hat Persistenz
In einigen Mustern ist ein überwachender Controller für die Navigation zwischen einem MVC und einem anderen verantwortlich. Der AppController entscheidet beispielsweise, dass der Client mit einer Zurück-Schaltfläche von einem Bearbeitungsbildschirm, der MVC-Widgets/-Formate enthält, zu einem Einstellungsbildschirm verschoben wird.
Im AppController-Muster reagiert AppController auf Ereignisse und ändert den aktuellen Bildschirm der Anwendung, indem er einen Aufruf an den Datenspeicher sendet, um alle erforderlichen Modelle zu laden und alle übereinstimmenden Ansichten und Controller für diesen Bildschirm zu erstellen.
Vorteile:
- Verschiebt die Persistenzebene im Stapel noch weiter nach oben, wo sie leicht geändert werden kann.
- Verschmutzt Controller niedrigerer Ebene wie ein DatePickerController nicht, die über die Persistenz informiert werden müssen.
Nachteile:
- Jede Seite bzw. jeder Bildschirm der App erfordert nun eine Menge Boilerplate zum Schreiben oder Aktualisieren: Model, View, Controller, AppController.
Empfohlene MVC-Frameworks
MVC ist für die Entwicklung von Chrome-Apps von entscheidender Bedeutung. Wir empfehlen die folgenden CSP-konformen MVC-Frameworks, um sichere und skalierbare Chrome-Apps zu schreiben:
- AngularJS (Referenz-App für Text Drive und Anleitung zum Erstellen von Apps mit AngularJS)
- Kendo-Benutzeroberfläche (Referenz-App für Photo Booth)
- Sencha (Video Player-Referenz-App und Anleitung zum Erstellen von Apps mit Sencha Ext JS)
Nützliches Infomaterial
Online
- HTML5Rocks.com
- Learning JavaScript Design Patterns (von Addy Osmani)
- TodoMVC
Bücher
- JavaScript-Webanwendungen (von Alex MacCaw)
- JavaScript Patterns (JavaScript-Muster) (von Stoyan Stefonov)
- Wartungsfähiger JavaScript-Code (von Nicolas Z. Zakas)