Artwork

Inhalt bereitgestellt von Sven Wiegand and Benjamin Hagemeister. Alle Podcast-Inhalte, einschließlich Episoden, Grafiken und Podcast-Beschreibungen, werden direkt von Sven Wiegand and Benjamin Hagemeister oder seinem Podcast-Plattformpartner hochgeladen und bereitgestellt. Wenn Sie glauben, dass jemand Ihr urheberrechtlich geschütztes Werk ohne Ihre Erlaubnis nutzt, können Sie dem hier beschriebenen Verfahren folgen https://de.player.fm/legal.
Player FM - Podcast-App
Gehen Sie mit der App Player FM offline!

SP05/16: Scala.js, Gradle vs. SBT

1:22:56
 
Teilen
 

Manage episode 157012356 series 1206977
Inhalt bereitgestellt von Sven Wiegand and Benjamin Hagemeister. Alle Podcast-Inhalte, einschließlich Episoden, Grafiken und Podcast-Beschreibungen, werden direkt von Sven Wiegand and Benjamin Hagemeister oder seinem Podcast-Plattformpartner hochgeladen und bereitgestellt. Wenn Sie glauben, dass jemand Ihr urheberrechtlich geschütztes Werk ohne Ihre Erlaubnis nutzt, können Sie dem hier beschriebenen Verfahren folgen https://de.player.fm/legal.

Änderungen beim ScalaProfis-Podcast

»Alles neu macht der Mai«. In diesem Sinne haben wir ein paar kleinere Anpassungen vorgenommen:

  • Die Episoden werden nun nicht mehr fortlaufend, sondern nach Jahr und Monat nummeriert — das ist unserer Meinung nach hilfreicher, da man die Episode gleich zeitlich einordnen kann.
  • Auf der Übersichtsseite werden nur noch die Themen der jeweiligen Episode aufgeführt.
  • Unterabschnitte der Show-Notes einer Episode sind jetzt besser als solche erkennbar.
  • Zu viele Kanäle machen die Pflege aufwändig. Daher konzentrieren wir uns auf Twitter und stellen die Google+ Seite ein.

ScalaJS

Sven hat sich mit ScalaJS beschäftigt.

Warum nicht direkt JavaScript?

Für jemanden, der statisch typisierte, mächtige Sprachen gewöhnt ist, ist das Programmieren in JavaScript kein Vergnügen:

  • die Auto-Completion in der IDE schlägt entweder nichts oder dutzende von (an dieser Stelle nicht relevanten) Feldern/Methoden vor
  • selbst simple Refactorings wie Umbenennungen erfordern viel Handarbeit — je allgemeiner der ursprüngliche Name, desto schlimmer
  • keine sinnvolle Modularisierung
  • umständliche Erstellung von Klassen
  • ungewohntes Sprachverhalten (Scope lokaler Variablen)
  • keine Immutability
  • geschwätzige Syntax (zumindest im Vergleich zu Scala)

Einiges wird mit ECMAScript 6 besser (Module, Arrow-Syntax für Funktionen, Klassen, let-Deklarationen für »korrektes« Scoping, const). In der Realität kommt man aber um einen ES6-nach-ES5-Transpiler wie Babel nicht herum.

Was für Alternativen gibt es zu JavaScript?

Wenn man eh einen Transpiler nutzt kann man auch gleich eine brauchbare Programmiersprache nehmen. Folgende Alternativen habe ich mir angeschaut:

  • CoffeeScript: Dynamisch, bringt somit nur marginale Verbesserungen, dafür ohne Runtime-Overhead (Library)
  • TypeScript: Sehr populär, statisch typisiert, erfordert somit Fassaden (für viele Libraries verfügbar), nicht sonderlich mächtig, kaum Runtime-Overhead
  • Kotlin: JavaScript-Generierung von Anfang an vorgesehen, schmale Standard-Library, aber noch nicht verfügbar
  • Scala.js: Volle Mächtigkeit von Scala zum Preis großer Runtime-Artefakte

Entscheidung für Scala.js

Maßgeblich war für mich die geplante Förderung von Scala.js durch das Scala Center — das suggeriert Ernsthaftigkeit und Zukunftssicherheit.

Ebenfalls interessant: Code-Sharing zwischen Frontend und Backend (ist natürlich via Node.js auch mit JavaScript möglich).

Wie funktioniert Scala.js

Scala.js ist im Wesentlichen ein Compile-Plug-In, das den Scala AST (der zuvor den größten Teil der Scala-To-JVM-Pipeline durchlaufen hat und dem entsprechend vereinfacht ist) in einen JavaScript AST übersetzt (Link).

