JS-Labs PT.3: Schlankere Controller durch Bindings mit AngularJS!
In meinem letzten Post habe ich gezeigt wie Jasmine und Coffeescript schönen Test-Code schreiben kann. In diesem Post werde ich zeigen wie sich Controller-Code durch Bindings mit AngularJS vereinfachen lässt.
Mein bisheriger Controller
Meine Arbeiten an der jQuery-Version des Wakmarks-Projekts neigen sich dem Ende zu. Ein Anti-Pattern was sich herauskristallisiert ist, dass der Controller bei diversen Events sowohl Model als auch View aktualisieren muss.
Als Beispiel soll hier der ‘click’-Handler auf dem “gelesen”-Button eines Bookmarks dienen. Mit dem Button lässt sich der Zustand eines Bookmarks zwischen “gelesen” und “ungelesen” wechseln:
onBookmarkReadClick : (event) -> bookmarkView = $(event.target).parents(".bookmark")# update the model ... bookmark = Bookmark.find(bookmarkView.data('id')) bookmark.read = !bookmark.read# ... and the viewif(bookmark.read) $(event.target).addClass('read') $(event.target).removeClass('unread') else $(event.target).addClass('unread') $(event.target).removeClass('read')
Das “M” und das “V” im MVC
Schön wäre es, wenn der Controller nur das Model aktualisieren müsste und sich der View dann automatisch aktuallisiert. Im klassischen MVC wird das Problem durch das Observer-Muster gelöst.
(original von Wikipedia)
In meinem Beispiel besteht der View aber aus purem HTML:
<div data-id="1"> ... <button class="unread"> </button> ... </div>
Was also tun?
Bindings
Glücklicherweise gibt es Frameworks die sogenannte Bindings anbieten. Durch Bindings lassen sich Attribute des Models an HTML-Elemente des Views binden und automatisch damit synchronisieren. Letztendlich handelt es sich um vereinfachte Variante um mit dem Observer-Musters zu arbeiten.
Mit AngularJS kann der Code des Controllers damit stark vereinfacht werden:
$scope.onBookmarkReadClick = (bookmark) -> bookmark.read = !bookmark.read$scope.getBookmarkReadClass = (bookmark) -> if bookmark.read "read" else "unread"
Eigentlich wäre es ein Zweizeiler gewesen, aber leider leider unterstützten AngularJS-Bindings keine Kontrollstrukturen, weshalb es die weitere Methode “getBookmarkReadClass” benötigt um den read-Flag in einen CSS-Klassennamen umzuwandeln.
Der View sieht dann so aus:
<div class="bookmark" data-id="{{bookmark.id}}">
...
<button class="{{getReadClassName(bookmark)}}"> </button>
...
</div>
Filter
Mir gefällt diese Variante schon deutlich besser, aber mich stört die Methode “getBookmarkReadClass” in meinem Controller. Es gibt in AngularJS auch die Möglichkeit eigene Filter zu definieren, damit liesse sich der View in etwa so schreiben:
<div data-id="{{bookmark.id}}">
...
<button class="bookmark.read | to_bookmark_class"> </button>
...
</div>
Die Methode “getBookmarkReadClass” könnte damit entfernt werden. Allerdings habe ich es nicht geschafft einen solchen Filter zu schreiben, da die Dokumenation nicht aktuell ist.
Weitere Frameworks mit Binding-Support
Morgen werde ich mir noch Batman-JS anschauen. Ein weiteres Framework mit Bindings wäre noch Ember-JS, welches aber leider nicht zu CoffeeScript kompatibel ist. Ein Vergleich verschiedener MVC Frameworks gibt es hier.
24.04.12
JS-Labs PT. 2: Javascript sauber testen mit Jasmine und Coffeescript
Im ersten JS-Labs Post habe ich angekündigt, dass ich mir verschiedene Frameworks zur RIA Entwicklung mit Javascript anschauen werde.
Der erste Versuch soll eine reine jQuery-Entwicklung werden – Keine kompletten MVC-Frameworks, nur jQuery mit ein paar Extras. Dazu habe ich mir das Testframework Jasmine und die Scriptsprache CoffeeScript angschaut.
Jasmine ist ein behaviour-driven-development-framework um Tests im Stil von rspec zu schreiben. CoffeeScript ist eine Scriptsprache die direkt in Javascript kompiliert. Die Kombination aus beiden führt zu sehr schönen Tests!
Hier ein vereinfachtes Beispiel der Suite für die Bookmark-Klasse aus dem Wakmarks-Projekt:
describe "Bookmark", ->bookmark = null beforeEach -> bookmark = new Bookmark(1, "A Bookmark", "http://google.de")it "should have correct id", -> expect(bookmark.id).toEqual(1)it "should have correct name", -> expect(bookmark.name).toEqual("A Bookmark")it "should have correct URL", -> expect(bookmark.url).toEqual("http://google.de")
Das Ergebnis ist sehr übersichtlich, wie ich finde.
Die getestete Bookmark-Klasse sieht in CoffeeScript so aus:
class Bookmark constructor: (@id, @name, @url) ->
Also wenn das nicht cool ist?
22.04.12JS-Labs – Wakmarks PT.1
In den nächsten Tagen werde ich verschiedene Frameworks zur RIA-Entwicklung austesten. Primär interessieren mich dabei die folgenden Punkte:
- MVC
- Dependency Injection
- Testbarkeit
- Performance
Momentan habe ich vor allem einen Blick auf AngularJS und JavascriptMVC.
Ich habe mir zu Testzwecken eine kleine WebApp überlegt um Bookmarks zu verwalten. Natürlich gibt es dafür schon tausende, es geht jar nur ums ausprobieren

