Ernsthaftes JavaScript


in Enterprise-Projekten


Aus der Perspektive eines Java-Entwicklers

Oliver Zeigermann / @DJCordhose

Online version at: http://djcordhose.github.io/serious-javascript/slides/jax.html

Was ist ein ernsthaftes Enterprise-Projekt?

  • es ist unternehmenskritisch, d.h. der Erfolg des Unternehmens ist davon abhängig
  • lebt für viele Jahre
  • ist ein unendliches Spiel (im Gegensatz zu einem endlichen Spiel in der Spieltheorie)
  • es gibt ein Team (mehr als ein Mitglied)
  • es gibt kein konstantes Team, Mitglieder kommen und gehen

JavaScript-Projekte

  1. haben keine Struktur und sind Chaos
  2. sind allein schon wegen der Ablaufumgebung (Browser) der Horror
  3. sind von Anfang an unwartbar ...
  4. ... und können nur im kleinen Rahmen funktionieren
  5. erfordern in jedem Fall eine polyglotte Programmierung

Stimmt das? Oder sind das Vorurteile?

Die Untersuchung ist Gegenstand dieser Session

Aufbau moderner Webanwendungen

So sieht eine moderne 08/15 Webanwendung aus

Erzeugt mit http://yeoman.io/

Untersuchung der Frage: Haben JavaScript-Projekte keine Struktur und sind Chaos?

Live-Demo: Eine komplette Webanwendung

  • yo webapp
  • IDE: WebStorm
  • Grunt.js: Build-Tool
  • Bower: Abhängigkeitsmanagement
  • Comapss und SASS: Abstraktion von CSS
  • Mocha / Chai: BDD-/Unit-Test-Framework
  • JsHint: Linter

Fragen?

Node.js und Avatar.js

Untersuchung der Frage: Erfordern JavaScript-Projekte in jedem Fall eine polyglotte Programmierung?

Fragestellung

  • JavaScript im Browser ist als Zielsprache gesetzt
  • Meist braucht man auch Code, der auf dem Server läuft
  • Wie setzt man diesen um?
  • JEE/Spring/.NET/Rails/Python?
  • Oder ebenfalls in JavaScript?

JavaScript auch auf dem Server?

  • Code kann wieder verwendet werden
  • Dieselben Tools für Frontend und Backend
  • Kleinerer Technologiestack
  • Vertikale Teams einfacher zu realisieren
  • Einheitliche Entwicklungsphilosophie
  • JSON als natürliches Datenformat

Node.js

  • Erlaubt die Ausführung von JavaScript auch auf dem Server
  • Bestandteile
    • Chrome V8 JavaScript-Engine
    • Asynchrone IO-Bibliothek (libuv), die auf allen Plattformen läuft
  • Asynchrones Programmiermodell, kein Multithreading
  • Forken für Auslastung alles Kerne mit "Clustering" als Kernmodul
  • Skalierung über viele Maschinen möglich
  • Skaliert sehr gut bei hoher Last (non-blocking)

Beispiel-Server für node

var http = require('http');

function handleRequest (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}
http.createServer(handleRequest).listen(1337);

Starten

node server.js

Wer nutzt Node.js in Produktion?

Umstellung auf Node.js? Aber:

  • Legacy code?
  • Nur ein Teil soll auf Node.js umgestellt werden?
  • Schrittweise Umstellung?
  • JavaScript hat nur "number". Wie sieht es mit Geld-Berechnungen aus?

JDK 8 Nashorn

  • JDK 8 hat eine neue JavaScript-Engine: Nashorn
  • Ersetzt Rhino
  • ECMAScript 5.1-Kompatibel
  • Übersetzt JavaScript in Java Bytecode
  • Deutlich schneller als Rhino bei länger laufenden Tasks (Server)
  • Zugriff auf Java-Klassen (BigDecimal!) und SAM types von JavaScript sehr einfach

Beispiel-Code Nashorn mit Java-Integration

var BigDecimal = Java.type('java.math.BigDecimal');

