Warum AngularJS auch für Java-Entwickler interessant ist

Module und Dependency Injection

Die Bedeutung und die Vorteile von Modularisierung und Dependency Injection sollten allen Entwicklern bekannt sein. Martin Fowlers Artikel zu DI [4] gehört meiner Meinung nach zur Pflichtlektüre. In Listing 3 sehen wir ein Beispiel sowohl für die Definition von Modulen als auch für DI in AngularJS. Module werden über angular.module registriert (Zeile 1) und können, wie am zweiten Parameter zu sehen, von anderen Modulen abhängen. Angular bietet dann über Method Chaining die Möglichkeit, Services, Controller, Direktiven usw. zu einem Modul hinzuzufügen (Zeile 2). Unser Service usefulService hat eine Abhängigkeit zum Service $window, den AngularJS mitbringt und der das globale window-Objekt per DI zur Verfügung stellt. Dieser Service wird bei der Erstellung unseres Services per DI bereitgestellt – genauso wie usefulService in myModule und alle Module, die von myModule abhängen. Unser Service besteht dabei lediglich aus einer Funktion (return in Zeile 3), die beim Aufruf das Fenster schließt (Zeile 4); sehr nützlich also.

Da JavaScript eine dynamisch typisierte Sprache ist, werden auch für Funktionsparameter keine Typen angegeben. Woher weiß AngularJS dann, was beim Funktionsaufruf bzw. bei der Service-Instanziierung injiziert werden muss? Angular verwendet hierfür Namen, sowohl bei der Registrierung als auch bei der Referenzierung. Dieser Mechanismus hat jedoch ein Problem: Codekompressoren ersetzen gerne die Namen von Funktionsparametern durch möglichst kurze, um die Dateigröße zu verringern (Zeile 2 und 4, Parameter a, eigentlich $window). Um dennoch die benötigte Information, den Namen der Abhängigkeit, zu bewahren, kann man statt der Funktion ein Array übergeben. Dieses Array enthält einen String für jeden Funktionsparameter sowie als letztes Element die Funktion selbst. Da die Namen der Abhängigkeiten jetzt als Strings im Code stehen (Zeile 2, erstes Array-Element), gehen sie bei der Kompression nicht verloren. Nachteil ist, dass man jeden Namen zweimal schreiben muss.

Listing 3
angular.module('myServiceModule', ['moduleOfOtherLibrary'])
.service('usefulService', ['$window', function(a) {
  return function() {
    a.close();
  }]
};
Testbarkeit

UI-Tests sind noch immer ein schwieriges Thema. Durch die Kombination von MVC und DI erreichen wir mit AngularJS bei Webanwendungen aber ein neues Niveau an Testbarkeit unseres UI-Codes. Schauen wir uns dafür noch einmal unseren usefulService in Listing 3 an. Wollen wir diesen Service testen und der Test läuft nicht in einem Browser, sondern in einer headless JavaScript-Testumgebung, steht höchstwahrscheinlich kein window-Objekt bereit. Da wir aber nicht das global verfügbare window-Objekt, sondern den AngularJS-Service $window verwenden, kann dieser sehr einfach durch einen Mock ersetzt werden. Dazu müssen wir lediglich im Modul ng den Mock unter dem Namen $window registrieren. Anschließend können wir beim Injector unseren usefulService erfragen, der dann den Mock nutzt. Ähnlich sieht es beim Testen von Controllern und somit der eigentlichen UI-Logik aus. Durch die strikte Vermeidung der Nutzung globaler Variablen und Service-Lookups oder gar hart kodierter Abhängigkeiten kann fast alles durch Mocks ersetzt werden. Da Controller zudem keinen Zugriff auf DOM-Elemente enthalten (sollten), sondern mit der View nur über den Scope kommunizieren, können auch diese ohne echten Browser und ohne UI getestet werden. Der Testcode kann dann den Zustand des Scope-Objekts und Aufrufe bei den Service-Mocks überprüfen. Zusätzlich kann natürlich weiterhin z. B. mit Silenium [5] das tatsächlich gerenderte UI samt dessen Verhalten getestet werden. Der notwendige Umfang dieser Tests und damit die Fehleranfälligkeit der Tests im Allgemeinen dürfte jedoch stark abnehmen. Außerdem können die Tests deutlich schneller ausgeführt werden, am besten gleich ständig während des Entwickelns.

Kommentare
  1. Johanna FLYACTS2014-11-26 15:54:41

    Auch wir haben uns in letzter Zeit viel mit AngularJS und Möglichkeiten von Plugins, Directiven und Modulen beschäftigt. Dabei ist ein Modul entstanden, das den Umgang mit der API ein wenig vereinfacht. Es ermöglicht die Anzeige von Daten eigener Analytics-Konten, beispielsweise auf Webseiten oder mobilen Apps. Damit können ganz einfach DataCharts oder ViewSelectors zugefügt und sogar verbunden werden.
    Für weitere Informationen: http://www.flyacts.com/blog/angularjs-google-analytics-embed-api-nganalytics/

    Das Modul auf Github: https://github.com/flyacts/ngAnalytics

    Viel Erfolg und danke für den tollen Artikel.

    Grüße Johanna

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.