Zum Zugriff auf JavaScript-Funktionen werden Fassaden benötigt. Die besorgt man sich entweder fertig oder man erstellt sie einfach selbst:

@js.native trait Window extends js.Object { val document: HTMLDocument = js.native var location: String = js.native def innerWidth: Int = js.native def innerHeight: Int = js.native def alert(message: String): Unit = js.native def open(url: String, target: String, features: String = ""): Window = js.native def close(): Unit = js.native } @js.native object GlobalDomDefinition extends js.GlobalScope { val window: Window = js.native } 

Um Scala-Klassen aus JavaScript nutzbar zu machen müssen diese exportiert werden:

@JSExport class Foo(val x: Int) { @JSExport def square(): Int = x*x // note the (), omitting them has a different behavior @JSExport("foobar") def add(y: Int): Int = x+y } 

Was geht nicht?

Es kann fast alles genutzt werden, was Scala bietet. Ausgeschlossen sind im Wesentlichen Reflection-basierte Funktionalitäten.

Wie sieht’s mit Performance und Overhead aus?

Um die Performance zu testen hat das Scala.js-Team einen Benchmark nach Scala.js überführt und die Ergebnisse auf der Scala.js-Seite veröffentlicht. Extrakt: Die Ausführung via Scala.js lag je nach Anwendungsfall 10 bis 20% über der nativen JavaScript-Lösung.

Ausnahme: Bei einem Collection-lastigen Test hat die Nutzung der Scala-Collections die Ausführungszeit um den Faktor 2.2 steigen lassen. Nachdem der Benchmark auf die Nutzung von JavsScript-Arrays umgestellt wurde, war der Benchmark wieder nur ca. 20% langsamer.

Was die Größe des resultierenden JavaScripts angeht: Während der Entwicklung wird zugunsten der Turnaround-Zeiten eine schnelle Optimierung durchgeführt. Ein einfaches AngularJS-Projekt hatte hier bei mir ca. 1 MB Größe. Der Release-Build wird unter Einsatz des Google Closure-Compilers größenoptimiert und lieferte bei mir 196 kB.

Aber Achtung: Der Google Closure Compiler macht die Anwendung wieder etwas langsamer.

Aufbau eines Scala.js-Projekts

Scala.js-Projekte werden mit SBT erstellt. Dabei kommen drei Source-Verzeichnisse zum Einsatz:

  • jvm: Scala-Sourcen hin, die nur für die JVM compiliert werden
  • js: Scala-Sourcen, die nur nach JavaScript compiliert werden
  • shared: Scala-Sourcen, die von jvm- und js-Sourcen genutzt werden können — diese werden also sowohl für die JVM als auch für JavaScript compiliert.

Ich habe Scala.js in einem Play-Projekt genutzt.

Testing & Debugging

ScalaTest 3 bringt als Haupt-Feature die Unterstützung für Scala.js — somit können die Tests mit einem bewährten Framework geschrieben werden.

Debugging im Browser funktioniert, da Scala.js Source-Maps generiert. Durch die Optimierung, sind allerdings teilweise Variablen nicht verfügbar und auf diversen Source-Zeilen können keine Breakpoints gesetzt werden. Evtl. müsste man mal probieren die Fast-Optimization im Entwicklungsprozess zu deaktivieren.

Erfahrungen

Mit Scala.js macht Frontend-Entwicklung endlich Spaß und wird produktiv! Wenn Fehler auftreten kann die Suche nach der Ursache aufwändig werden, aber wie immer hilft Erfahrung hier weiter.

Aufgrund des Overheads, den die Standard-Library produziert, ist Scala.js sicherlich nicht zum Aufwerten einer normalen Web-Seite geeignet. Geht es aber um eine vollwertige Web-Applikation, mit der sich der Anwender längere Zeit beschäftigt, steht in meinen Augen einer Nutzung in Produktivsystemen nichts mehr im Wege.

Links

Gradle vs. SBT

Gradle