function calculatePercentage(amount, percentage) {
    var result = new BigDecimal(amount).multiply(
       new BigDecimal(percentage)).divide(new BigDecimal('100'),
        2, BigDecimal.ROUND_HALF_EVEN);
    return result.toPlainString();
}

Ja, das ist JavaScript-Code

Avatar.js

  • Bietet das Node.js Programmiermodell für Java und Nashorn
  • Core-Pakete und alle wichtigen Module laufen
  • Start aus Java heraus möglich
  • Threading für JavaScript möglich
  • Aufruf beliebiger Java-Services (Legacy) aus JavaScript

Fragen?

Code Qualität, Module, statische Analyse

Untersuchung der Fragen: Sind JavaScript-Projekte von Anfang an unwartbar und können nur im kleinen Rahmen funktionieren?

Provokantere Frage: Selbst wenn ich schnell in JavaScript entwickeln kann, wird mein Code in einem Jahr noch wartbar sein?

Und in 5 Jahren?

Und in 10 Jahren?

Fragestellungen der Wartbarkeit

  • Wie modularisiere ich meinen Code, um
    • ihn handhabbar zu halten
    • mit mehreren Entwicklern daran arbeiten zu können
  • Wie halte ich meinen Code einfach lesbar?
  • Wie definiere ich ein Maß für Code-Qualität und wie erreiche ich diese?
  • Wie ermögliche ich eine statische Analyse?

Muster für größere Projekte

Erfahrung: Module und Typen-Hierarchien fördern strukturiertes Arbeiten

Klassische Typen und Vererbung mit JavaScript

  • Typen und Konstruktoren sind Mechanismen, um mehrere, strukturell gleiche oder ähnliche Objekte zu erzeugen
  • Auch in JavaScript können eigene Typen definiert werden
  • Einfachvererbung ist ebenso möglich
  • Der Mechanismus ist nicht direkt in die Sprache eingebaut
  • Stattdessen benutzen wir Best-Practice-Patterns
  • Grundlage ist die prototypische Vererbung

Setzen des Prototypen aka das Typen-System

Typen werden über Konstruktor-Funktionen definiert

/** @constructor */
function Person(name) {
    this.name = name;
}
Person.prototype.getName = function() {
    return this.name;
};
var olli = new Person('Olli');
olli.getName() === 'Olli';

Modularisierung

Revealing Module Pattern

var person = {};
(function () {
    // Constructor
    function Person(name) {
        this.name = name;
    }

    // Factory
    function create(name) {
        return new Person(name);
    }

    // Export der Factory-Methode
    person.createPerson = create;
})();
var olli = person.createPerson('Olli');

Es gibt zwei grundsätzlich unterschiedliche Modul-Systeme als Defacto-Standard

  • AMD
    • Module werden nicht blockierend und potentiell asynchron geladen
    • Module werden über bower oder manuell installiert
    • Verwendung auf Client-Seite
    • Default-Implementierung: RequireJS
  • CommonJS
    • Module werden blockierend und synchron geladen
    • Module werden über npm installiert
    • Verwendung auf Server-Seite
  • Beide Modul-Systeme können über r.js / Browserify auch auf Server / Client benutzt werden

Deklarierte Typen

  • Grundlage der Überlegung
    • Verlässliche Toolunterstützung für Analyse und Refactoring sind ohne statische Typ-Information nicht möglich
    • Ohne verlässliche Analyse- und Refactoring-Möglichkeiten wird Enterprise-Code schnell untwartbar
  • Mögliche Techniken
    • Google Closure Compiler
    • TypeScript

Google Closure Compiler

Beispiel-Code: Interface

/**
 *
 * @interface
 */
function HasName() { }

/**
 * @returns {string}
 */
HasName.prototype.getName = function() {};

Beispiel-Code: Class

/**
 *
 * @param name {string}
 * @param alter {number}
 * @param geschlecht {string=}
 * @constructor
 * @implements {HasName}
 */
function Person(name, alter, geschlecht) {
    this.name = name;
    this.alter = alter;
    this.geschlecht = geschlecht;
}

