• Noser.com
facebook
linkedin
twitter
youtube
  • NOSERmobile
    • Android
    • HTML 5
    • Hybrid Apps
    • iOS
    • Windows Phone
  • NOSERembedded
    • Medizintechnik
  • NOSERprojektmanagement
  • NOSERtesting
  • NOSERlifecycle
    • .NET Allgemein
    • Application Lifecylce Management
    • Apps
    • Architektur
    • ASP.NET
    • Azure
    • Cleancode
    • Cloud
    • Silverlight
    • Visual Studio / Team Foundation Server
    • Windows 8
    • Windows Presentation Foundation
  • NOSERinnovation
    • Big Data
    • Cloud
    • IoT
    • Operations Research
    • Augmented Reality
    • RFID, NFC, Bluetooth LE

ManuScripts: Wenn jemand eine Reise tut… Funktionale Programmierung mit Elm – Teil 2 – Kein Picknick

10. Mai 2016
Manuel Baumann
4
Angular Js, Angular2, AngularJs, Javascript, Reactive Programming

nopicnic
Eine Blog-Serie zum Vergleich von Elm, ReactJS und AngularJS anhand eines praktischen Beispiels. Hier geht es direkt zu [Teil 1, 3, 4, 5, 6]

“Ich packe in meinen Rucksack…. ein Quickstart-Tutorial”

Wer sich über die Entwicklung mit Angular2 informieren will, der landet innert Kürze auf dieser Url: https://angular.io/docs/js/latest/quickstart.html.

Persönlich hatte ich schon selbst Erfahrungen mit Angular 1.4 gesammelt, darum wusste ich, dass die Überschrift “5 MIN QUICKSTART” entweder als Hohn oder Lüge zu verstehen war. Und es war natürlich auch klar, dass es deutlich mehr zu tun gäbe, um mit AngularJS das selbe Resultat zu erreichen. Um es vorwegzunehmen: meine effektive Erfahrung übertraf meine Prophezeiung sogar noch!

Da müssen wir durch…

Typsicherheit

Javascript selbst kennt nur dynamisches Typing und wird zur Laufzeit interpretiert. Das lässt eine recht freie Art der Programmierung zu, führt aber z.B. zu einer Reihe von lästigen und unproduktiven Laufzeitfehlern aufgrund von Tipp- und Typ-Fehlern. Aus diesem Grund macht es durchaus Sinn, dass AngularJS nun (u.a.) auf dem typisierten Javascript-Derivat TypeScript von Microsoft aufbaut.

Angular2-Applikationen können zur Zeit mit ES5, ES2015 oder TypeScript geschrieben werden. Da Elm statisches Typing anbietet, kommt nur (die vorgeschlagene) Variante mit TypeScript für den Vergleich mit Elm in Frage

Projekt und Abhängigkeiten

Für die Entwicklung mit Angular2 MUSS node.js und npm installiert sein. Danach:

mkdir ang2-anagram && cd ang2-anagram

TypeScript Compiler Konfiguration

Da wir TypeScript verwenden, muss der Compiler mittels der Datei tsconfig.json konfiguriert werden.

{
  "compilerOptions": {
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  },
  "exclude": [
    "node_modules",
    "typings/main",
    "typings/main.d.ts"
  ]
}

Wer den Inhalt dieser Datei genau verstehen will, benötigt bereits ein breites Wissen über die aktuellen Javascript-Standards, Build-Tools, Module-Loader und sogar node.js . Hier sei jedoch zusammengefasst erklärt, dass diese Datei den TypeScript-Compiler anweist, die TS-Dateien nach Javascript zu “transpilieren”, und zwar im ES5-Standard. Es sollen aber auch ES2016-Style Typ-Dekoration zugelassen werden (experimental). Die Ergebnisse werden mit SystemJS geladen und gebundelt.

Mit exclude werden Verzeichnisse und Dateien von der Transpilation und dem Bundling ausgeschlossen.

Typ-Informationen (typings)