  • In Groovy geschriebene DSL für Build-System
  • Plug-Ins können in jeder JVM Sprache geschrieben werden (also auch in Scala)
  • Convention over Configuration
  • Hervorragende Dokumentation
  • Ant-Tasks können direkt aus Gradle aufgerufen werden

Installation

Gradle muss nicht von allen Entwicklern installiert werden. Wenn ein Projekt neu aufgesetzt wird kann ein Entwickler der Gradle
installiert hat den Gradle-Wrapper erzeugen. Der Gradle-Wrapper wird dann zusammen mit dem restlichen Code im Repository abgelegt
und kann von allen anderen Entwicklern direkt verwendet werden.

Die konkrete Version ist dann Build-Skript festgelegt und wird bei der ersten Verwendung runter geladen.

Definieren von Abhängigkeiten

scalaMajorVersion = 2.10 scalaVersion = 2.10.5 dependencies { compile "org.scala-lang:scala-library:$scalaVersion" compile "org.scala-lang:scala-reflect:$scalaVersion" compile("com.escalatesoft.subcut:subcut_$scalaMajorVersion:2.0") { exclude module: 'scala-compiler' } } 

Definieren von Tasks

task taskA << { println("Hello Gradle!") } 

Etwas komplizierter:

task taskA { description "Gibt 'Hello Gradle!' aus" doLast { println("Hello Gradle!") } } 

Aufrufen von anderen Tasks

Aus einem Gradle-Task heraus können andere Tasks nicht direkt ausgeführt werden. Das geht nur indirekt über Abhängigkeiten:

task taskA { ... } task taskB { ... } task taskC { dependsOn(taskA, taskB) ... } 

Wenn sichergestellt werden muss, dann beim Aufruf von Task C erst A und dann B ausgeführt wird kann entweder noch eine Abhängigkeit
von Task B zu Task eingerichtet werden

taskB.dependsOn taskA 

oder (z.B. wenn Task B auch unabängig von Task A ausgeführt werden kann) über mustRunAfter eine Reihennfolge festgelegt werden:

taskB.mustRunAfter taskA 

Zugriff auf Einstellungen

task printMainTargetDirectory << { println(sourceSets.main.output.classesDir) } 

Solange man den Namen kennt kann man dynamisch auf jede Einstellung zugreifen. Allerdings ist das nicht typsicher und Tippfehler
fallen auch erst zur Laufzeit auf.

SBT

  • In Scala geschriebene DSL für Build-Systeme (wobei Benjamin findet, dass SBT eher eine API als eine DSL ist)
  • Convention over Configuration
  • Sehr gute Unterstützung von inkrementeller Compilierung
  • Man arbeitet in einer Konsole, so dass nicht für jeden Befehl die Build-Skripte neu kompiliert werden müssen
  • Cross-Compile für verschiedene Scala Versionen

Installation

SBT muss nicht installiert werden. Auf der Homepage kann man sich ein sehr schlankes Paket runterladen, dass so wie der Gradle-Wrapper
nur die unbendingt notwendigen Dateien enthält und den notwendigen Rest bei Bedarf nach lädt. Dieses Paket kann man auch im Repository
ablegen.

Die in einem Projekt verwendete SBT Version wird in project/build.properties definiert.

Definieren von Abhängigkeiten

scalaVersion in Global := "2.10.5" libraryDependencies ++= Seq( "org.scala-lang" % "scala-library" % scalaVersion.value, "org.scala-lang" % "scala-reflect" % scalaVersion.value, "com.escalatesoft.subcut" %% "subcut" % "2.0" exclude("org.scala-lang", "scala-compiler") ) 

Definieren von Tasks

val taskA = taskKey[Unit]("Gibt 'Hello sbt!' aus") taskA := { println("Hello sbt!") } 

Aufrufen von anderen Tasks

val taskA = taskKey[Unit]("...") val taskB = taskKey[Unit]("...") val taskC = taskKey[Unit]("...") taskC := { taskA.value taskB.value } 

Anders als man denken könnte führt taskC damit aber nicht taskA und taskB in der angegebenen Reihennfolge aus — zumindest
nicht solange es keine Abhängigkeiten zwischen den Tasks gibt. SBT führt die Tasks parallel aus und abhängig von den Tasks
und eventuellen Abhängigkeiten zu anderen Tasks kann es sogar sein, dass taskB vor taskA ausgeführt wird.

Wenn man eine bestimmte Reihenfolge erzwingen will kann man das wie bei Gradle über Abhängigkeiten machen oder über Def.sequential:

val taskA = taskKey[Unit]("...") val taskB = taskKey[Unit]("...") val taskC = taskKey[Unit]("...") taskA := ... taskB := ... taskC := Def.sequential(taskA, taskB).value 

Zugriff auf Einstellungen

val printMainTargetDirectory = taskKey[Unit]("Prints the main target directory") printMainTargetDirectory := println((classDirectory in Compile).value) 

Der Zugriff auf Einstellungen oder dem Rückgabewert einer Task erfolgt immer über .value. Das funktioniert aber nur innerhalb
einer Task oder wenn man den Wert für eine andere Einstellung festlegt.

Gradle vs. SBT

Vorteile Gradle