Google Closure Compiler: Bewertung

  • Vorteile
    • Lesbarkeit für Menschen verbessert
    • Verbesserter IDE-Support durch deklarierte Typen
    • Kein Compilierungsschritt zur Ausführung notwendig
    • Compiler nutzt Typ-Informationen auch zur Optimierung
  • Nachteile
    • Technologie-Stack wächst
    • Es sieht nicht sonderlich schön aus
    • Abhängigkeit von Google-Technologie (Rückkehr zu einfach JavaScript möglich)
    • JavaScript-Konstrukte (z.B. für Interfaces oder Varargs) teilweise etwas überraschend

TypeScript

Beispiel-Code

interface HasName {
    getName(): string;
}

class Person implements HasName {
    constructor(private name: string, private alter: number,
    private geschlecht: string = 'F') {
    }
    getName() {
        return this.name;
    }
}

var olli: HasName = new Person('Olli', 43);

TypeScript: Bewertung

  • Vorteile
    • Lesbarkeit für Menschen verbessert
    • Stark verbesserter IDE-Support durch deklarierte Typen
    • Typinformation sogar für JSON-Objekte
  • Nachteile
    • Technologie-Stack wächst
    • Compilierungsschritt immer notwendig
    • Abhängigkeit von MicroSoft-Technologie (Rückkehr zu JavaScript möglich)
    • Optionale Typen erfordern viel Eigenverantwortung der Entwickler

Code Qualität mit JSHint

  • Analysiert JavaScript-Files und macht konfigurierbare Prüfungen
  • http://www.jshint.com/
  • Deckt potentielle Fehler auf
  • Kann die Code-Conventions des Teams unterstützen

Was könnten hier die Probleme sein?

function olli() {
    console.log("aha")
    func();
    variable = 10;
 var myVar;
    10 == "10";
    if (true) console.log('Yo');
}
  • Aufruf von der Kommandozeile oder IDE-Integration
  • Anhand eine Konfigurationsfiles können alle Optionen an oder ausgeschaltet bzw. konfiguriert werden
  • In jeder JavaScript-Datei können zudem Warnungen ausgeschaltet werden (vgl. @SuppressWarnings in Java)

Fragen?

Browser-Frameworks

Untersuchung der Frage: Sind JavaScript-Projekte allein schon wegen der Ablaufumgebung (Browser) der Horror?

Wozu ein Framework für die Browser-Entwicklung?

  • Es gibt immer noch eine Reihe von Browser-Unterschieden bzgl. DOM und JavaScript (insbesondere pre IE9)
  • Das DOM ist kein "ideales" API
  • Selbst idealerweise ist das DOM immer noch sehr low-level
  • Unterstützung unterschiedlicher Gerätekonzepte und Gerätegrößen

Anforderungen an ein Browser-Framework für Enterprise-Projekte

  • Es muss zu meiner Anwendung passen
    • Business-Anwendung?
    • Soll auf mobilen Geräten laufen?
    • Grafisch sehr ansprechend?
    • Leichte Bedienung? (Business-User vs. Casual)
  • Es muss über viele Jahre gewartet bleiben
  • Rückwärtskompatibilität
  • Es muss leicht erlernbar sein

Kultur-Clash Java- / JavaScript-Frameworks

  • kleinere Module dominieren die JavaScript-Framework-Welt
    • npm und bower mit anarchischer Organisationsstruktur
    • Wenn überhaupt dann Defacto-Standards
    • Jeder muss sich seinen eigenen Satz an Komponenten auswählen
    • u.a. yeoman und Bootstrap-Pakete geben zumindest etwas Richtung
  • Java kommt mit komplettem JDK und JEE-Standard
    • bietet Orientierung
    • allerdings auch weniger Freiheit (bzw. andere Auswahl muss auch vertreten werden)

Auswahl von Frameworks, die sich als Enterprise-würdig erwiesen haben

  • jQuery
  • AngularJS
  • Ext.js
  • Kein Framework

Zum Vergleich: Hello World ohne Framework

<!DOCTYPE html>
<html>
  <head>
    <title>Hello World!</title>
  </head>
    <body>
      <div id="log"></div>
      <script>
          var element = document.getElementById("log");
          element.innerHTML = "<h1>Hello World</h1>";
      </script>
    </body>
</html>
                        
Run

Option: jQuery

  • Standard-JavaScript-Bibliothek
  • Fast überall zu finden
  • Adressiert Probleme bei der Programmierung des DOMs
  • Abstrahiert nicht von der Ebene der DOM-Manipulation
  • Funktionalität unterteilbar in "Auswahl" und "Manipulation"

Hello World jQuery

<!DOCTYPE html>
<html>
  <head>
    <title>Hello World jQuery!</title>
    <body>
      <div id="log"></div>
      <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>

      <script>
        $(document).ready(function(){
            $("#log").html("<h1>Hello World</h1>");
        });
      </script>
    </body>
</html>
                        
Run

Option: AngularJS

HTML enhanced for web apps!

http://angularjs.org

Konzepte

  • Client-Seitige Templates
  • MVC (Modell ist eher ViewModel)
  • Die drei Ds
    • Data Binding
    • Dependency Injection
    • Directives

Hello World AngularJS

<html ng-app>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.min.js"></script>
    <script src="controller.js"></script>
</head>
<body ng-controller="HelloController">
    <input ng-model="greeting">
    <p>{{greeting}}, World!</p>
</body>
</html>
function HelloController($scope) {
    $scope.greeting = 'Hello';
}
Run

Option: ExtJs

  • hat alle Komponenten für eine Business-Anwendung
  • folgt weniger der Web-Philosophy als der Desktop-Metapher
  • ExtJS 5 unterstützt alle Devices
  • Unterstützt weiterhin IE8
  • Unterschiedliche Themes durch austauschen von CSS
  • existiert seit vielen Jahren, Einsatz kommerziell

Hello World ExtJS

Ext.application({
    name: 'Hello World',

    launch: function() {
        Ext.create('Ext.container.Viewport', {
            layout: 'fit',
            items: [
                {
                    xtype: 'panel',
                    title: 'Hello World',
                    html : 'Hello!'
                }
            ]
        });
    }
});
Run

Letzte Option: Kein Framework

  • Was ist die Motivation?
  • Passt keines der Frameworks zu den Anforderungen?
  • Selbstbetrug ausschließen: Bauen wir uns nicht unser eigenes Framework?
  • Glauben wir wirklich, dass unser eigenes Framework besser sein wird als ein Standard-Framework?
  • Wenn ja, wer in dem Team hat schon einmal ein vergleichbares Framework gebaut?

Wrapup

  • Kein Framework: Gängige Frameworks passen nicht oder Anwendung ist sehr einfach
  • jQuery: DOM als Abstraktion ist ausreichend, Projekt evtl. nicht sehr komplex
  • Angular.js: Sehr praktisch für SPAs und größere Projekte
  • Ext.js: Für Business-Anwendungen, wie man sie auch mit JSF oder JavaFX bauen würde

Fragen?

Was haben wir gesehen?

  • Es gibt brauchbare Strukturen, Prozesse und Tools für JavaScript-Projekte
  • Gute Frameworks machen das DOM und die Browser-Vielfalt erträglich
  • Die Sprache JavaScript und Werkzeuge um die Sprache herum ermöglichen Wartbarkeit auch für große Projekte
  • JavaScript ist auf Client und auf Server möglich

Allerdings

  • Herangehensweise anders als bei Java / .NET
  • Vieles muss man sich selbst erarbeiten
  • Es gibt wenige echte Standards
  • Die meisten Entscheidungen muss man selbst treffen (und verantworten)
  • Langlebigkeit von Bibliotheken teilweise fraglich
  • Einstieg daher oft mit Angst und Unsicherheit verbunden

Vielen Dank

Fragen / Diskussion

Oliver Zeigermann / @DJCordhose