Weiter geht’s: als nächstes wird im referenzierten Tutorial der TypeScript-Compiler mit zusätzlichen Typinformationen versehen, indem Referenzen auf externe d.ts Dateien im File typings.json  erfasst werden. Dies ist für unsere Zwecke momentan nicht nötig, wir haben also (noch) Glück und können diesen Schritt auslassen. Untenstehende Datei würde per Tutorial also ebenfalls eingebunden, und früher oder später werden wir die Datei auch nachliefern müssen, wenn oder falls wir externe Bibliotheken einbinden und uns dafür TypeScript-Type-Checking wünschen.

{
  "ambientDependencies": {
    "es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#7de6c3dd94feaeb21f20054b9f30d5dabc5efabd",
    "jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#5c182b9af717f73146399c2485f70f1e2ac0ff2b"
  }
}

Wir verzichten demnach momentan auf Typinformationen für den ES6-Shim (Unterstützung von ES6-Features in Legacy-Browsern) und für das Testing-Framework Jasmine.

package.json

Es folgt die npm -Projekt-Definition im File package.json  (auch wieder leicht gekürzt gegenüber dem Tutorial):

{
  "name": "angular2-quickstart",
  "version": "1.0.0",
  "scripts": {
    "start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ",
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "lite": "lite-server"
  },
  "license": "ISC",
  "dependencies": {
    "angular2": "2.0.0-beta.15",
    "systemjs": "0.19.26",
    "es6-shim": "^0.35.0",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.2",
    "zone.js": "0.6.10"
  },
  "devDependencies": {
    "concurrently": "^2.0.0",
    "lite-server": "^2.2.0",
    "typescript": "^1.8.10"
  }
}

Auch diese Datei ist wieder gepackt mit Entwicklungs- und Laufzeit- Abhängigkeiten. Bei den Entwicklungs-Abhängigkeiten (devDependencies ) sehen wir den typescript -Kompiler und den lite-server , der als Entwicklungs-Server dient. concurrently  erlaubt die Ausführung mehrere Node-Prozesse gleichzeitig.

Bei den Laufzeit-Abhängigkeiten (dependencies ) wurde systemjs  und es6-shim  schon oben erwähnt, reflect-metadata  bringt den Decorator-Support. rxjs  und zone.js  schlussendlich behandeln die reaktiven und asynchronen Aspekte der Applikation. Die werden wir sicher benötigen. Nicht für “Hello World”, aber für den Anagrammerator, und Elm unterstützt diese Funktionalität von Haus aus (diese Aussage, bzw. zu welchem Umfang muss noch genauer untersucht werden)

Die Sektion scripts  beinhaltet übrigens nützliche npm-Ziele, um den TypeScript-Compiler oder den Entwicklungs-Web-Server anzustossen.

Das haut den stärksten Wanderer aus den Latschen

Die erzwungene Wander-Referenz soll an dieser Stelle die Aufmerksamkeit des Lesers wieder herstellen. Zwar hätte ich damit wohl besser gewartet bis nach dem nächsten Befehl:

npm install

Damit werden alle diese vorgängig konfigurierten Abhängigkeiten heruntergeladen und im node_modules/-Ordner abgelegt. Unter Verwendung obiger Konfiguration (welche dem Quick-Start-Tutorial gegenüber noch geschrumpft wurde), sind das sage und schreibe 11‘646 Dateien, die 113 MB Disk-Platz beanspruchen.

Eine erste Vergleichsgrösse zu Elm (mal abgesehen von den offensichtlichen Unterschieden im “Ease-of-Getting-Started”):

Verwendete Abhängigkeiten für “Hello World” auf Disk:

Elm Angular Faktor
Anzahl Files 149 11‘646 78
Anzahl MB 1.1 113 102

 

(Hierzu kommen übrigens auch noch die Node.js-Programmdateien, welche bei Elm nur für die Ausführung der REPL-Konsole gebraucht werden. Dafür muss für Elm ein Compiler installiert werden.)

Dieses Verhältnis wird sich auch beim Ausbau des Anagramm-Generators noch verändern und sollte ganz zum Schluss nochmals betrachtet werden.