Ich werde in nächster Zeit drei Protoypen bauen, jeweils mit UnterschiedlichenTTechnologien:
- jQuery plus diverse Plugins für Unit-Tests und Klassen.
- AngularJS
- JavascriptMVC
Die statische Variante (ohne Funktion) ist bereits hier (ja ich weiss: schön ist was anderes ;D). In den folgenden Parts werde ich dann die einzelnen Prototypen vorstellen.
| Posted in Basteleien, Javascript | 1 Comment »
Rest in peace Flex … oder: was ich in der Javascript-Welt vermisse …
Seit ich HTML und Javascript entwickele, wächst in mir eine Trauer. Ich trauere um Flex und ich trauere um Actionscript. Ich trauere um eine Art der RIA-Entwicklung, wie sie sein sollte. Actionscript und vor allem das Flex-Framework boten so vieles, was ich in der Javascript-Welt einfach nicht wiederfinde.
Im Folgenden werde ich auf einige Dinge eingehen, die mir ganz besonders fehlen. Für Lösungsvorschläge bin ich natürlich sehr dankbar!
Vollständige, flexible und stylebare UI-Komponenten
Hier hatte ich nie mit Problemen gerechnet. Für mich war beim Wechsel ganz klar, das es da draussen UI-Bibliotheken geben müsse, die zumindest annähernd so vollständig und flexibel sind, wie die von Flex … Aber Pustekuchen!
jQueryUI, YUI und wie sie alle heissen, sie alle bieten nur eine unvollständige Anzahl an zusammengewürfelten Komponenten, die wenig mit einemv ollständigen Baukasten für eine RIA zu tun haben. Zudem haben sie meist kein einheitliches Konzept von Erweiterbarkeit oder Wiederverwendbarkeit. Und noch dazu ist das Styling in CSS meist die Hölle. Mein Lieblingsbeispiel ist hier das Menu von YUI-3 : Schwierig zu stylen, so gut wie nicht konfigurierbar, es gibt überhaupt keine Events und beim Initialisieren der Seite zickt und zuckt es das ich Augenkrebs bekomme. Und das ist die Zukunft?
Wer mir ein open-source UI-Framework nennen kann, das so vollständig, so einfach zu verwenden, zu stylen und trotzdem so anpassbar wie Flex ist, dem werd ich persönlich die Füße küssen!
Data-Binding
In Flex ist das Entwickeln von Views einfach genial. Mittels Data-Binding werden Daten des Models gebunden und damit ist das View-Verhalten ganz klar vom Controller-Code getrennt. Und wie ist das mit jQuery? Hmm … zugegeben: es ist deutlich besser als mit reinem Javascript, aber jetzt manipuliert man mit jQuery Daten des DOM und wo liegt dieser Code? Im Controller? Gehört er hier wirklich hin? Ein Blick in die Dokumentation von JavascriptMVC bestätigt es mir, ja da kommt er hin!
Durch Data-Binding in Flex ist es möglich Views zu entwickeln, von denen der Controller nichts weiss. Ich denke dies ist der richtige Weg um Wiederverwendbarkeit zu erlangen, da der View jederzeit ausgetauscht werden kann, genauso wie der Controller. Mit gängigen Javascript-Frameworks wird das ganze so streng mit einander verwoben, das hier von Wiederverwendbarkeit keine Rede sein kann.
ECMAScript 4
ECMAScript 4 … das sollte einmal ein Javascript-Standard werden:
Though flexible and formally powerful, the abstraction facilities of ES3 are often inadequate in practice for the development of large software systems. ECMAScript programs are becoming larger and more complex with the adoption of Ajax programming on the web and the extensive use of ECMAScript as an extension and scripting language in applications. The development of large programs can benefit substantially from facilities like static type checking, name hiding, early binding and other optimization hooks, and direct support for object-oriented programming, all of which are absent from ES3.
ECMAScript 4 wurde aber aus irgendwelchen politischen Gründen der Browserhersteller verworfen, allerdings erst nachdem Actionscript 3 diesen Standard bereits adaptiert hat. Mir ist es bis heute nicht klar warum, dieser Standard hätte so vieles ändern können. Während Actionscript sich bereits seit guten 5 Jahren wie eine ausgewachsene Programmiersprache anfühlt, fühlt man sich bei Javascript immer noch wie ein Script-Kiddie, dem offenbar keine Grenzen gesetzt sind.
Bei Javascript ist alles möglich und das liegt hauptsächlich am sog. “Prototyping“, dem Vererbungsmechanismus in Javascript. Das Prototyping ist meiner Meinung nach eine Katastrophe, die Dinge zulässt, die in einer objektorientierten Programmiersprache nicht möglich sein dürfen. Und was haben wir statt dem? Dutzende Frameworks, die versuchen genau diese Probleme lösen, in dem mittels Prototyping eine Abstraktion geschaffen wird, um eine OO-Sprache nachzuahmen. Jedes Framework meint das besser zu können als andere Frameworks. Damit ist jede einzelne Klasse, die ich in einem solchen Framework schreibe, eben an dieses Framework gebunden. Mit anderen Worten: Fast jedes Framework bringt seine eigene Programmiersprache mit sich.
Multimedia-Formate
Dazu gibt es nicht viel zu sagen: in Flash brauche ich ein Video oder Musikstück nur in einem Format ausliefern, in der HTML-Welt muss ich Multimedia-Formate für verschiedene Browser in verschiedenen Formaten abliefern. Hier wird so schnell leider keine Javascript Bibliothek Abhilfe schaffen können.
Event-Modell
Das Event-Modell von Javascript ist nicht einheitlich. Der eine Browser unterstützt Event-Bubbling, der andere Event-Capturing und mit jQuery erhalte ich auch ein einheitliches Event-Modell, bei dem ich aber folglich weder Bubbling noch Capturing verwenden darf, weil eben nicht jeder Browser unterstützt wird. Korrigiert mich bitte wenn ich hier falsch liege. Auch hier wird leider kein Framework Abhilfe schaffen können.
Fazit
Wie gut die Aussicht hinsichtlich UI-Komponenten ist, weiss ich nicht. Ich hoffe einfach darauf, dass irgendwann einmal das Thema von kompetenten Entwicklern in die Hand genommen wird und ein reichhaltiges UI-Framework geschaffen wird. Leider ist dies keine einfache Aufgabe, hier sind sicherlich viele Mannjahre an Arbeit erforderlich.
Hinsichtlich Data-Binding ist das AngularJS-Framework sehr vielversprechend. Dieses werde ich mir in nächster Zeit genauer anschauen.
Die Punkte ECMAScript 4, Multimedia-Formate und Event-Modell sind mit einer Javascript Bibliothek oder einem Framework vermutlich nicht so einfach lösbar. Das ist die alleinige Schuld der Browser-Hersteller!
Ich sehne mich nach einer Zukunft ohne Flash, aber in dieser Zukunft muss die HTML-Welt liefern, was in Flash schon seit Jahren Realität ist!
| Posted in Actionscript, Javascript | 1 Comment »
von der XBOX zum HTPC
Medien lassen sich auf viele verschiedene Weise im Wohnzimmer abspielen. Eine brauchbare Möglichkeit ist heute der oftmals im TV eingebaute Media-Player. Es gibt aber auch dedizierte Player, wie beispielsweise die Produkte von Pocorn Hour. Aber gerade ersteres hat meistens ein stark eingeschränktes Interface und spielt meist nur eine Hand voll Formate ab. Für Bastler, zu denen ich mich zähle, war jahrelang die erste XBOX mit XBMC eine gute Wahl. In letzter Zeit wird auch die Kategorie des sog. Home Theater Personal Computer (HTPC) immer interessanter.
Auch ich habe mich dazu entschieden einen HTPC zu bauen. Ausschlaggebend dafür war, dass meine alte XBOX technisch den heutigen Formaten nicht mehr gewachsen ist. Ich wollte eine Lösung, die alles kann: Alle möglichen Film-Formate abspielen und für Musik sollte ich nicht extra den TV einschalten müssen! Ein HTPC, mit der richtigen Software, erfüllt diese Anforderungen.
Media Center PCs (bzw. HTPCs) hatten lange Zeit gewaltige Nachteile im Bereich Stromverbauch, Wärmeentwicklung und damit auch der Lautstärke. Ende 2008 änderte sich dies, denn hier begann Intel mit dem Vertrieb der Atom-CPUs, welche weniger auf Performance, sondern auf niedrigen Stromverbrauch (~8Watt TDP) ausgelegt sind. Seit 2010 beinhalten diese CPUs gleichzeitig auch eine GPU, so dass theoretisch der Einsatz einer dedizierten Grafikkarte unnötig gemacht wurde. Allerdings hatte diese GPI keine HD-Fähigkeiten und die CPU alleine reicht hierfür schlichtweg nicht aus. Im Jahr 2011 stieg auch AMD in diesen Markt ein und liefert mit ihrer Fusion-Reihe eine CPU mit integrierter Radeon HD GPU, welcher in meinen Augen nun den Durchbruch zum kostengünstigen, stromsparenden HTPC darstellt.
Erst einmal Hardware einkaufen …
Nach einigen Recherchen und Unterstützung von Kollegen, hatte ich meine Wunschkonfiguration gefunden:
- Gehäuse: Silverstone La Scala LC19B-R (inkl. 120W Netzteil), 140€
Das Gehäuse hat einfach Style! Ausserdem hat es den Vorteil, dass es bereits mit einem lüfterlosen 120W Netzteil verbaut ist. Mehr Power benötigt so ein HTPC in der Regel nicht. Es ist sehr flach und passt sich damit perfekt in die TV-Landschaft ein. Ein LCD-Display oder eine Fernbedienung fehlt leider – da ich aber die Box sowieso per Android-Phone oder Maus steuere, ist dies für mich kein Negativpunkt. - Mainboard (inkl. Atom Fusion 350) : Gigabyte GA-E350N-USB3, 93€
Dieses Board ist sehr günstig, besitzt aber auch keinerlei Schnickschnack wie WLAN oder Bluetooth. Dafür ist es im Vergleich zu anderen Boards sehr energieeffizient.
RAM : 4GB 1066 CL7 , 15 €
Da das Board kein Dual-Channel unterstützt, braucht man hier nur einen einzigen Riegel kaufen.- SSD: 16GB Kinston S100, 41€
Die SDD dient als reine Systemplatte, damit der HTPC schnell bootet. - Optisches Laufwerk: Samsung SN-208BB, 21€
Für ca. 40 € Aufpreis bekommt man ein Slimeline Blueray Laufwerk. Das habe ich mir gespart, da ich für die Blueray-Wiedergabe noch eine PS3 besitze.
Das macht also summa summarum ca. 310 €. Allerdings fehlt bei der Konfiguration noch eine Daten-Platte sowie TV-Karte. Glücklicherweise hatte ich noch eine 2TB Festplatte herumliegen. Die Festplattenpreise sind derzeit aufgrund der Flutkatastrophe in Thailand nämlich horrend hoch. Auf eine TV-Karte kann ich vorerst verzichten.
Putting it all together