  • Dokumentation
  • Einfacher Zugriff auf Einstellungen (allerdings nicht Typsicher)
  • Besser lesbarer und verständlicherer Code

Vorteile SBT

  • Konsole
  • Performance (insbesonders inkrementelles compilieren, ausführen der durch eine Änderung betroffenen Tests)
  • Typsicher
  • Ökosystem

Links

Scala Native

Your favourite language gets closer to bare metal.

Ahead-of-time-Compilierung für Scala inklusive Low-Level-Operationen wie Structs und Pointer und Interoperabilität mit C.

Projekt vom EPFL.

Link

Scala Compiler Hacking

Miles Sabin hat in einem Blog erläutert wie er den PR für SI-2712 entwickelt hat.

Links

clippy

Clippy ist ein SBT-Plugin, dass schwer verständliche Compiler-Fehler in verständliche übersetzt.

Beispiel

[error] TheNextFacebook.scala:16: type mismatch; [error] found : akka.http.scaladsl.server.StandardRoute [error] required: akka.stream.scaladsl.Flow[akka.http.scaladsl.model.HttpRequest,akka.http.scaladsl.model.HttpResponse,Any] [error] Http().bindAndHandle(r, "localhost", 8080) 

wird übersetzt in

[error] Clippy advises: did you forget to define an implicit akka.stream.ActorMaterializer? [error] It allows routes to be converted into a flow. [error] You can read more at http://doc.akka.io/docs/akka-stream-and-http-experimental/2.0/scala/http/routing-dsl/index.html 

Links

https://github.com/softwaremill/scala-clippy

Einbetten von Dateiinhalten via Macro: Leider nicht praxistauglich

Sven hatte von seiner Lösung geschwärmt, bei der Inhalte einer HTML-Datei via Macro als String eingebettet wurden. Leider ist diese Lösung nicht praxistauglich, da SBT die Abhängigkeit zwischen den beiden Sourcen nicht korrekt erkennt: Ändert sich die HTML-Datei, so erkennt SBT nicht, dass es die importierende Scala-Source-Datei neu kompilieren muss. Somit ist diese Lösung nicht praktisch einsetzbar.

Expressions in string interpolation

Unser Hörer Daniel Jentsch hat sich Svens Fragestellung aus der letzten Episode angenommen, wie man einen String-Interpolator erstellt, der nicht das Ergebnis eines Ausdrucks einbettet, sondern den Ausdruck selbst (um z.B. Reafctoring-sichere Templates im Umfeld von Scala.js zu erstellen).

Das Ergebnis findet Ihr im Artikel Expressions in string interpolation

Libraray-Liste »Awesome Scala«

Awesome Scala ist eine von der Community erstellte Liste von nützlichen Scala-Libraries, Frameworks und Software.

Vielen Dank für den Tipp von Stefan Kaufmann.

Gib uns Dein Feedback als Kommentar auf unserer Web-Site, via Twitter oder Google+.

Kauf uns einen Kaffee

Kapitel

  1. Intro (00:00:00.000)
  2. Änderung beim ScalaProfis-Podcast (00:00:38.061)
  3. ScalaJS (00:03:07.939)
  4. Gradle vs. SBT (00:39:23.757)
  5. Scala Native (01:11:27.299)
  6. Scala Compiler Hacking (01:13:24.547)
  7. Clippy (01:14:23.267)
  8. Einbetten von Dateiinhalten via Macro (01:16:44.856)
  9. Expressions in string interpolation (01:18:40.792)
  10. Library-Liste »»Awesome Scala (01:19:55.267)
  11. Closer (01:21:12.978)

Lizenz

Creative Commons Lizenzvertrag
Scala Profis von Benjamin Hagemeister & Sven Wiegand ist lizenziert unter einer Creative Commons Namensnennung — Keine Bearbeitungen 4.0 International Lizenz.

Über diese Lizenz hinausgehende Erlaubnisse kannst Du unter http://scalaprofis.de erhalten.

Titelsong basierend auf Wish You Were Here von THE.MADPIX.PROJECT lizensiert unter Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0).

  continue reading

Kapitel

1. Intro (00:00:00)

2. Änderung beim ScalaProfis-Podcast (00:00:38)

3. ScalaJS (00:03:07)

4. Gradle vs. SBT (00:39:23)

5. Scala Native (01:11:27)

6. Scala Compiler Hacking (01:13:24)

7. Clippy (01:14:23)

8. Einbetten von Dateiinhalten via Macro (01:16:44)

9. Expressions in string interpolation (01:18:40)

10. Library-Liste ""Awesome Scala (01:19:55)

11. Closer (01:21:12)

15 Episoden

Artwork

SP05/16: Scala.js, Gradle vs. SBT

Scala Profis

13 subscribers

published

iconTeilen
 
Manage episode 157012356 series 1206977
Inhalt bereitgestellt von Sven Wiegand and Benjamin Hagemeister. Alle Podcast-Inhalte, einschließlich Episoden, Grafiken und Podcast-Beschreibungen, werden direkt von Sven Wiegand and Benjamin Hagemeister oder seinem Podcast-Plattformpartner hochgeladen und bereitgestellt. Wenn Sie glauben, dass jemand Ihr urheberrechtlich geschütztes Werk ohne Ihre Erlaubnis nutzt, können Sie dem hier beschriebenen Verfahren folgen https://de.player.fm/legal.

Änderungen beim ScalaProfis-Podcast

»Alles neu macht der Mai«. In diesem Sinne haben wir ein paar kleinere Anpassungen vorgenommen:

  • Die Episoden werden nun nicht mehr fortlaufend, sondern nach Jahr und Monat nummeriert — das ist unserer Meinung nach hilfreicher, da man die Episode gleich zeitlich einordnen kann.
  • Auf der Übersichtsseite werden nur noch die Themen der jeweiligen Episode aufgeführt.
  • Unterabschnitte der Show-Notes einer Episode sind jetzt besser als solche erkennbar.
  • Zu viele Kanäle machen die Pflege aufwändig. Daher konzentrieren wir uns auf Twitter und stellen die Google+ Seite ein.

ScalaJS

Sven hat sich mit ScalaJS beschäftigt.

Warum nicht direkt JavaScript?

Für jemanden, der statisch typisierte, mächtige Sprachen gewöhnt ist, ist das Programmieren in JavaScript kein Vergnügen:

  • die Auto-Completion in der IDE schlägt entweder nichts oder dutzende von (an dieser Stelle nicht relevanten) Feldern/Methoden vor
  • selbst simple Refactorings wie Umbenennungen erfordern viel Handarbeit — je allgemeiner der ursprüngliche Name, desto schlimmer
  • keine sinnvolle Modularisierung
  • umständliche Erstellung von Klassen
  • ungewohntes Sprachverhalten (Scope lokaler Variablen)
  • keine Immutability
  • geschwätzige Syntax (zumindest im Vergleich zu Scala)

Einiges wird mit ECMAScript 6 besser (Module, Arrow-Syntax für Funktionen, Klassen, let-Deklarationen für »korrektes« Scoping, const). In der Realität kommt man aber um einen ES6-nach-ES5-Transpiler wie Babel nicht herum.

Was für Alternativen gibt es zu JavaScript?

Wenn man eh einen Transpiler nutzt kann man auch gleich eine brauchbare Programmiersprache nehmen. Folgende Alternativen habe ich mir angeschaut:

  • CoffeeScript: Dynamisch, bringt somit nur marginale Verbesserungen, dafür ohne Runtime-Overhead (Library)
  • TypeScript: Sehr populär, statisch typisiert, erfordert somit Fassaden (für viele Libraries verfügbar), nicht sonderlich mächtig, kaum Runtime-Overhead
  • Kotlin: JavaScript-Generierung von Anfang an vorgesehen, schmale Standard-Library, aber noch nicht verfügbar
  • Scala.js: Volle Mächtigkeit von Scala zum Preis großer Runtime-Artefakte

Entscheidung für Scala.js

Maßgeblich war für mich die geplante Förderung von Scala.js durch das Scala Center — das suggeriert Ernsthaftigkeit und Zukunftssicherheit.

Ebenfalls interessant: Code-Sharing zwischen Frontend und Backend (ist natürlich via Node.js auch mit JavaScript möglich).

Wie funktioniert Scala.js

Scala.js ist im Wesentlichen ein Compile-Plug-In, das den Scala AST (der zuvor den größten Teil der Scala-To-JVM-Pipeline durchlaufen hat und dem entsprechend vereinfacht ist) in einen JavaScript AST übersetzt (Link).

Zum Zugriff auf JavaScript-Funktionen werden Fassaden benötigt. Die besorgt man sich entweder fertig oder man erstellt sie einfach selbst:

@js.native trait Window extends js.Object { val document: HTMLDocument = js.native var location: String = js.native def innerWidth: Int = js.native def innerHeight: Int = js.native def alert(message: String): Unit = js.native def open(url: String, target: String, features: String = ""): Window = js.native def close(): Unit = js.native } @js.native object GlobalDomDefinition extends js.GlobalScope { val window: Window = js.native } 