Entwicklung mit Angular

Nun sind wir endlich soweit, dass wir eine Komponente erstellen können. Dazu erstellen wir erst das empfohlene app-Verzeichnis:

mkdir app && cd app

Eine Angular2-Komponente besteht aus 3 Teilen:

  • Imports: deklariert die verwendeten Bibliotheken
  • Component Decorator: Metadaten zur Erstellung und Verwendung der Komponente
  • Component Class: Die Komponente selbst enthält Eigenschaften und Applikations-Logik. In unserem Beispiel ist sie noch leer.

Das Beispiel aus dem Quick-Start sieht in etwas so aus (leicht angepasst, damit es der Elm-Vorlage mehr entspricht) – app.component.ts :

import {Component} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: '<span>Hello Angular</span>'
})

export class AppComponent { }

Das nächste File heisst main.ts  und wird im app/ -Ordner angelegt:

/// <reference path="../node_modules/angular2/typings/browser.d.ts" />

import {bootstrap}    from 'angular2/platform/browser';
import {AppComponent} from './app.component';

bootstrap(AppComponent);

Das Skript benutzt die Browser-Bootstrapping-Variante des Frameworks, um unsere Komponente in diesem Kontext zu betreiben. Die erste Zeile ist kein Kommentar und stammt auch nicht aus dem Tutorial, sondern wurde nach Fehlern bei der Ausführung eingefügt. Gefunden wurde sie mit den hervorragenden und viel zu wenig gelobten Werkzeugen “Google Search” und StackOverflow.

Schliesslich erstellen wir im Projekt-Root-Verzeichnis (cd.. ) noch die Html-Datei index.html  mit folgendem Inhalt:

<html>
  <head>
    <title>Angular 2 Anagrammerator</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">    

    <!-- 1. Load libraries -->
    <!-- IE required polyfills, in this exact order -->
    <script src="node_modules/es6-shim/es6-shim.min.js"></script>
    <script src="node_modules/systemjs/dist/system-polyfills.js"></script>
    <script src="node_modules/angular2/es6/dev/src/testing/shims_for_IE.js"></script>   

    <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <script src="node_modules/rxjs/bundles/Rx.js"></script>
    <script src="node_modules/angular2/bundles/angular2.dev.js"></script>

    <!-- 2. Configure SystemJS -->
    <script>
      System.config({
        packages: {        
          app: {
            format: 'register',
            defaultExtension: 'js'
          }
        }
      });
      System.import('app/main')
            .then(null, console.error.bind(console));
    </script>
  </head>

  <!-- 3. Display the application -->
  <body>
    <my-app>Loading...</my-app>
  </body>
</html>

Der Code ist zwar kommentiert, aber um genau zu verstehen, was hier vor sich geht, ist auch wieder ein solides Basiswissen und eine eingehende Erklärung vonnöten:

  1. Zuerst werden die vielen Sourcen aus den zuvor deklarierten Abhängigkeiten eingebunden, wie üblich das meiste davon nur, um mit IE kompatibel zu sein.
  2. Dann wird der Module-Loader konfiguriert, indem js als Standard-Suffix für zu verarbeitende Dateien und der Einstiegspunkt auf app/main  festgelegt wird. (An dieser Stelle sei auf die überzeugende(re) Alternative webpack  hingewiesen)
  3. Zum Schluss folgt der Html-Body, der mit einem merkwürdigen Tag namens <my-app>  startet, was mich erneut stutzen lässt, weil ich aus dem darüberstehenden Code nicht ableiten kann, woher das nun genau stammt und warum das gültiges HTML sein soll. Aber doch, im Dekorator der Klasse AppComponent findet sich ein Eintrag namens selector , der den Wert my-app  hat…!

 

Auf die Datei styles.css  verzichten wir, weil es a) schon mehr als genug zu tun gab und b) das Elm-Beispiel bisher auch kein Styling hat.

Geschafft! Wortwörtlich

Die Ausführung der ganzen Geschichte gestaltet sich mit npm start  dann doch überraschend einfach. Durch die Ausführung des Befehls wird der TypeScript-Compiler im Watch-Modus gestartet (überwacht die Quell-Dateien und kompiliert sie bei Änderung neu) und gleichzeitig wird der Entwicklungs-Webserver lite-server  gestartet und index.html angezeigt.

Wenn sich nun eine Datei verändert, wird die Seite im Browser neu geladen, was natürlich äusserst nützlich ist.

Bei der Entwicklung des Blog-Posts wurde an dieser Stelle der oben beschriebene Bug im Tutorial von angular.io festgestellt und behoben

Können wir endlich los….?

Zugegeben, das Angular Quick-Start-Tutorial beinhaltet viele Teile, die für die Ausgabe von “Hello World” nicht nötig gewesen wären. Das wird auch im offiziellen Quick-Start Tutorial so erwähnt, mit der Begründung, man wolle für grössere Absichten gerüstet sein und z.B. rxjs  jetzt schon einbinden, damit man es später nicht vergesse.

Persönlich empfinde ich dieses Quick-Start-Tutorial alles andere als Quick. Es ist gespickt mit verwirrenden Begriffen aus diversen spezifischen Technologien, die ein Anfänger zu Überlesen gezwungen ist und bei welchen sich auch ein Profi fragen sollte, ob er sich damit auseinandersetzen will.

Aber da diese Details in der Natur der Sache liegen, welche ohne sie nicht oder nur schwer auskommt, kann es pädagogisch schon sinnvoll sein, den Benutzer früh und wiederholt an die sich über die Jahre entwickelte Komplexität im Javascript-Entwicklungs-Bereich heranzuführen.

Elm sitzt mit leichtem Gepäck und voller Tatendrang auf der Vorderkante des Sofas im Wohnzimmer von Angular, während dieser seinen Rucksack mit der Hälfte davon vollstopft und dabei unverständliches Zeug vor sich hin brummelt. Dabei dämmert es Elm langsam, worauf sie sich mit dieser gemeinsamen Wanderung eingelassen hatte. Sie zückt ihr vibrierendes Smartphone aus der Hüfttasche und sieht darauf eine Nachricht von ReactJS:

“Na, seid ihr bald alle soweit? Habe zur allgemeinen Unterhaltung noch meine Fiddle mitgenommen und warte beim Bahnhof auf Euch. Frag Angular bitte, ob ich von seinem TypeScript auch etwas abhaben kann, mein Arzt hat es mir für grössere Wanderungen empfohlen. Wir können die Details der Reise ja unterwegs besprechen. Ich muss Euch unbedingt von meinem neuen Bibel-Chor erzählen!”

Und kurz darauf:

“Babel-Core!! Blödes Autokorrekt…”

Und im Anhang fand sich ein Bild der Reisetasche von ReactJS:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello, React!</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react-with-addons.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
  </head>
  <body>
    <div id="main"></div>
    <script type="text/babel">
      ReactDOM.render( <span>Hello, React!</span>, document.getElementById('main') );
    </script>
  </body>
</html>

Elm muss schmunzeln, als sie Angular das Bild zeigt und sich dieser offensichtlich darüber aufregt, wie minimalistisch sich alle, ausser ihm selbst natürlich, auf diese Reise vorbereitet haben. Dabei weiss ja eigentlich niemand so genau, was sie auf diesem Ausflug alles erwarten würde.

Leicht aufgebracht schwingt er sich seinen Rucksack auf den Rücken und dabei fallen ihm einige .js  und js.map  – Dateien aus einer offengelassenen Seitentasche.

“Igitt, das ist ja ekelhaft!”, stösst es Elm auf, als diese die verstreuten Dateien genauer betrachtet. “Kannst Du die nicht besser verstauen? Das müssen ja nun wirklich nicht alle zu sehen bekommen!”.

