Solide auf drei Pfeilern

Softwarearchitektur in JavaScript
Kommentare

Die Architektur einer Software beschreibt den Aufbau und das Zusammenspiel der einzelnen Komponenten des Systems. Sobald Sie vorhaben, eine Anwendung zu erstellen, die mehr als eine Handvoll Zeilen JavaScript-Quellcode umfassen soll, sollten Sie sich Gedanken über die Architektur dieser Anwendung machen. Wie eine solche Architektur aussehen kann und worauf Sie bei der Planung achten sollten, erfahren Sie in diesem Artikel.

Die ernüchternde Nachricht komm zuerst: Es gibt nicht die eine perfekte Vorgehensweise, wenn es um den Aufbau von Anwendungen in JavaScript geht. Die Wahl der Mittel und damit der Architektur hängt vielmehr von zahlreichen Faktoren ab. Diese fallen häufig in den Bereich der nicht funktionalen Anforderungen einer Applikation. Klassische Beispiele sind hier Antwortzeiten, Skalierbarkeit oder Zuverlässigkeit. Je nachdem, was Ihre Applikation leisten soll, werden diese nicht funktionalen Anforderungen unterschiedlich gewichtet und müssen bei der Planung der Architektur und der Auswahl der Hilfsmittel berücksichtigt werden.

Architektur in der realen Welt

Wie aber funktioniert die Auswahl der Architektur für eine Applikation in den meisten Fällen? Hier gibt es die verschiedensten Varianten. Häufig kennen ein oder mehrere Entwickler eine bestimmte Architekturform und wenden diese auf das zu lösende Problem an. Diese Vorgehensweise hat jedoch den Nachteil, dass die gewählte Architektur nicht aufgrund des Problems, sondern wegen persönlicher Präferenzen gewählt wurde. Eine weitere, nicht unproblematische Form der Architekturauswahl besteht darin, zunächst sehr klein und wenig strukturiert mit der Entwicklung einer Applikation zu beginnen. Mit zunehmendem Wachstum der Applikation wird der Quellcode jedoch nicht umstrukturiert, sondern lediglich erweitert und auf der wenig stabilen Basis aufgesetzt. Dadurch werden technische Schulden aufgebaut, die Sie früher oder später in Form von Refactorings zurückzahlen müssen, oder die Entwicklung Ihrer Applikation wird so teuer, dass es sich nicht mehr lohnt, sie weiter zu betreiben. Die dritte und beste Variante besteht darin, die passende Architekturform für das gegebene Problem zu finden und zu implementieren. Dabei sollten Sie Ihre Architekturentscheidung kontinuierlich hinterfragen und, wann immer notwendig, Korrekturen und Änderungen vornehmen. Das Finden der richtigen Softwarearchitektur ist also keine einmalige Aktion zu Beginn eines Projekts, sondern vielmehr ein laufender Prozess, der sich über die gesamte Lebenszeit einer Applikation erstreckt. Nehmen Sie laufend kleinere Änderungen an Ihrer Applikation vor und modernisieren Sie Ihre Applikation so stetig. Verlängern Sie einerseits die Lebenserwartung Ihrer Applikation und vermeiden andererseits eine veraltete und nicht mehr wartbare Architektur.

Nicht funktionale Anforderungen an eine Webapplikation

Die perfekte Architektur für eine Webapplikation schon zu Beginn eines Projekts zu finden, ist eine Illusion. Es gelingt Ihnen maximal eine grobe Näherung an die perfekte Lösung. Entscheidend für eine gute Lösung sind die Rahmenbedingungen, die für die Applikation gesetzt werden. Wie bei der Sammlung von funktionalen Anforderungen werden Sie auch bei der Aufnahme der nicht funktionalen Anforderungen nicht alleine gelassen. Es existieren einige Frameworks und Dokumente, die Ihnen hier Hilfestellung leisten können. Ein guter Ansatzpunkt, um Anforderungen an Ihre Architektur zu finden, ist, dass Ihre Software eine gute Qualität aufweisen muss. Softwarequalität ist laut DIN durch die folgenden Rahmenparameter definiert:

  • Funktionalität
  • Zuverlässigkeit
  • Benutzbarkeit
  • Effizienz
  • Wartbarkeit
  • Übertragbarkeit