Um Scala-Klassen aus JavaScript nutzbar zu machen müssen diese exportiert werden:

@JSExport class Foo(val x: Int) { @JSExport def square(): Int = x*x // note the (), omitting them has a different behavior @JSExport("foobar") def add(y: Int): Int = x+y } 

Was geht nicht?

Es kann fast alles genutzt werden, was Scala bietet. Ausgeschlossen sind im Wesentlichen Reflection-basierte Funktionalitäten.

Wie sieht’s mit Performance und Overhead aus?

Um die Performance zu testen hat das Scala.js-Team einen Benchmark nach Scala.js überführt und die Ergebnisse auf der Scala.js-Seite veröffentlicht. Extrakt: Die Ausführung via Scala.js lag je nach Anwendungsfall 10 bis 20% über der nativen JavaScript-Lösung.

Ausnahme: Bei einem Collection-lastigen Test hat die Nutzung der Scala-Collections die Ausführungszeit um den Faktor 2.2 steigen lassen. Nachdem der Benchmark auf die Nutzung von JavsScript-Arrays umgestellt wurde, war der Benchmark wieder nur ca. 20% langsamer.

Was die Größe des resultierenden JavaScripts angeht: Während der Entwicklung wird zugunsten der Turnaround-Zeiten eine schnelle Optimierung durchgeführt. Ein einfaches AngularJS-Projekt hatte hier bei mir ca. 1 MB Größe. Der Release-Build wird unter Einsatz des Google Closure-Compilers größenoptimiert und lieferte bei mir 196 kB.

Aber Achtung: Der Google Closure Compiler macht die Anwendung wieder etwas langsamer.

Aufbau eines Scala.js-Projekts

Scala.js-Projekte werden mit SBT erstellt. Dabei kommen drei Source-Verzeichnisse zum Einsatz:

  • jvm: Scala-Sourcen hin, die nur für die JVM compiliert werden
  • js: Scala-Sourcen, die nur nach JavaScript compiliert werden
  • shared: Scala-Sourcen, die von jvm- und js-Sourcen genutzt werden können — diese werden also sowohl für die JVM als auch für JavaScript compiliert.

Ich habe Scala.js in einem Play-Projekt genutzt.

Testing & Debugging

ScalaTest 3 bringt als Haupt-Feature die Unterstützung für Scala.js — somit können die Tests mit einem bewährten Framework geschrieben werden.

Debugging im Browser funktioniert, da Scala.js Source-Maps generiert. Durch die Optimierung, sind allerdings teilweise Variablen nicht verfügbar und auf diversen Source-Zeilen können keine Breakpoints gesetzt werden. Evtl. müsste man mal probieren die Fast-Optimization im Entwicklungsprozess zu deaktivieren.

Erfahrungen

Mit Scala.js macht Frontend-Entwicklung endlich Spaß und wird produktiv! Wenn Fehler auftreten kann die Suche nach der Ursache aufwändig werden, aber wie immer hilft Erfahrung hier weiter.

Aufgrund des Overheads, den die Standard-Library produziert, ist Scala.js sicherlich nicht zum Aufwerten einer normalen Web-Seite geeignet. Geht es aber um eine vollwertige Web-Applikation, mit der sich der Anwender längere Zeit beschäftigt, steht in meinen Augen einer Nutzung in Produktivsystemen nichts mehr im Wege.

Links

Gradle vs. SBT

Gradle

  • In Groovy geschriebene DSL für Build-System
  • Plug-Ins können in jeder JVM Sprache geschrieben werden (also auch in Scala)
  • Convention over Configuration
  • Hervorragende Dokumentation
  • Ant-Tasks können direkt aus Gradle aufgerufen werden

Installation

Gradle muss nicht von allen Entwicklern installiert werden. Wenn ein Projekt neu aufgesetzt wird kann ein Entwickler der Gradle
installiert hat den Gradle-Wrapper erzeugen. Der Gradle-Wrapper wird dann zusammen mit dem restlichen Code im Repository abgelegt
und kann von allen anderen Entwicklern direkt verwendet werden.

Die konkrete Version ist dann Build-Skript festgelegt und wird bei der ersten Verwendung runter geladen.

Definieren von Abhängigkeiten

scalaMajorVersion = 2.10 scalaVersion = 2.10.5 dependencies { compile "org.scala-lang:scala-library:$scalaVersion" compile "org.scala-lang:scala-reflect:$scalaVersion" compile("com.escalatesoft.subcut:subcut_$scalaMajorVersion:2.0") { exclude module: 'scala-compiler' } } 

Definieren von Tasks

task taskA << { println("Hello Gradle!") } 

Etwas komplizierter:

task taskA { description "Gibt 'Hello Gradle!' aus" doLast { println("Hello Gradle!") } } 

Aufrufen von anderen Tasks

Aus einem Gradle-Task heraus können andere Tasks nicht direkt ausgeführt werden. Das geht nur indirekt über Abhängigkeiten:

task taskA { ... } task taskB { ... } task taskC { dependsOn(taskA, taskB) ... } 

Wenn sichergestellt werden muss, dann beim Aufruf von Task C erst A und dann B ausgeführt wird kann entweder noch eine Abhängigkeit
von Task B zu Task eingerichtet werden

taskB.dependsOn taskA 

oder (z.B. wenn Task B auch unabängig von Task A ausgeführt werden kann) über mustRunAfter eine Reihennfolge festgelegt werden:

taskB.mustRunAfter taskA 

Zugriff auf Einstellungen

task printMainTargetDirectory << { println(sourceSets.main.output.classesDir) } 

Solange man den Namen kennt kann man dynamisch auf jede Einstellung zugreifen. Allerdings ist das nicht typsicher und Tippfehler
fallen auch erst zur Laufzeit auf.

SBT

  • In Scala geschriebene DSL für Build-Systeme (wobei Benjamin findet, dass SBT eher eine API als eine DSL ist)
  • Convention over Configuration
  • Sehr gute Unterstützung von inkrementeller Compilierung
  • Man arbeitet in einer Konsole, so dass nicht für jeden Befehl die Build-Skripte neu kompiliert werden müssen
  • Cross-Compile für verschiedene Scala Versionen

Installation

SBT muss nicht installiert werden. Auf der Homepage kann man sich ein sehr schlankes Paket runterladen, dass so wie der Gradle-Wrapper
nur die unbendingt notwendigen Dateien enthält und den notwendigen Rest bei Bedarf nach lädt. Dieses Paket kann man auch im Repository
ablegen.

Die in einem Projekt verwendete SBT Version wird in project/build.properties definiert.

Definieren von Abhängigkeiten

scalaVersion in Global := "2.10.5" libraryDependencies ++= Seq( "org.scala-lang" % "scala-library" % scalaVersion.value, "org.scala-lang" % "scala-reflect" % scalaVersion.value, "com.escalatesoft.subcut" %% "subcut" % "2.0" exclude("org.scala-lang", "scala-compiler") ) 

Definieren von Tasks

val taskA = taskKey[Unit]("Gibt 'Hello sbt!' aus") taskA := { println("Hello sbt!") } 

Aufrufen von anderen Tasks

val taskA = taskKey[Unit]("...") val taskB = taskKey[Unit]("...") val taskC = taskKey[Unit]("...") taskC := { taskA.value taskB.value } 

Anders als man denken könnte führt taskC damit aber nicht taskA und taskB in der angegebenen Reihennfolge aus — zumindest
nicht solange es keine Abhängigkeiten zwischen den Tasks gibt. SBT führt die Tasks parallel aus und abhängig von den Tasks
und eventuellen Abhängigkeiten zu anderen Tasks kann es sogar sein, dass taskB vor taskA ausgeführt wird.

Wenn man eine bestimmte Reihenfolge erzwingen will kann man das wie bei Gradle über Abhängigkeiten machen oder über Def.sequential:

val taskA = taskKey[Unit]("...") val taskB = taskKey[Unit]("...") val taskC = taskKey[Unit]("...") taskA := ... taskB := ... taskC := Def.sequential(taskA, taskB).value 

Zugriff auf Einstellungen

val printMainTargetDirectory = taskKey[Unit]("Prints the main target directory") printMainTargetDirectory := println((classDirectory in Compile).value) 

Der Zugriff auf Einstellungen oder dem Rückgabewert einer Task erfolgt immer über .value. Das funktioniert aber nur innerhalb
einer Task oder wenn man den Wert für eine andere Einstellung festlegt.

Gradle vs. SBT

Vorteile Gradle

  • Dokumentation
  • Einfacher Zugriff auf Einstellungen (allerdings nicht Typsicher)
  • Besser lesbarer und verständlicherer Code

Vorteile SBT