Wenn man die Verpackung des Motherboards in die Hand nimmt, fällt einem schon auf wie klein es eigentlich ist. Aber beim Auspacken ist man völlig baff. Der CPU-Lüfter ist gerade einmal 2 Daumen dick!
Das Gehäuse ist sehr gut verarbeitet und bei diesem kleinen Mainboard ist der Platz mehr als ausreichend. Laut Herstellerangaben kann in dem Gehäuse nur eine 2,5 oder 3,5″ HDD verbaut werden, allerdings habe ich mindestens 3 weitere mögliche Orte gefunden, um 2,5″ Laufwerke unter zu bringen.




Die Hardware-Installation lief nahezu reibungslos ab. Einzig das DVD-Rom konnte ich nicht sofort in Betrieb nehmen, da es einen speziellen Mikro-SATA Adapter (ca. 5€) benötigt. Also musste für die Betriebsystem-Installation erstmal das DVD-Laufwerk meines PCs herhalten.
… fehlt noch das Betriebsystem!

Ich bin großer Ubuntu-Linux-Fan: es liefert eine sinnvolle Standardkonfiguration, startet sehr schnell und ist aktuell. Der einzige Haken an der Geschichte ist, dass die ATI Treiber leider die XVMC-Schnittstelle nicht unterstützen, welche benötigt wird um HD-Inhalte in X11 auf der GPU zu rendern. Ob ATI dies jemals nachreichen wird, steht in den Sternen. Es gibt zwar Möglichkeiten den MPlayer hardwarebeschleunigt zum laufen zu bringen, aber das sieht mir derzeit sehr nach einem Gefrickel aus, worauf ich mich jetzt noch nicht einlassen möchte.
Also war sehr schnell klar, dass es eine Windows-Variante werden wird. Vorzugsweise Windows-7, wegen der SSD-TRIM-Funktionalität. Glücklicherweise habe ich eine Windows 7 Lizenz geschenkt bekommen, so dass hier kein weiterer Kostenpunkt entstanden ist. Fairerweise muss an dieser Stelle aber gesagt werden, dass ein kompletter HTPC (inkl. Windows 7, HDD und TV-Karte) unter 400 € eher unrealistisch ist.
16GB für’s Betriebsystem reicht doch locker … nicht?!
Windows 7 auf einer 16 GB Platte zu installieren ist gar nicht mal so einfach. Nach der Grundinstallation von Windows 7 x64 Professional hatte ich noch 1,42GB freien Speicherplatz. Ich hab verschiedene Maßnahmen durchgeführt:
Abschalten der Indexierung auf der Systemplatte- Systemwiederherstellungspunkte deaktiviert
- Auslagerungsdatei deaktiviert
- nahezu alle Windows Funktionen deinstalliert
- Suspend-To-Disk deaktiviert
- Große Windows-Ordner auf die andere HDD gelegt
Zwischenzeitlich hatte ich auch bis zu 5GB freien Speicher, aber nach einigen Windows-Updates war das auch wieder ausgeschöpft und irgendwann habe ich aufgegeben, so dass ich mir jetzt ein 32-Bit Image mit vorinstalliertem Service Pack 1 besorgt habe.
Windows-7 auf einer 16GB-Platte zu halten ist mühsam und kann ich niemandem Raten! Hier habe ich eindeutig an der falschen Stelle gespart!
XBMC, i luv u! <3
Eine Sache stand von vornherein fest: Als Media-Player Software kommt XBMC zum Einsatz! Hier bin ich echt schon etwas religiös, aber ich behaupte einfach (ohne es wirklich zu wissen), dass es nichts besseres gibt! Es ist natürlich auch etwas Gewohnheit, da ich XBMC bereits von der XBOX kenne und lieben gelernt habe. Mir ist bisher noch kein Format untergekommen, was der Player nicht abgespielt hat. Es hat eine einfache Bedienung und mit der Remote-App auf Android lässt sich das ganze dann noch einfach per Handy steuern. Dadurch lässt sich dann auch Musik abspielen ohne extra den TV einzuschalten.
Es gibt viele weitere sinnvolle Features. Ein Beispiel: Es lässt sich eine Verzögerung für der Audiospur einstellen, da bei manchen Filmen ja Audio- und Videospur nicht synchron sind. Das habe ich so in keinem anderen Player wiedergefunden!
Und das beste ist: es ist Open Source!