Was bedeutet das aber jetzt für Ihre JavaScript-Applikation? Zunächst müssen Sie bewerten, was Ihre Applikation leisten soll und wie viel Ihnen das wert ist. Je mehr nicht funktionale Anforderungen Sie an Ihre Applikation stellen, desto umfangreicher und damit teurer wird Ihre Implementierung. Das bedeutet, dass Sie, vor allem wenn Sie nicht über ein unerschöpfliches Budget verfügen, priorisieren sollten, worauf Sie Wert legen. Eine konkrete Situation könnte sein, dass Ihnen nur begrenzte Serverressourcen für Ihre Applikation zur Verfügung stehen und Sie aus diesem Grund großen Wert auf die Effizienz Ihrer Applikation legen müssen. Oder dass Ihre Applikation besonders darauf ausgelegt sein soll, dass Erweiterungen und zusätzliche Features in Zukunft möglichst günstig umzusetzen sind.

Alle diese Parameter beeinflussen, welche Struktur, Komponenten, Bibliotheken und Frameworks bei der Entwicklung Ihrer Applikation zum Einsatz kommen.

Grundsätzliche Arten von Webapplikationen

Zunächst sollten Sie sich die grundsätzliche Frage stellen: Wie soll Ihre Applikation aufgebaut sein? Unterteilen Sie Ihre Applikation in mehrere voneinander getrennte Seiten, oder besteht Ihre Applikation aus nur einer Seite, die für die Anzeige aller Informationen verantwortlich ist?

Außerdem sollten Sie abschätzen, wie oft sich die Informationen innerhalb Ihrer Applikation ändern. Visualisieren Sie beispielsweise innerhalb Ihrer Applikation Echtzeitdaten, wie die Leistungsdaten eines Servers oder Börsenkurse, müssen Sie dafür sorgen, dass Sie regelmäßig aktualisierte Daten vom Server erhalten. Die Entscheidung zwischen jeweils Multi-Page-Webapplikationen MPA, Single-Page-Webapplikationen (SPA) und Echtzeitwebapplikationen bedeutet für Sie zunächst die erste Weichenstellung. Die Art der Applikation entscheidet zunächst generell über die Menge an JavaScript, die Sie in Ihrer Applikation benötigen. Bei einer MPA setzen Sie normalerweise weniger JavaScript ein als bei einer SPA. Die Informationen, die Sie in einer MPA darstellen, befinden sich im Normalfall auf der Seite, die vom Server geladen wird. JavaScript spielt hier nur eine untergeordnete Rolle und dient lediglich zur Erweiterung der Funktionalität. Im Gegensatz dazu müssen Sie bei einer SPA die Daten vom Server holen, die Sie für die aktuell gewählte Komponente darstellen möchten. Diese Logik müssen Sie in JavaScript abbilden. Ein Vorteil der SPA gegenüber der MPA ist, dass Sie die Daten der Bibliotheken und Frameworks, die Sie für Ihre Applikation benötigen, lediglich einmal, nämlich beim Aufruf der Applikation im Browser, laden müssen. Im weiteren Verlauf laden Sie lediglich Informationen oder Teile der Applikation nach. Bei einer MPA wird bei jedem Seitenwechsel die gesamte Seite, also das gesamte benötigte HTML, CSS und JavaScript, geladen. Die Single Page fühlt sich also für den Benutzer nach einem längeren initialen Start responsiver an. Trotz ihrer Nachteile haben MPAs ihre Daseinsberechtigung. In Umgebungen, in denen JavaScript nur für die Unterstützung von Benutzern verwendet werden kann, nicht aber die gesamte Funktionalität der Applikation übernehmen darf, sind Sie auf MPA angewiesen. Vor allem im Bereich E-Commerce oder bei Anwendungen für öffentliche Auftraggeber stellt die Barrierefreiheit eine wichtige Anforderung dar. Und diese Barrierefreiheit ist nicht gewährleistet, wenn die Applikation nur mit dem Einsatz von JavaScript funktionieren kann.

Noch aufwändiger als bei den SPA wird es bei einer Echtzeitapplikation. Diese Art der Applikation stellt in den meisten Fällen eine Erweiterung der SPA dar. Bei einer Echtzeitapplikation besteht eine permanente Kommunikationsverbindung zwischen Client und Server, über die Informationen ausgetauscht werden. Diesen Kommunikationskanal können Sie über Technologien wie WebSockets oder Long Polling realisieren. Sie müssen sowohl auf dem Client wie auch auf dem Server mit eingehenden Daten umgehen können. Konkret bedeutet das, dass Sie neue oder geänderte Daten darstellen und im schlimmsten Fall mit Konflikten umgehen müssen. Aber auch für diese Problemstellungen existieren Bibliotheken, die Ihnen zumindest einen Teil der Arbeit abnehmen.