Auf dem Weg zum Bahnhof schweigen beide. Die bedrückte Stimmung lockert sich erst, als sie dort auf ReactJS stossen, der die beiden schon von Weitem und heftig winkend dorthin beordert, wo ihr Weg sie ohnehin führen musste. Dem Funkeln in seinen Augen nach zu schliessen, hat er viel zu erzählen…

In der nächsten Etappe wird auch noch der letzte Reise-Teilnehmer React.JS vorgestellt.

Dann aber wenden wir uns wieder dem Anagramm-Generator und Elm zu, denn wie sich herausstellen wird, haben die anderen zwei während der Fahrt sowieso eine Menge Insider-Zeugs miteinander zu besprechen.

 

ManuScripts: Wenn jemand eine Reise tut… Funktionale Programmierung mit Elm – Teil 1 – Aufbruch

03. Mai 2016
Manuel Baumann
5
Angular, AngularJs, Elm, Functional Programming, Javascript, React Js, Reactive Programming, SPA

Ein ungleiches Trio auf einer Wandertour zum Mount Anagramm

react logo
elm logo
angular logo

Diese Blog-Serie bietet eine Einführung in die funktionale Programmierung mit Elm. Durch die iterative Entwicklung eines Anagramm-Generators (für die deutsche SCRABBLE-Community) soll dem Leser die funktionale Programmierung im Allgemeinen und die vorzügliche Sprache Elm im Speziellen, näher gebracht werden.

Um einen Vergleich mit herkömmlichen Frameworks im imperativen, der Objektorientierung angelehnten Stil zu ermöglichen, wird die Applikation auch in AngularJS und ReactJS geschrieben werden und Elm gegenüber gestellt.

Hier geht es direkt zu [Teil 2, 3, 4, 5, 6]

Bild der Wander-Region von Elm


Eine Reise von Javascript nach Elm

Elm ist nicht nur eine wunderschöne Wanderregion der Schweiz mit einer vom UNESCO-Welterbe anerkannten Gebirgslandschaft, es ist auch eine unlängst erschienene funktionale reaktive Programmiersprache, welche mit Haskell geschrieben wurde und sich im Syntax an Haskell und F# anlehnt.

Elm ist für die Erstellung von Javascript-Web UI’s hervorragend geeignet, aus dem bestechenden Grund, dass es in erster Linie dafür konzipiert worden ist.

Während React.Js sich im jüngsten Technologie-Radar von 2016 bereits im Status “Adopt” befindet, hat sich Elm hochgearbeitet und ist wie Angular.Js im Status “Assess”. Es ist mit kleiner Community, und ohne viel Aufsehen zu erregen, ein ernstzunehmendes Werkzeug geworden.

Die Programmierung mit Javascript hat eine lange und spannende Entwicklung durchgemacht. Erst belächelt, dann missbraucht, lange nicht ernst genommen, endlich zu neuem Ruhm gelangt mit node.js und nun in den höchsten Tönen gefeiert. Aber zu den höchsten Tönen gehört auch Geschrei und Gekreische!

Eine umfangreiche und unterhaltsame Beschreibung vom Aufstieg und Fall der Sprache Javascript hat Flaki geschrieben.

Diese Blog-Serie ist sowohl für Anfänger der Frontend-Entwicklung, als auch für erfahrene Javascript-Programmierer geschrieben. Erstere sollten vielleicht die Javascript-Abschnitte überspringen und direkt nach Elm aufbrechen, die anderen finden hier hoffentlich ein Stück Glück bei ihrer Suche nach alternativen (Wander)-Wegen und wirksamen Werkzeugen.

Klären wir aber zuerst einmal die Begriffe, bevor wir untersuchen, ob Elm als richtungsweisend bezeichnet werden kann und warum funktionale Programmierung von Entwicklern genutzt und (anderen) Entscheidungsträgern gefordert, gefördert und getragen werden sollte.


Begriffe

Von der Github-Seite des Autoren Evan Czaplicki vernimmt man:

“Elm is a type inferred, functional reactive language that compiles to HTML, CSS, and JavaScript.”

  • ELM ist KEIN gültiges SCRABBLE-Wort. DOM schon.
  • FRP oder funktionales reaktives Programmieren stellt eine Methode dar, um auf deklarative Art reaktive Systeme zu erstellen.
  • Reaktive Programmierung findet überall dort eine Anwendung, wo man auf Systeme trifft, die von der Verarbeitung von vielen externen Eingaben abhängen (das macht sie reaktiv), also in Domänen wie IOT, graphischen Simulationen (sprich: Games) oder Benutzeroberflächen, um nur wenige zu nennen.
  • Funktionale Programmierung im ML-Stil existiert nun schon seit über 45 Jahren und predigt die Einhaltung eines puren Programmierstils, welcher mit unveränderbaren Werten operiert (Stichwort: immutability), um ungewünschte Seiteneffekte zu reduzieren oder ganz zu verhindern. Die meisten Funktionen in Elm sind deshalb auch “pure”: wenn man eine Funktion mit den gleichen Argumenten mehrmals und zu unterschiedlichen Zeitpunkten aufruft, erhält man immer das gleiche Resultat. Dies ist NICHT der Fall für Funktionen in anderen Sprachen, welche sich potentiell auf global verändernden Zustand beziehen. Diese Eigenschaft wird sich noch als äusserst vorteilhaft erweisen (z.B. für die Parallelisierung) und soll in dieser Serie genauer untersucht werden.
  • Von Typinferenz wird gesprochen, wenn der Compiler einen Typ ableiten, resp. schlussfolgern kann, ohne dass dieser deklariert werden muss. Dies lässt statische Typisierung zu, Deklarationen und Signaturen können auf ein Minimum beschränkt werden.
  • Deklarativ schlussendlich bedeutet, dass wir beim Programmieren nicht beschreiben WIE etwas getan werden soll, sondern WAS es zu tun gibt.

 


Yadayada! Ist diese Blog-Serie für mich? (YOLO!)

In dieser Serie geht es darum, eine fundierte Aussage erreichen zu können über die Vor- und Nachteile der Entwicklung mit Elm im Vergleich zu anderen bekannten Web-Frameworks wie React.JS und Angular.

Wer sich nur für das Resultat interessiert, muss sich noch etwas gedulden. Das Ganze ist, der Zeit entsprechend, ein agiler Prozess in der Entstehung.

Wer aber schon einmal Web-GUIs entwickelt hat oder es gerne tun möchte, wer je Erfahrung gemacht hat mit einem Template-System (ColdFusion, JSP, ASP.NET, PHP, Jade, Handlebars, Mustache, Razor, waren es allein für mich in dieser endlosen Liste) oder mit einem Binding-Framework (jQuery, Knockout.JS, Backbone.JS, AngularJS und React.JS), oder wer sich wegen der grossen Auswahl und endloser Fülle an Tutorials nicht entscheiden kann (auch eine Zeiterscheinung), der sollte sich die Programmiersprache Elm anschauen, bzw. diese Blog-Serie lesen und bookmarken.

Funktionale Programmierung mit Elm ist eine andere Art der Programmierung: direkter, problembezogener, korrekter. Sie zwingt den Programmierer, erst das Problem zu analysieren und zu formalisieren, bevor er eine elegante Lösung aus ihm herauskitzelt.

Zudem muss er sich schon von Anfang an auch um den Fehlerfall kümmern, da keine der Funktionen im Elm-Empirium sich diese Blösse geben würden, einen undefinierten Zustand zu hinterlassen, nicht einmal die “unpuren”.

Und Elm unterstützt sowohl den Einsteiger, als auch den erfahrenen Web-Entwickler, wo es nur kann:

  • Der Elm-Compiler liefert sinnreiche, detaillierte Erklärungen, Vorschläge und Kommentare. Dies war sogar Schwerpunkt der letzten zwei Releases.
  • Der mitgepackte Elm-Reactor ist ein Entwicklungs-Webserver, welcher Elm-Module automatisch in ein Javascript-Bundle kompiliert, dieses in eine HTML-Seite einbettet und aushändigt.
  • Der “zeitreisende” Debugger setzt dem Ganzen dann noch die Haube auf: er erlaubt es, den Zustand der Applikation zurück- und wieder vorzuspulen. Das kennt man als “Live-Coding”, was als solches bekannt gemacht wurde durch den Visionär Bret Victor