  • Konsole
  • Performance (insbesonders inkrementelles compilieren, ausführen der durch eine Änderung betroffenen Tests)
  • Typsicher
  • Ökosystem

Links

Scala Native

Your favourite language gets closer to bare metal.

Ahead-of-time-Compilierung für Scala inklusive Low-Level-Operationen wie Structs und Pointer und Interoperabilität mit C.

Projekt vom EPFL.

Link

Scala Compiler Hacking

Miles Sabin hat in einem Blog erläutert wie er den PR für SI-2712 entwickelt hat.

Links

clippy

Clippy ist ein SBT-Plugin, dass schwer verständliche Compiler-Fehler in verständliche übersetzt.

Beispiel

[error] TheNextFacebook.scala:16: type mismatch; [error] found : akka.http.scaladsl.server.StandardRoute [error] required: akka.stream.scaladsl.Flow[akka.http.scaladsl.model.HttpRequest,akka.http.scaladsl.model.HttpResponse,Any] [error] Http().bindAndHandle(r, "localhost", 8080) 

wird übersetzt in

[error] Clippy advises: did you forget to define an implicit akka.stream.ActorMaterializer? [error] It allows routes to be converted into a flow. [error] You can read more at http://doc.akka.io/docs/akka-stream-and-http-experimental/2.0/scala/http/routing-dsl/index.html 

Links

https://github.com/softwaremill/scala-clippy

Einbetten von Dateiinhalten via Macro: Leider nicht praxistauglich

Sven hatte von seiner Lösung geschwärmt, bei der Inhalte einer HTML-Datei via Macro als String eingebettet wurden. Leider ist diese Lösung nicht praxistauglich, da SBT die Abhängigkeit zwischen den beiden Sourcen nicht korrekt erkennt: Ändert sich die HTML-Datei, so erkennt SBT nicht, dass es die importierende Scala-Source-Datei neu kompilieren muss. Somit ist diese Lösung nicht praktisch einsetzbar.

Expressions in string interpolation

Unser Hörer Daniel Jentsch hat sich Svens Fragestellung aus der letzten Episode angenommen, wie man einen String-Interpolator erstellt, der nicht das Ergebnis eines Ausdrucks einbettet, sondern den Ausdruck selbst (um z.B. Reafctoring-sichere Templates im Umfeld von Scala.js zu erstellen).

Das Ergebnis findet Ihr im Artikel Expressions in string interpolation

Libraray-Liste »Awesome Scala«

Awesome Scala ist eine von der Community erstellte Liste von nützlichen Scala-Libraries, Frameworks und Software.

Vielen Dank für den Tipp von Stefan Kaufmann.

Gib uns Dein Feedback als Kommentar auf unserer Web-Site, via Twitter oder Google+.

Kauf uns einen Kaffee

Kapitel

  1. Intro (00:00:00.000)
  2. Änderung beim ScalaProfis-Podcast (00:00:38.061)
  3. ScalaJS (00:03:07.939)
  4. Gradle vs. SBT (00:39:23.757)
  5. Scala Native (01:11:27.299)
  6. Scala Compiler Hacking (01:13:24.547)
  7. Clippy (01:14:23.267)
  8. Einbetten von Dateiinhalten via Macro (01:16:44.856)
  9. Expressions in string interpolation (01:18:40.792)
  10. Library-Liste »»Awesome Scala (01:19:55.267)
  11. Closer (01:21:12.978)

Lizenz

Creative Commons Lizenzvertrag
Scala Profis von Benjamin Hagemeister & Sven Wiegand ist lizenziert unter einer Creative Commons Namensnennung — Keine Bearbeitungen 4.0 International Lizenz.

Über diese Lizenz hinausgehende Erlaubnisse kannst Du unter http://scalaprofis.de erhalten.

Titelsong basierend auf Wish You Were Here von THE.MADPIX.PROJECT lizensiert unter Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0).

  continue reading

Kapitel

1. Intro (00:00:00)

2. Änderung beim ScalaProfis-Podcast (00:00:38)

3. ScalaJS (00:03:07)

4. Gradle vs. SBT (00:39:23)

5. Scala Native (01:11:27)

6. Scala Compiler Hacking (01:13:24)

7. Clippy (01:14:23)

8. Einbetten von Dateiinhalten via Macro (01:16:44)

9. Expressions in string interpolation (01:18:40)

10. Library-Liste ""Awesome Scala (01:19:55)

11. Closer (01:21:12)

15 Episoden

Alle Folgen

×
 
Loading …

Willkommen auf Player FM!

Player FM scannt gerade das Web nach Podcasts mit hoher Qualität, die du genießen kannst. Es ist die beste Podcast-App und funktioniert auf Android, iPhone und im Web. Melde dich an, um Abos geräteübergreifend zu synchronisieren.

 

Kurzanleitung