Navigation und Routing

Die Auswahl der Art der Applikation wirkt sich auch direkt auf die Navigation innerhalb Ihrer Applikation aus. Wo Sie bei einer MPA über eine klassische Navigation über Hyperlinks einfach von einer Seite zur nächsten springen können, besteht diese Möglichkeit bei einer SPA nicht. Nutzen Sie einen normalen Link, würden Sie die Seite neu laden, was dem Grundsatz der Single Page widerspricht. Also gilt es, die Navigation anderweitig zu realisieren. Ein sehr einfaches Mittel bietet hier die so genannte Hash-Navigation. Bei dieser Methode wird die Tatsache ausgenutzt, dass der URL einer Webseite nicht nur unter anderem aus dem Hostnamen und dem Pfad besteht, sondern auch noch das so genannte Fragment aufweist. Dieser Teil des URL ist vom Rest durch das Raute-Symbol (#) getrennt. Eigentlich dient dieses Fragment zur Navigation zu einem bestimmten Ankerpunkt innerhalb einer Webseite und führt so nicht zu einem erneuten Laden der Seite. Diese Tatsache macht sich die Hash-Navigation zunutze. Wird der Hash entweder durch das Betätigen eines Links oder durch das Ausführen von JavaScript geändert, wird ein Hash-Change-Event ausgelöst. Sie können innerhalb Ihrer Applikation auf derartige Events reagieren und bestimmte Aktionen wie beispielsweise die Anzeige bestimmter Komponenten ausführen. Eine Alternative zur Hash-Navigation bietet eine Funktionalität des HTML5-History-API, nämlich pushState. Dabei wird ein Statusobjekt einem URL zugeordnet. Dieses Objekt enthält weitere Informationen über den aktuellen Status der Applikation. Den initialen Status Ihrer Applikation setzen Sie durch einen Aufruf der replaceState-Funktion. Mit der pushState-Funktion können Sie einen neuen setzen und so weiter navigieren. Navigiert der Benutzer zurück in der Browserhistorie, wird das popState-Event ausgelöst, auf das Ihre Applikation entsprechend reagieren muss. Der Vorteil der pushState-Navigation gegenüber der Hash-Navigation ist, dass Sie weitere Informationen in Form eines Objekts übergeben und so den Status besser beschreiben können.

Das Ziel all dieser Bemühungen ist, dass zwei wichtige Features des Browsers unterstützt werden. Das erste ist der Zurück-Button. Viele Anwender sind es gewohnt, durch Betätigen dieses Buttons zurück zur vorhergehenden Seite zu gelangen. Bei einer SPA existiert diese vorherige Seite allerdings nicht, weil die Applikation ja nur aus dieser einen Seite besteht. Sowohl die Hash-Navigation als auch pushState bieten Ihnen allerdings die Möglichkeit, den Zurück-Button in Ihrer Applikation zu unterstützen. Das zweite Browserfeature, das durch diese Arten der Navigation unterstützt wird, sind Bookmarks. Nahezu jeder Status Ihrer Applikation wird durch einen eindeutigen URL identifiziert, die sich ein Benutzer speichern und zu einem späteren Zeitpunkt wieder aufrufen kann. Ein weiteres Einsatzgebiet von eindeutigen URLs, die einen Status innerhalb einer Applikation beschreiben, ist, dass ein Benutzer diesen URL an andere Personen weitergibt. Die Erwartungshaltung des Benutzers ist in beiden Fällen, dass er zum gleichen Stand der Applikation weitergeleitet wird. Aber auch dieser Anforderung wird Hash-Navigation und pushState gerecht.

Die perfekte Welt

Nach einer kurzen Einführung in die verschiedenen Arten von Webapplikationen und den Möglichkeiten der Navigation innerhalb einer Applikation, erfahren Sie nun, wie Sie Ihre Applikation am besten strukturieren können. Sehen Sie sich die aktuellen JavaScript-Frameworks an, finden Sie bei nahezu jeder Implementierung einen modularen Ansatz. Ein Modul ist, unabhängig von der konkreten Implementierung, eine in sich geschlossene Einheit. Diese Einheit kann von einem Stück JavaScript-Logik über eine Kombination von JavaScript und HTML bis hin zu einem vollständigen Widget reichen, das aus einem HTML-Template zur Strukturierung mit eigenem CSS für das Styling und JavaScript zur Abbildung der Logik besteht.

Module

Der Gedanke hinter der Modularisierung ist, dass Sie Ihre Software aus einzelnen unabhängigen Komponenten aufbauen. Diese Vorgehensweise ermöglicht es Ihnen, sich auf die Lösung der einzelnen Teilprobleme zu konzentrieren und sie im nächsten Schritt dann in einer Applikation zu integrieren. Der erste Vorteil, den Sie durch die Modularisierung erhalten, ist eine lose Kopplung der einzelnen Elemente Ihrer Applikation. Das bedeutet, dass Sie die Komponenten Ihrer Applikation weitestgehend unabhängig voneinander weiterentwickeln können. Außerdem sollte die Modularisierung dafür sorgen, dass eine defekte Komponente nicht automatisch dafür sorgt, dass Ihre Applikation in ihrer Gesamtheit unbenutzbar ist. In diesem Fall ist lediglich der Teil der Applikation nicht mehr funktionsfähig, der durch die Komponente abgedeckt wird. Ein weiterer Vorteil besteht darin, dass Sie die Module wiederverwenden können. So können Sie gezielt Duplikate im Quellcode Ihrer Applikation reduzieren, sodass Sie Fehlerbehebungen im Idealfall nur an einer Stelle durchführen müssen und sich diese dann an allen Stellen auswirken, an denen die fehlerhafte Komponente verwendet wird. Durch einen modularen Ansatz beim Aufbau Ihrer Applikation profitieren Sie außerdem davon, dass Sie bei größeren Applikationen die Module von unterschiedlichen Teams entwickeln lassen können. Sind die Abhängigkeiten zwischen den Modulen so gering, dass sie sich nur auf definierte Schnittstellen beschränken, kann der Einsatz mehrerer Teams dafür sorgen, dass Sie mehr Features in geringerer Zeit implementieren und Ihren Benutzern zur Verfügung stellen können.

Struktur einer Multi-Page-Applikation

Bei der Strukturierung einer Applikation unterscheiden sich die Single-Page- und Multi-Page-Ansätze erheblich voneinander. Wo Sie bei einer SPA separate Logik benötigen, um das Routing und damit die Navigation zu implementieren, nimmt Ihnen der Browser diese Problemstellung bei einer MPA bereits ab. Bei einer MPA müssen Sie also nur dafür sorgen, dass auf einer Seite sämtliche benötigten Komponenten zur Verfügung stehen. Gehen Sie beispielsweise von einem Klassiker einer MPA, einem Webshop, aus, haben Sie im Wesentlichen zwei Seiten. Das sind zum einen die Produktübersichtsseite und zum anderen die Produktdetailseite. Die übrigen Seiten sind meist statisch oder bestehen aus Formularen. Die Übersichtsseite besteht neben der Navigation und der Kopfzeile mit Logo und Banner aus der eigentlichen Produktliste. Mit dieser Aufzählung an Komponenten haben Sie schon einen ersten Anhaltspunkt von Modulen auf Ihrer Seite. Die JavaScript-Logik, die Sie für Ihre Seite benötigen, sollten Sie entsprechend Ihrer Komponenten gruppieren. Häufig findet sich auf solchen Übersichtsseiten außerdem noch eine Toolbox, die dem Einkaufenden zusätzliche Hilfsmittel bietet. Auch hier bietet sich ein Ansatzpunkt für eine weitere Komponente.

Die HTML-Struktur von MPAs wird im Normalfall bereits auf dem Server korrekt zusammengesetzt. Das bedeutet, dass Sie die Komponenten Ihrer Module serverseitig schon korrekt unterteilen müssen und die Template-Engine Ihres Servers den Zusammenbau übernimmt. Für jedes Modul, also beispielsweise die Tabelle, die die Produktdarstellung auf der Übersichtsliste übernimmt, existieren dann ein oder mehrere Templates, CSS- und JavaScript-Dateien. Im nächsten Schritt müssen Sie nun dafür sorgen, dass die Seite mit ihren Modulen zum Benutzer geschickt wird. Hier gibt es einige weitere Dinge zu beachten. Sie sollten stets dafür sorgen, dass möglichst wenige Requests an den Server notwendig sind, um Ihre Seite auszuliefern. Außerdem sollten die Antworten auf die benötigten Requests möglichst optimiert sein. Das bedeutet, dass Sie die JavaScript- und CSS-Dateien jeweils zu einer Datei zusammenfassen und diese durch einen Minifier optimieren lassen sollten, um Übertragungsvolumen zu sparen. Das wird vor allem relevant, wenn Ihre Applikation auch für mobile Geräte benutzbar sein soll, wo Bandbreite momentan durchaus noch eine Rolle spielt. Die Zusammenfassung von JavaScript und CSS können Sie entweder pro Seite spezifisch durchführen, sodass Sie eine Datei für die Übersichtsseite und eine andere für die Detailseite ausliefern. Eine andere Alternative besteht darin, dass Sie sämtliches JavaScript und CSS auf einmal ausliefern und dies dann durch den Browser cachen lassen.

Struktur einer Single-Page-Applikation

Wo der Einsatzzweck von JavaScript bei einer MPA noch recht begrenzt ist, da hier die Applikation meist auch ohne JavaScript benutzbar sein muss, haben Sie bei einer SPA die gesamte Bandbreite der Möglichkeiten von JavaScript zur Verfügung. Bei einer Single-Page-Applikation können Sie davon ausgehen, dass Ihre Benutzer über einen halbwegs aktuellen Browser verfügen und JavaScript aktiviert haben. Eine SPA kann nur mit aktiviertem JavaScript funktionieren, da andernfalls keine Navigation möglich ist. Sie können eine SPA zwar ohne Probleme ohne weitere Unterstützung eines Frameworks entwickeln, dieses Vorgehen ist allerdings nicht empfehlenswert, da das lediglich bedeuten würde, das Rad neu zu erfinden. Allgemein gilt, man sollte zumindest einmal ein Framework gemeistert haben, bevor man sich selbst an die Arbeit macht, ein eigenes Framework zu schreiben.

Bei Frameworks für SPA geht der Trend aktuell ebenfalls zur Modularisierung. Konkret bedeutet das, dass sich die Frameworks lediglich um einen bestimmten Aspekt der Applikationsentwicklung kümmern und alle übrigen Aufgaben anderen Frameworks oder Bibliotheken überlassen. Zwei populäre Vertreter dieser leichtgewichtigen Art von Strukturframeworks sind AngularJS und Backbone.js. Beide Frameworks bieten Ihnen eine Möglichkeit, um Ihre SPA zu strukturieren. Die Interaktion mit dem Benutzer findet, wie im Web üblich, über HTML statt. Das bedeutet aber im Rückschluss auch wieder, dass das Framework eine Möglichkeit zur Manipulation des DOM benötigt. Nach dem Motto „Das Rad nicht neu erfinden“ setzen sowohl AngularJS als auch Backbone.js für diese Aufgabe auf jQuery. AngularJS bringt beispielsweise eine abgespeckte Version von jQuery mit, wobei Sie dennoch die Möglichkeit haben, ein vollwertiges jQuery einzusetzen, auf der das Framework dann aufbaut. Backbone.js macht das Vorhandensein von jQuery zur Abhängigkeit. jQuery lässt sich in diesem Fall auch durch das leichtgewichtigere und weitestgehend API-kompatible Zepto ersetzen. AngularJS und Backbone.js stellen allerdings nur eine sehr kleine Auswahl von Frameworks dar, die Sie bei der Strukturierung Ihrer Applikation unterstützen. Aktuell entsteht eine Vielzahl derartiger Lösungen. Sowohl Backbone.js als auch AngularJS haben sich jedoch mittlerweile etabliert und kommen bei zahlreichen Webapplikationen zum Einsatz. Die Geschichte von Backbone.js lässt sich über mehr als drei Jahre bis zum initialen Commit auf GitHub verfolgen. Die Grundsteinlegung von AngularJS fand sogar noch etwas früher, nämlich bereits 2009, statt. Diese Art von Frameworks unterstützt den MV*-Ansatz der Strukturierung einer Applikation. MV* aus dem Grund, weil Sie hier mehrere Varianten unterscheiden müssen. Die Basis bildet MVC – das Model-View-Controller-Pattern. Daraus haben sich weitere Entwurfsmuster wie MVVM und MVP ergeben, wobei die Zuordnung zu einem konkreten Muster in den meisten Fällen schwierig und nicht immer eindeutig ist.

MVC – Model View Controller

Backbone.js ist ein Vertreter der MVC-Frameworks. Den Controller bildet bei Backbone.js der Router. Dieser sorgt dafür, dass URLs, die entweder durch pushState oder Hash-Navigation aktiviert werden, auf Funktionen gemappt werden. Diese Funktionen sind am ehesten mit den Controller Actions aus serverseitigen Frameworks vergleichbar. Sie sorgen dafür, dass Models und Views miteinander verbunden werden. Die Models halten dabei die Daten der Applikation und die clientseitige Geschäftslogik. Zum Erstellen, Auslesen, Ändern und Löschen von Informationen wird bei Backbone.js REST verwendet. Ein Model wird über eine eindeutige ID identifiziert und die entsprechende URL des Servers im Model-Objekt hinterlegt. Die Darstellung der Daten übernimmt schließlich das View-Objekt. In diesem Objekt wird sowohl das Template, in dem die Daten angezeigt werden als auch die Darstellungslogik gekapselt. Eine Erweiterung von Backbone.js sind die so genannten Collections. Das sind Sammlungen von gleichartigen Models, die am ehesten noch mit einem Array verglichen werden können, allerdings darüber hinausgehende Funktionalität bieten. Backbone.js stellt Ihnen lediglich diese Komponenten zur Verfügung. Benötigen Sie weitere Komponenten, können Sie auf zusätzliche Module zugreifen, die andere Entwickler als Erweiterung für Backbone.js erstellt haben. Abbildung 1 zeigt das grundlegende Schema von MVC.

Abb.1: Das Prinzip von MVC

Abb.1: Das Prinzip von MVC

 

Eine Variante des MVC Patterns stellt MVVM dar.

MVVM – Model View ViewModel

Das Ziel des MVVM Patterns (Abb. 2) ist, dass es mit den Nachteilen des MVC Patterns umgehen soll und die Anzeigelogik besser von den Templates trennt. AngularJS war ursprünglich wie Backbone.js als MVC-Framework gedacht. Mittlerweile wird AngularJS, durch eine bessere Trennung der Anzeigelogik und der View-Komponente, als MVVM-Framework bezeichnet. AngularJS verfügt wie auch Backbone.js über eine Routing-Funktionalität, mit der Sie Hash-Navigation betreiben können. Das erste M steht bei MVVM für Model. Das Model ist bei AngularJS eine freie Datenstruktur. Sie unterliegen hier also keinerlei Beschränkung, was die Struktur Ihrer Models angeht. Als View-Komponente dient AngularJS der DOM. Im Controller bauen Sie über ein spezielles Scope-Objekt, das ViewModel, eine Verbindung zwischen Model und View auf. AngularJS bietet Ihnen ein so genanntes Two-Way Data Binding: Ändern sich die Informationen des Models, wird gleichzeitig die View aktualisiert. Ändert ein Benutzer in der View die Datenrepräsentation des Models, wirkt sich diese Änderung gleichzeitig auf das Model aus.

Mit den Services von AngularJS können Sie Funktionen auslagern. Sie können in den Services beispielsweise die Businesslogik Ihrer Applikation implementieren. Das letzte wesentliche Feature von AngularJS sind die Direktiven. Sie dienen dazu, das Vokabular von HTML zu erweitern. Das bedeutet, Sie definieren eine Direktive und können diese durch die Angabe eines Attributs aktivieren.

Zur Speicherung von Daten auf dem Server können Sie auf fertige Services zurückgreifen, die Ihnen AngularJS zur Verfügung stellt. Durch das Konzept der Services können Sie die Komponenten Ihrer Applikation weiter entkoppeln. Durch das Konzept der Dependency Injection wird Ihr Quellcode außerdem besser testbar. Sämtliche Abhängigkeiten nach außen werden als Abhängigkeit in eine Funktion als Argument übergeben. Bei einem Test können Sie eine konkrete Abhängigkeit durch ein Stub-Objekt ersetzen.

Abb. 2: Der Aufbau von MVVM

Abb. 2: Der Aufbau von MVVM

 

Module Loader

Einen Nachteil hat die Modularisierung allerdings: Sie müssen alle Dateien laden, die Sie für Ihre Applikation benötigen. Im schlimmsten Fall endet das in einer Vielzahl von script-Tags, die dafür sorgen, dass alle Dateien verfügbar sind. Noch problematischer wird die Situation, wenn die einzelnen Dateien Abhängigkeiten untereinander aufweisen.Eine Lösung für dieses Problem bietet ein Modul Loader. Die Aufgabe dieses Werkzeugs ist es, sich um das Laden von Dateien und die Auflösung von Abhängigkeiten zu kümmern. Einer der am weitesten verbreiteten Modul Loader ist RequireJS. Benutzen Sie RequireJS, müssen Sie lediglich ein script-Tag in Ihre Applikation einfügen, das dafür sorgt, dass RequireJS geladen wird. In diesem script-Tag geben Sie außerdem an, wo sich die Konfiguration für RequireJS befindet. RequireJS stellt Ihnen zwei globale Funktionen bereit. Mit define definieren Sie neue Module. Sie können dieser Funktion drei Argumente übergeben. Das erste besteht aus einer Zeichenkette und gibt den Namen des Moduls an, das zweite Argument ist ein Array von Abhängigkeiten, die vor diesem Modul geladen werden müssen. Das dritte Argument ist eine Funktion, die das eigentliche Modul darstellt. Diese Funktion erhält als Argumente die zuvor angegebenen Abhängigkeiten, sodass Sie diese innerhalb der Funktion verwenden können. Der Rückgabewert des Moduls kann dann wiederum in anderen Modulen als Abhängigkeit verwendet werden.

Die zweite Funktion von RequireJS lautet require. Mit ihr definieren Sie Module, die Sie nicht als Abhängigkeit in anderen Modulen benutzen möchten, sondern lediglich in Ihre Applikation einbinden. Mit RequireJS erhalten Sie außerdem einen Optimizer, der es Ihnen erlaubt, die einzelnen Dateien Ihrer Applikation zu einer einzigen Datei zusammenzufassen. Dieser Optimizer heißt r.js und kann sowohl mit Node.js als auch mit Rhino benutzt werden. Eine Alternative zu RequireJS als Modul Loader stellt CommonScript dar. Dieser Module Loader verfolgt eine komplett andere Strategie als RequireJS. Zunächst hält sich CommonScript an den von CommonJS vorgeschlagenen Standard, bei dem Module durch module.exports definiert werden wie auch beispielsweise bei Node.js. Der nächste Unterschied ist, dass CommonScript die benötigten Dateien per AJAX nachlädt. Für größere Projekte ist allerdings RequireJS als Modul Loader eher zu empfehlen, da es bereits seit mehreren Jahren etabliert ist und außerdem über einen Optimizer verfügt.

Zusammenfassung

Grundsätzlich ist es wichtig, dass Sie die Architektur Ihrer Applikation passend zur Problemstellung auswählen. Sie sollten immer darauf achten, dass Sie mehrere Architekturvarianten zur Auswahl haben und daraus die am besten passende wählen. Neben Kriterien wie Skalierbarkeit und Erweiterbarkeit kann auch die Erfahrung der Programmierer mit dieser Architektur beziehungsweise mit bestimmten Frameworks ein entscheidender Faktor sein. Die Architektur einer Applikation lässt sich grob in drei Teile untergliedern:

  1. Die Grundlage Ihrer Applikation bildet das Basisframework. Seine Aufgabe ist es, sich um grundlegende Funktionen wie die Manipulation des DOM oder AJAX zu kümmern. Ein Beispiel für ein solches Framework ist jQuery. Auf dieser Grundlage baut der eigentliche Kern der Applikation auf.
  2. Dieser Kern gibt die Struktur der Applikation vor. Typisch für diese Stufe der Architektur sind Frameworks wie AngularJS oder Backbone.js. Auf diesem Kern bauen schließlich die Module Ihrer Applikation auf.
  3. Die Module sollten untereinander über möglichst wenige Abhängigkeiten verfügen, damit Sie eine möglichst lose Kopplung innerhalb Ihrer Applikation erreichen.

Mit einem modularen Ansatz erreichen Sie eine hohe Wartbarkeit und Erweiterbarkeit Ihrer Applikation.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -