mit angularjs projekte schnell an die wand fahren. © 2015 andrena objects ag experts in agile...
TRANSCRIPT
© 2015 andrena objects ag
Experts in agile software engineering
Häufige Fehler und wie sie sich vermeiden lassen
Rouven Röhrig
Mit AngularJS Projekte schnell an die Wand fahren
© 2015 andrena objects ag
Experts in agile software engineering 2
Agenda
1. Herausforderungen in Enterprise-JavaScript-Projekten
2. Was ist AngularJS und was bietet es
3. Wie man Projekte an die Wand fährt… und wie man es verhindert
4. Zusammenfassung und Ausblick
© 2015 andrena objects ag
Experts in agile software engineering 3
Agenda
1. Herausforderungen in Enterprise-JavaScript-Projekten
2. Was ist AngularJS und was bietet es
3. Wie man Projekte an die Wand fährt… und wie man es verhindert
4. Zusammenfassung und Ausblick
© 2015 andrena objects ag
Experts in agile software engineering 4
Herausforderungen in Enterprise-JavaScript-Projekten
• Kein Compiler
• Keine „natürliche“ Strukturierung
• Loser Zusammenhang der Dateien
• Dynamische Typisierung
• Kein „Klassen“-Konzept
• Asynchronität
• Client-seitige Ausführung
© 2015 andrena objects ag
Experts in agile software engineering 5
Agenda
1. Herausforderungen in Enterprise-JavaScript-Projekten
2. Was ist AngularJS und was bietet es
3. Wie man Projekte an die Wand fährt… und wie man es verhindert
4. Zusammenfassung und Ausblick
© 2015 andrena objects ag
Experts in agile software engineering 6
Was ist AngularJS?
• Client-seitiges JS für interaktives HTML
• Kümmert sich um die Abhängigkeiten der Dateien
• Hilft beim Strukturieren (u.a.) durch das MVVM-Pattern
• Entworfen für eine hohe Testbarkeit (UI- und Unit-Testing)
• Ermöglicht „expressive HTML“
JavaScript-Framework für Single-Page-Applikationen
© 2015 andrena objects ag
Experts in agile software engineering 7
Was ist eine Single-Page-Applikation?
Webseite aufrufen HTTP requests
Antwort(en) mit Dateien (HTML, CSS, JS etc.)
Webseite aufbauen
Link anklicken
Webseite aufrufen HTTP requests
Antwort(en) mit Dateien (HTML, CSS, JS etc.)
Webseite aufbauen
Link anklicken (HTTP requests)
Send updates
Klassische Webseite Single-Page-Applikation
© 2015 andrena objects ag
Experts in agile software engineering 8
Was ist „expressive HTML“? <div> <div> <div> <span>9</span> <span>1</span > ... </div> <div> <span> </ span > ... </div> ... </div> </div>
<sudoku> <grid> <row id="row1"> <cell id="r1c1">9</cell> <cell id="r1c2">1</cell> ... </row> <row id="row2"> <cell id="r2c1"> </cell> ... </row> ... </grid> </sudoku>
© 2015 andrena objects ag
Experts in agile software engineering 9
MVW-Pattern: Model-View-Whatever-Pattern
• Manche sagen Angular basiert auf dem MVC-Pattern
• Andere (darunter der Referent) sagen es entspricht eher dem MVVM-Pattern
• Angular sagt es ist ein Model-View-Whatever-Pattern1:
• Stellen Sie es sich so vor, wie es für Sie am meisten Sinn ergibt!
• … Angular sagt aber auch „[…] it's now closer to MVVM.“
Angular ermöglicht die Trennung von View und Logik
1 AngularJS: MVC vs MVVM vs MVP, https://plus.google.com/+AngularJS/posts/aZNVhj355G2, 19 Juli 2012
© 2015 andrena objects ag
Experts in agile software engineering 10
Angulars wichtigste Konzepte
• Dependency Injection
• Two-Way-Databinding
• Expressive HTML
© 2015 andrena objects ag
Experts in agile software engineering 11
Angulars wichtigste Bausteine
• Expressions
• Direktiven
• Controller
• Services
• Module
© 2015 andrena objects ag
Experts in agile software engineering 12
Controller im MVVM
View DOM
ViewModel Controller
stellt Daten und Methoden zur
Verfügung
Model nicht
festgelegt in Angular
Databinding ?
© 2015 andrena objects ag
Experts in agile software engineering 13
Two-way-Databinding
Hallo!
.controller('MyController', function() {
this.helloWorld = 'Hello World!';
this.input;
});
Hello World!
// 'Hallo!'
© 2015 andrena objects ag
Experts in agile software engineering 14
Zusammenspiel Direktive
HTML partial template
Direktive
Cont roller
Service HTML partial
Service
Service
Service
Direktive
Direktive
Service
HTML partial
Cont roller
HTML partial
Cont roller
Cont roller
© 2015 andrena objects ag
Experts in agile software engineering 15
Agenda
1. Herausforderungen in Enterprise-JavaScript-Projekten
2. Was ist AngularJS und was bietet es
3. Wie man Projekte an die Wand fährt… und wie man es verhindert
4. Zusammenfassung und Ausblick
© 2015 andrena objects ag
Experts in agile software engineering 16
Problem: Unzureichende Automatisierung
• Problematik:
• Manuelle Pflege der Abhängigkeiten
• Tests geben kein schnelles Feedback
• Es gibt keinen automatisierten Build-Prozess
• Build-Server ohne Build- und Test-Ergebnis
• => Tests werden vernachlässigt
• => Produktivitätsverlust
• => Nachgelagerte Automatisierung ist oft teuer!
„Wir fangen erst einmal an und automatisieren später“
© 2015 andrena objects ag
Experts in agile software engineering 17
Besser: Erst Automatisieren, dann Entwickeln
• JavaScript-basierte Anwendungen lassen sich sehr gut automatisieren
• Automatisierung muss mitwachsen
• Umso später automatisiert wird, umso aufwendiger
-> Geeignete Werkzeuge sind notwendig!
Wir machen Automatisierung zur Voraussetzung!
© 2015 andrena objects ag
Experts in agile software engineering 18
Besser: Erst Automatisieren, dann Entwickeln (2)
• NodeJS und npm für Entwicklungsabhängigkeiten
• npm als Command-line-tool
• npm als einziger Einstiegspunkt für
• Abhängigkeitsmanagement und Installation
• Build-Prozess
• Testausführung (Unit und GUI)
• Grunt oder Gulp? JA, Faustregel: „npm wenn möglich, Grunt/Gulp wenn nötig“
Build-Prozess: NodeJS und npm
© 2015 andrena objects ag
Experts in agile software engineering 19
Besser: Erst Automatisieren, dann Entwickeln (3)
package.json
Build-Prozess: npm als einziger Einstiegspunkt
install Entwicklungsabhängigkeiten postinstall: Frontend-Abhängigkeiten test: Unit-Tests e2e-test: UI-Tests taskXY: gulp complicated-job …
… gulp.task('complicated-job', …); …
gulpfile.js
© 2015 andrena objects ag
Experts in agile software engineering 20
Besser: Erst Automatisieren, dann Entwickeln (4)
• Beliebiges JavaScript-Projekt, beliebiger Rechner:
• Voraussetzung: NodeJS und git
1. git clone…
2. npm install (Installiert ALLE Abhängigkeiten lokal)
3. npm test (führt Tests aus)
4. npm start (optional: startet Webserver)
-> Komplexität massiv reduziert
Standardisierte autarke Projekte durch npm
© 2015 andrena objects ag
Experts in agile software engineering 21
Besser: Erst Automatisieren, dann Entwickeln (5)
• npm für Entwicklungsabhängigkeiten
• bower für Frontend-Abhängigkeiten
• Vorteile:
• Trennung von Frontend und Backend-Abhängigkeiten.
• Flacher Abhängigkeitsgraph
Bower für Frontend-Abhängigkeiten
© 2015 andrena objects ag
Experts in agile software engineering 22
Problem: Keine oder kaum GUI-Tests
• Problematik:
• Fehler treten trotz Unit-Tests auf
• Aufwand des manuellen Testens steigt
• Fehler bleiben lange unentdeckt
• => Äußere Qualität ist schlecht
• => Späte Automatisierung offenbart schlecht testbares HTML
© 2015 andrena objects ag
Experts in agile software engineering 23
GUI-Tests ab der ersten Seite
• GUI-Tests sind aufwendig und veralten schnell
• Auf wichtige Use Cases konzentrieren
-> Smoke-Tests
• Testbare HTML-Komponenten benötigen IDs
• Klassen sind fehleranfälliger
Das Gesamtsystem testen
<row id="row1"> <cell id="r1c1"> … </cell> <cell id="r1c2"> … </cell> … </row> <row id="row2"> <cell id="r2c1"> … </cell> … </row>
© 2015 andrena objects ag
Experts in agile software engineering 24
GUI-Tests: Page Object Pattern
• Egal ob Protractor oder Selenium, Java oder JavaScript: Page Objects!
• Ein Page Object
• repräsentiert eine Webseite
• weiß wie man darauf zugreift
• kennt Page Objects verlinkter Seiten
• Tests verwenden Page Objects statt eigene Locator
• Vorteil: Ändert sich eine Webseite, ändert sich nur ein Page Object
© 2015 andrena objects ag
Experts in agile software engineering 25
GUI-Tests: Page Object Pattern (2)
describe('Login Page', function() {
it('a user can login', function() {
var loginPage = new LoginPage();
loginPage.get();
loginPage.setUsernameAndPassword('user1', 'abc');
var overviewPage = loginPage.clickLoginExpectSuccess();
expect(overviewPage.isDisplayed()).toBe(true);
});
});
Eine von vielen Möglichkeiten, die auf die Folie
gepasst hat!
Für Page Objects bieten
sich auch „Singletons“ an!
© 2015 andrena objects ag
Experts in agile software engineering 26
GUI-Tests: Page Object Pattern (3)
function LoginPage() {
this.get = function () {
return browser.get('/#/login');
};
this.setUsernameAndPassword = function(username, password) {
element(by.id('login-username')).sendKeys(username);
element(by.id('login-password')).sendKeys(password);
};
this.clickLoginExpectSuccess = function() {
element(by.id('login-button')).click();
return new OverviewPage();
};
}
Eine von vielen Möglichkeiten, die auf die Folie
gepasst hat!
© 2015 andrena objects ag
Experts in agile software engineering 27
Problem: Keine oder wenig Unit-Tests
• Problematik:
• Viele Fehler
• Fehler werden spät entdeckt
• Entwicklung per „Trial and Error“
• Schlecht wartbarer und nicht testbarer Code
• => Schlechte innere und äußere Qualität
• => langsame riskante Entwicklung
„Das Frontend lässt sich nicht Unit-Testen“
© 2015 andrena objects ag
Experts in agile software engineering 28
Besser: Von Anfang an Unit-Tests
• Testbarkeit ist wichtige Metrik für Qualität
• In Angular: „Nur ein testbarer Controller kann ein guter Controller sein“
• Frontend-Code lässt sich auch testen (Direktiven und Controller)
• Strikte Trennung von View und Logik
• Controller darf nicht vom DOM abhängen (nur Zustand und Methoden)
• Direktiven:
• Operationen möglich mit Tools
• Fokus auf Controller
Noch besser: TDD oder Test-first
© 2015 andrena objects ag
Experts in agile software engineering 29
Besser: Von Anfang an Unit-Tests (2)
• Test-Framework: Jasmine oder Mocha
• Test-Runner: Karma
• Testausführung in verschiedenen Browsern
• Viele Erweiterungen:
• Code-Coverage
• Ergebnis für Build-Server (z.B. Jenkins)
• Automatisierung:
• npm führt Karma aus, Karma führt Jasmine-Tests aus
Geeignete Werkzeuge
© 2015 andrena objects ag
Experts in agile software engineering 30
Besser: Von Anfang an Unit-Tests (3)
• Viele Projekte haben einen größeren Build-Prozess
• z.B. Minification, Uglification, Sass-Build etc.
• Häufig muss der Code gebaut werden, bevor er getestet wird
• Okay und gut für Build-Server
• Schlecht für TDD und schnelles Feedback
• Empfehlung: Unit-Tests müssen auch ohne Build laufen
• Oder watch-Task für Entwickler der wirklich schnell ist
Automatisierung ≠ Automatisierung
© 2015 andrena objects ag
Experts in agile software engineering 31
Problem: Keine einheitlichen Codekonventionen
• Problematik:
• Flüchtigkeitsfehler schleichen sich ein
• Einfache Programmierfehler treten auf
• Schlechte Lesbarkeit und Wartbarkeit
• => Verringerte Softwarequalität
• => Verringerte Produktivität
© 2015 andrena objects ag
Experts in agile software engineering 32
Codekonventionen durchsetzen
• Statische Codeanalyse
• überprüft Codekonventionen und findet typische Fehler
• Bekannte Linter:
• JSLint: Fester Standard
• JSHint: Konfigurierbar
• ESLint: Konfigurierbar und erweiterbarer
• Zusätzlich: HTML validieren
=> Gute IDEs integrieren Linter-Errors
Linter findet einfache Fehler und stellt Konventionen sicher
© 2015 andrena objects ag
Experts in agile software engineering 33
Problem: IDE unterstützt JavaScript unzureichend
• Problematik: Schlechter oder kein JavaScript-Support
• Kein Syntax-Highlighting
• Keine Funktionen
• Keine automatisierten Refactorings
• Keine Linter-Integration
• => Langsame Entwicklungsgeschwindigkeit
• => Viele überflüssige Fehler
„Wir entwickeln schon immer mit <BLANK>.“
© 2015 andrena objects ag
Experts in agile software engineering 34
Eine IDE mit guter JavaScript-Integration
• WebStorm (kommerziell)
• Brackets, Atom, Sublime et al. (nicht-kommerziell)
• Visual Studio (kommerziell)
=> Aufwand und Kosten amortisieren sich schnell!
Folgende IDEs bieten eine Integration
© 2015 andrena objects ag
Experts in agile software engineering 35
Problem: Code-Duplikationen
• Problematik:
• Änderungen müssen an vielen Stellen erfolgen
• Gefixte Fehler tauchen wieder auf
• Features sind nicht an allen Stellen implementiert
• => Änderungen und Erweiterungen sind teuer
• => Zunehmend unwartbarer Code
• => Schlechte Codequalität
© 2015 andrena objects ag
Experts in agile software engineering 36
Keine Code-Duplikationen
• HTML-Duplikationen
• Controller-unabhängig: Template-Direktive
• Controller-abhängig: Direktive (mit eigenem Controller)
• Duplikationen im Controller:
• Wiederverwendbarer Service
• JavaScript-Objekt
Aber wie?
© 2015 andrena objects ag
Experts in agile software engineering 37
Keine Code-Duplikationen (2)
• Objekte können on-the-fly erzeugt werden
-> Führt zu Code-Duplikationen
function Message(title, content) {
this.title = title;
this.content = content;
} var message = {
title: 'a title',
content: 'a message'
};
.factory('Message', function() {
return Message;
});
JavaScript-Objekte explizit modellieren
Eine von vielen Möglichkeiten, die auf die Folie
gepasst hat!
Besser
© 2015 andrena objects ag
Experts in agile software engineering 38
Keine Code-Duplikationen (3)
• Methodik:
• Große Controller lassen sich schlecht testen, daher: TDD!
-> Kann ich einen Controller schwer Unit-Testen, ist er häufig zu groß.
• Werkzeuge:
• Services: (Wiederverwendbare) Logik auslagern
• Template-Direktiven: (Wiederverwendbare) HTML-Templates
• Direktiven: (Wiederverwendbare) UI-Aspekte kapseln
Kleine Controller, Direktiven und Services
© 2015 andrena objects ag
Experts in agile software engineering 39
Problem: ng-controller statt Direktiven
• Problematik:
• ng-controller wird verwendet
• HTML-Code-Duplikationen
• Ähnliche oder duplizierte Controller
• => Komplizierte Scope-Abhängigkeiten
• => Schwer verständlicher Code
• => Duplizierter Code
© 2015 andrena objects ag
Experts in agile software engineering 40
Besser: Domänenspezifische Sprache mit Direktiven
• Eine Direktive ist in sich abgeschlossen, bestehend aus:
• HTML-Template
• Controller
• Styling
• Unit-Test ;-)
• Eine Direktive manipuliert nur ihren eigenen DOM
Direktiven sind das Feature von AngularJS
© 2015 andrena objects ag
Experts in agile software engineering 41
Besser: Domänenspezifische Sprache mit Direktiven (2)
.directive('infobox', function() {
return {
templateUrl: 'infobox.html',
controller: function() {...},
controllerAs: 'infobox',
scope: {
'text': '@',
},
bindToController: true
};
});
<div class="alert alert-info"> {{infobox.text}} <div>
<infobox text="Hello World!"/>
https://jsbin.com/lonifo
Hello World!
infobox{ /* styling */ }
© 2015 andrena objects ag
Experts in agile software engineering 42
Besser: Domänenspezifische Sprache mit Direktiven (3)
.directive('anotherDirective',
function() {
return {
/*…*/
};
});
<infobox ng-if="{{anotherDirective.someCondition}}" text="{{anotherDirective.status}}"/> <input … /> <button .../>
anotherDirective{ /* styling */ }
© 2015 andrena objects ag
Experts in agile software engineering 43
Problem: Callback-based APIs
• Problematik:
• Führt meist in die „Callback Hell“ [1]
• Abhängigkeiten schlecht parallelisierbar
• Aufwendige Fehlerbehandlung
• Keine Trennung von Fehler- und Erfolgsfall
[1] http://callbackhell.com/
© 2015 andrena objects ag
Experts in agile software engineering 44
Besser: Promise-based APIs
• Promises ermöglichen
• Einheitliches API-Design
• Trennung von Fehler- und Erfolgsfall
• „Promise chaining“
• Sauberer Code
=> Achtung Design und Testing eigener APIs ist dennoch anspruchsvoll
Angular bietet eigene API für Promises
loadData(42)
.then( preprocessData )
.then( displayResult )
.catch( alertUser )
.finally( clearLoadingFlag );
© 2015 andrena objects ag
Experts in agile software engineering 45
Agenda
1. Herausforderungen in Enterprise-JavaScript-Projekten
2. Was ist AngularJS und was bietet es
3. Wie man Projekte an die Wand fährt… und wie man es verhindert
4. Zusammenfassung und Ausblick
© 2015 andrena objects ag
Experts in agile software engineering 46
Empfehlungen
• Automatisierung von Anfang an
• GUI-Tests ab der ersten Seite
• Unit-Tests -> TDD oder Test-first
• Hohe Testabeckung -> Testabdeckung messen!
• Code-Konventionen -> Linter und gute IDE
• Keine Code-Duplikationen -> Angulars Möglichkeiten nutzen
• Promise-based APIs
© 2015 andrena objects ag
Experts in agile software engineering 47
Rahmenbedingungen von Enterprise-JavaScript-Projekten
• Kein Compiler Testautomatisierung
• Keine „natürliche“ Strukturierung Disziplin und Angular-Module
• Loser Zusammenhang der Dateien Angular-Module
• Dynamische Typisierung Testautomatisierung
• Kein „Klassen“-Konzept Explizit modellierte Objekte
• Asynchronität ~ Promise-based APIs
• Client-seitige Ausführung
• => Einige Probleme werden von EcmaScript2015 adressiert
© 2015 andrena objects ag
Experts in agile software engineering 48
Noch besserer Code durch TypeScript
• Typisierung (Typdeklaration, Klassen, Interfaces)
• Compile-Errors
• Typsichere Rest-Schnittstelle
• Serverseitiges DTO (z.B. in Java geschrieben) kann als TypeScript-DTO generiert werden
-> TypeScript-Compile-Errors
• Kommt mit vielen zukünftigen EcmaScript-Features
• (Debugging mit Source in TypeScript-Dateien möglich)
Vorteile von Angular mit TypeScript
© 2015 andrena objects ag
Experts in agile software engineering 49
Noch besserer Code durch TypeScript (2)
• Konversion nicht immer ohne Cast möglich
• Compiler-Schritt kostet etwas Zeit
• Typdefinitionen für externen JavaScript-Code
• => Angular 2 wird mit TypeScript entwickelt
Einschränkungen beim Einsatz von TypeScript mit Angular