Wie einfach sich der Einstieg mit Elm gestaltet, soll nun demonstriert werden.


Ich kann nicht warten

Das kenn ich. Los gehts!

Elm Plattform installieren

Mit npm install -g elm oder Installationsprogramm

Installation überprüfen

Die folgenden Tools werden installiert:
– elm-compiler – der ominöse Übersetzer
– elm-repl – (benötigt node.js): die Read-Eval-Print-Loop-Konsole für Elm
– elm-make – das Build-Tool für Elm
– elm-reactor – der Entwicklungs-Web-Server mit zeitreisendem Debugger
– elm-package – der fleissige Package-Manager von Elm

Die aktuell installierte Version findet man z.B. mit elm-reactor -v . (sollte sich nach der Installation im Pfad befinden).

Projekt aufsetzen

Projekt-Verzeichnis anlegen und elm und git initialisieren:

mkdir elm-anagrams && cd elm-anagrams

elm-package install -y

git init
(echo elm-stuff/ elm.js) > .gitignore
git add * 
git commit -m "initial commit"

Die einzig relevante Zeile ist natürlich elm-package install -y , aber die anderen gehören zum guten Ton und zeigen auch gleich, welche generierten Artifakte von der Versionierung ausgeschlossen werden sollten.

Editor-Support

Als Editor für Elm kann ich Sublime Text 3 empfehlen, welches ein Package Elm Language Support anbietet mit Intellisense, Syntax-Highlighting und Build-Integration mit Fehler-Highlighting.

Hello.elm

Die Datei wird im Root-Verzeichnis angelegt, mit folgendem Inhalt:

import Graphics.Element exposing (..)

main = show "Hello, Elm!"

Anschliessend wird der Reactor gezündet von der Kommandozeile aus mit

elm-reactor

Jetzt kann im Browser auf http://localhost:8000 navigiert, Hello.elm angeklickt und gestaunt werden.


Was ist hier genau geschehen?

Der Befehl elm-package install -y  hat die Datei elm-package.json angelegt mit dem folgenden Inhalt:

{
    "version": "1.0.0",
    "summary": "helpful summary of your project, less than 80 characters",
    "repository": "https://github.com/user/project.git",
    "license": "BSD3",
    "source-directories": [
        "."
    ],
    "exposed-modules": [],
    "dependencies": {
        "elm-lang/core": "3.0.0 <= v < 4.0.0"
    },
    "elm-version": "0.16.0 <= v < 0.17.0"
}

Mal abgesehen von der genauen Bedeutung der unbenutzten Eigenschaft exposed-modules ist der Inhalt selbsterklärend. Bei den Abhängigkeiten (dependencies ) gibt es genau eine davon, nämlich diejenige auf das Kern-Paket des Elm-Frameworks.

Beim Klicken der Hello.elm -Datei im Browser läuft im Reactor folgendes ab:

  1. Die deklarierten Abhängigkeiten werden heruntergeladen und mit elm-make sowohl nach Javascript transpiliert, als auch in ein eigenes Binärformat kompiliert. Die Resultate werden im Verzeichnis elm-stuff  abgelegt (Daher der Eintrag im .gitignore ).
  2. Auch die Zieldatei (Hello.elm ) wird entsprechend kompiliert und aus den abhängigen Erzeugnissen wird das Bundle (unsere Applikation) elm.js  generiert (wird ebenfalls ignoriert im git).
(elm.js - generiert)
...
Elm.Main.make = function (_elm) {
   ...
   var _op = {};
   var main = $Graphics$Element.show("Hello World");
   return _elm.Main.values = {_op: _op,main: main};
};
  1. Es wird automatisch eine In-Memory Html-Seite erzeugt, in welche der elm.js -Skript eingebettet wird, und diese Seite wird dann via HTTP ausgeliefert (Seite im Browser mit Developer-Konsole (F12) inspizieren):