HTPC vs XBOX
Um zu überprüfen, ob sich der Aufwand gelohnt hat, habe ich ein paar Messungen gemacht. Vorweg sei gesagt, dass sich natürlich alleine wegen der HD-Fähigkeit das Upgrade gelohnt hat. Bei den Strommessungen ist zu beachten, dass diese nicht über einen längeren Zeitraum gemacht wurden, und damit nicht für bare Münze genommen werden sollten. Für Lautstärken-Messungen fehlt mir das entsprechende Equipment, so dass ich das nach meinem perönlichen Empfinden beschreibe.

iXy (xbox)
Die XBOX hat relativ veraltete Hardware, dafür kann sie noch erstaunlich viel wiedergeben (ab 720p ist meistens schluss). Zugriff auf die Daten bekommt man nur per FTP.
Hardware:
- Intel Mobile Celeron (Coppermine-Kern) mit 733 MHz
- 64 MB DDR-RAM mit 200 MHz
- Geforce 3-Kern „NV2A“
- 300GB 5400 RPM HDD (original sind nur 10GB)
Stromverbrauch:
- Standby: 1,7W
- Idle: 52W
- Last: 60W
Lautstärke:
Trotz tausch des Lüfters ist die XBOX sehr deutlich hörbar und hat zusätzlich zum Lüfterton einen deutlichen Summton. Zu dem waren die Festplatten damals noch deutlich lauter, so dass man jeden Zugriff auf die Festplatte wahrnimmt!
Bauform:
3,9kg leicht aber dafür ist Gehäuse klobig und hässlich.
hatepeze (htpc)
Der HTPC kommt mit allen gängigen Formaten (1080p Videos eingeschlossen) ohne Probleme klar, ausserdem kann ich neben XBMC weitere Programme im Hintergrund ausführen. Neben FTP kann ich beispielsweise über Windows-Shares Daten freigeben.
Hardware:
- AMD Fusion E-350 2x 1,6 GHz
- 4GB DDR3-RAM mit 1066 MHz
- AMD Radeon HD 6310
- 16 GB SSD und 2TB 7200 RPM HDD
Stromverbrauch:
- Standby: 2,1W, das liesse sich auf <1W reduzieren, wenn man auf die WAL (wake on lan) Funktion verzichtet.
- Idle: 33W
- Last: 40W (ich habe aber teilweise auch > 40W gesehen)
Lautstärke:
Bauform:
Ist mit 4,9KG deutlich schwerer, dafür aber ein praktisches und wirklich schönes Gehäuse.
Fazit
Mein HTPC steht jetzt seit 5 Tagen in meinem Wohnzimmer und ich möchte ihn nicht mehr missen. Neben den eigentlichen Player-Funktionen kann ich ihn als Download-Knecht verwenden oder einfach mal damit surfen. Früher musste ich verschiedene Formate an verschiedenen Playern ausgeben: Die XBOX funktionierte zwar für Musik; HD-Filme musste ich je nach Format aber auf PS3 (m2ts) oder TV (mkv) wiedergeben, und selbst dann gab es häufig Probleme. Der HTPC spielt alles ohne Zicken ab!
Nachtrag:
Bei der Datenerhebung habe ich vergessen die Startzeit zu messen, allerdings hat hier bei einem Kaltstart trotz der SSD im HTPC, eindeutig die XBOX die Nase vorn. Einen Standby-Modus gibt es bei der XBOX so nicht, daher würde hier wieder der HTPC gewinnen.
Und Thanks Richie, Bruty und Jia für die vielen Tipps zur Hardware; danke Moggebert für die Windows-7 Lizenz.
| Posted in hardware | 5 Comments »
neo4j + scala = fun
I had a great time at the LCGTUG Hackaton yesterday.
We played around with Neo4J and Scala. The result is pretty useless: a shortest-path calculator using the Dijsktra algorithm. But I think everyone learned something new about Neo4j, Scala or Dijsktra