<script>var runningElmModule = Elm.fullscreen(Elm.Main);</script>
  1. Unser Elm-Programm main wird ausgeführt wenn die Seite fertig geladen ist.
main = show "Hello World"

Das Hauptprogramm besteht einzig aus dem Aufruf der Funktion show  aus dem Elm-Core-Modul Graphics.Element . Dieses Modul enthält einen Typ namens Element , welcher ein rechteckiges, graphisches Element bekannter Grösse darstellt, das auf dem Bildschirm dargestellt werden kann.

show hat die folgende Signatur (lies: Name der Funktion : In1 -> In2 -> InN -> Out ):

show: a -> Element

Der kleingeschrieben Platzhalter a  steht für einen beliebigen Typen, d.h. der Typ des einzigen Eingabe-Parameters wird nicht spezifiziert, also kann diese Funktion jegliche Struktur akzeptieren und im Browser darstellbar machen.

In Elm ist das in etwa so implementiert (vorerst ohne Erläuterung für die Neugierigen):

show : a -> Element
show value = leftAligned (Text.monospace (Text.fromString (toString value)))

Beim Aufruf von show “Hello World”  wird also der String  (Elm-Datentyp) “Hello World”  in ein graphisches Element verwandelt und ausgegeben. In der Entwickler-Konsole des Browsers stellt man das folgende DOM-Element fest:

<span style="font-family:monospace;">"Hello World"</span>

Abmarsch

So, damit haben wir das Nötigste eingepackt für eine spannende Wanderung im Elm-Gebirge. Bevor wir aber los marschieren, schauen wir doch unseren Kollegen Angular und React beim Packen zu.

Was alles getan werden muss, um mit Angular2/TypeScript oder ReactJS/Typescript zum gleichen Basis-Resultat zu gelangen, wird Inhalt des nächsten Blog-Eintrags sein.

Berg heil? bis zum nächsten Teil…

1234

Tag Cloud

.NET android Angular AngularJs Arduino ASP.Net automated testing Azure Big Data C# C++ Cloud continuous integration Elm Embedded Führung gRPC Internet of Things IoT Java Javascript M2M OWASP Projektmanagement protobuf Python Raspberry Pi Reactive Programming REST Scrum Security Softwarequalität SPA Testen testing Testmanagement Teststrategie UX Visual Studio WebAPI windows WPF Xamarin Xamarin.Android Xamarin.Forms

Archive

Current Posts

  • Akzente setzen mit der Android Splash Screen API unter .NET MAUI
  • Do You have Your Personal Space?
  • Automated provisioning with ARM Templates
  • Asynchrone Beobachtungen und Versprechungen in Angular
  • Simplify Your Automated Tests With Fluent Syntax

Last Comments

  • Hans Reinsch bei Der Safety-Plan: Die wichtigsten Antworten mit Checkliste
  • George H. Barbehenn bei Modeling Optocouplers with Spice
  • Noser Blog Touch-Actions in Xamarin.Forms - Noser Blog bei Mach mehr aus Animationen in Xamarin.Forms mit SkiaSharp
  • Noser Blog Focus on the Secure Storage service of Trusted Firmware (TFM) - Noser Blog bei First run of the Trusted Firmware (TFM) application
  • Noser Blog First run of the Trusted Firmware (TFM) application - Noser Blog bei Focus on the Secure Storage service of Trusted Firmware (TFM)

Popular Posts

Xamarin.Android Code Obfuscation

6 Comments

ManuScripts: Wenn jemand eine Reise tut... Funktionale Programmierung mit Elm - Teil 1 - Aufbruch

5 Comments

C# Concurrency Teil 8: Delegate Tasks

4 Comments

Contact us

  1. Name *
    * Please enter your name
  2. Email *
    * Please enter a valid email address
  3. Message *
    * Please enter message
© 2013 NOSER ENGINEERING AG. All rights reserved. Datenschutz | Cookie-Richtlinie