Thank you LCGTUG for organizing the event.
Do It Yourself!
In the current project I am working on, we have about 50 external JAR-Dependencies. About one of ten bugs in our software is caused by one of these dependencies. They are not only hard to find, but hard to fix either. And even if you get it fixed within the source-code and create a patch, there is no guarantee that the fix will ever make it in the next version. Many open-source-projects are not very active or the maintainers are just too lazy to implement patches.
So, if you want to keep your dependencies update-able, it often results in ugly workarounds. I remember my time as a flash-developer, where we had to subclass nearly every component in the Flex-SDK and do really dirty hacks to get everything working as suspected.
The way of introducing a new dependency often looks like this: We need to implement a new feature, and the first thing we do is to research about stuff already done. During the research we maybe find a library which solves exactly that problem, and the initial effort to implement the feature using that library may not very high. But problems arise with time, when the software is being tested in real world situations, with real data and conditions. This may be months after the library has been introduced. Some of these problems become really time-consuming, and some of them cannot be solved in an acceptable amount of time.
I believe we should spend much more time before adding new external dependencies to our project. We should not only care about how fast we can implement our features with them, but also how good they are maintained, how easily patches can be committed and also if it wouldn’t be more efficient to just implement it by ourselves!
Scala and the Observer Pattern
I just started coding my first scala snippets. I played a bit around with lwjgl library to create some random graphic stuff.
The first problem I faced was to find a generic implementation to dispatch events such as render- or input-events from one place and handle them in another place. In OO-Languages this problem is usually solved using the observer pattern.
After studying some existing scala solutions, I did not find the one that fits my coding style. Since I come from the Flash-world, I would really appreciate a solution where observers are just callback-functions instead of implementations of traits. I also don’t like to have my observables cluttered with code for dispatching the events to the observers.
My Solution consists of a single generic class, the “Event”:
class Event[T] {
private var listeners: List[T] = List();
def apply(listener: T): Unit = register(listener);
def register(listener : T) : Unit = listeners ::= listener;
def unregisterAll() : Unit = listeners = List();
def fire(f : (T) => Unit) = {
for(l <- listeners) {
f(l)
}
}
}
All an observable has to do now is to create one field for each event-type they offer and to call fire() on them. The following example defines one event that gets fired as soon as the position of a DisplayObject changes. The callback-method takes the coordinates as paramters containing the new values.
class DisplayObject {
val onPositionChangeEvent = new Event[(Int, Int) => Unit];
private var x:Int = 0;
private var y:Int = 0;
def changePosition(x:Int, y:Int) = {
this.x = x;
this.y = y;
onPositionChangeEvent.fire(_(x, y));
}
}
Now we can register a callback-function directly at the onPositionChangeEvent-field. In the following example we print the new value to the console.
var observable = new DisplayObject(); observable.onPositionChangeEvent((x, y) => println(x + ":" + y)); observable.changePosition(10, 15);
One problem I faced is that I could not find any possibility to reliably unregister from an event. So I decided to implement an unsubscribeAll method.
observable.onPositionChangeEvent.unregisterAll();
If someone has an idea how this could be improved, please leave me a comment.

| Posted in HTML, Javascript, patterns | No Comments »