IOException.de

Icon

Ausgewählter Nerdkram von Informatikstudenten der Uni Ulm

Building node-webkit programs with Grunt

The days before Christmas were busy as usual: It’s not just that everyone is hunting gifts for family and friends. There’s also the annual German Youth Team Championship of Chess beginning on 25th December. Together with some friends I’m trying to broadcast this big event with more than 500 young participants to their families left at home, waiting for results.

In the last years, we used a simple mechanism to provide near to live results: The arbiters got a special email adress where they could send their tournament files to. On the server side there was a small node.js mail server (as mentioned in “Einfacher SMTP-Server zur Aufgabenverarbeitung” [german]) that took the proprietary file format, converted it and imported the results of already finished games. Although being a huge progress to the past where the results were imported once all games has been finished, this approach needed an arbiter constantly sending mails around.

Therefore I wanted to try another way: A program that keeps an eye on the tournament file and uploads it once it was changed and automatically triggers the import of new game results. Having just some days for its development it was necessary to stay with the same technology stack we used before for the mail server and tournament file converter: node.js.

As the tournament arbiters aren’t all familiar with command line tools, a graphical user interface was necessary. Strongloop published a blog post about node-webkit, which allows writing native apps in HTML and Javascript, some days before. This blog post is a good entry to the topic. Nettuts+ wrote a nice introduction recently too. Different from their approach I used the plugin for Grunt grunt-node-webkit-builder, which takes on the whole building process. Here’s my project’s setup:

/
├── dist
├── Gruntfile.js
├── package.json
└── src
    ├── index.html
    ├── package.json
    ├── js
    │   └── index.js
    └── css
        └── style.css

By using the grunt-node-webkit-builder it is necessary to keep the source of the building tool (all in the root directory) separate from the source code of the node-webkit program. Otherwise it may happen that the building tools (Grunt, you know?) get bundled in the node-webkit program as well which leads to high file sizes and slow execution times.

So it’s clear we specify in /package.json only the dependencies that are necessary for the building process:

{
  "name": "do-my-build",
  "version": "0.0.1",
  "description": "Using Grunt to build my little program",
  "author": "Falco Nogatz <fnogatz@gmail.com>",
  "private": true,
  "dependencies": {
    "grunt": "~0.4.2",
    "grunt-node-webkit-builder": "~0.1.14"
  }
}

We also have to create the Gruntfile.js:

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('src/package.json'),
    nodewebkit: {
      options: {
        build_dir: './dist',
        // specifiy what to build
        mac: false,
        win: true,
        linux32: false,
        linux64: true
      },
      src: './src/**/*'
    },
  });

  grunt.loadNpmTasks('grunt-node-webkit-builder');

  grunt.registerTask('default', ['nodewebkit']);
};

The real node-webkit program can be written now in the /src directory. As also mentioned in the tutorials linked above, the /src/package.json should be filled with some node-webkit related fields:

{
  "name": "my-program",
  ...
  "main": "index.html",
  "window": {
    "toolbar": false,
    "width": 800,
    "height": 600
  }
}

To build the node-webkit program for the architectures specified in /package.json you simply have to call the command:

grunt

This downloads the up-to-date binaries necessary for the specified architectures and builds an executable program. The result for Windows is simply a .exe file, for Linux an executable file. It contains all needed to run the program, so the user neither has to install node.js nor Chrome. The builds are located in /dist/releases.

By using this setup it was possible to automate the building process and develop the application within some days. The node-webkit runtime extends some native browser properties, for example it is possible to get the full path of a file selected by an <input type="file">. With that it was possible to create a graphical user interface to select tournament files and watch for their changes, which would trigger the update process.

Fünf Tage unterwegs: Rückblick zu MongoDBMunich und NodeDublin

It’s conference time! – Oder “was” vielmehr. Denn beide oben genannten Konferenzen liegen bereits mehrere Wochen zurück, mein defektes Notebook machte aber leider einen schnelleren Bericht unmöglich. Die Erinnerungen an die beiden Konferenzen sind aber nicht erblasst, sodass ich sie noch gerne teilen möchte.

Mitte Oktober. Für viele meiner Kommilitonen bedeutete dies vor allem eines: Beginn des neuen Wintersemesters. Und während die meisten dem wohl mit Blick auf die nun zu Ende gegangenen Semesterferien vorlesungsfreie Zeit etwas wehleidig entgegensahen, bedeutete es für mich nur eines: Eine ziemlich ereignisreiche Woche liegt vor mir. Bereits mehrere Monate zuvor hatte ich meine Teilnahme an der MongoDB Konferenz in München festgemacht. Recht kurzentschlossen entwickelte sich dann noch der Plan, von München direkt weiter nach Dublin zur Node.js-Konferenz NodeDublin zu fliegen, was dank des netten Angebots von Organisator Cian Ó Maidín, den Ticketpreis etwas studentenfreundlicher zu gestalten, und günstiger Flugpreise sogar realistisch schien. So begann für mich also das Semester ein wenig anders: Am Dienstag, den 16. Oktober ging es mit dem Zug nach München zur MongoDB Konferenz, von dort am nächsten Tag mit Aer Lingus in die irische Hauptstadt, wo Donnerstag und Freitag NodeDublin anstand. Samstag in aller Früh ging dann auch schon der Rückflug nach Frankfurt, da ich tagsüber noch eine (nein, diesmal nicht Technik-) Tagung der Deutschen Schachjugend in Heidelberg hatte. Klingt doch nach einem tollen Plan, oder?

16. Oktober: MongoDB Munich

Leider nicht mehr online verfügbar: Der Sessionplan von MongoDB Munich

Leider ist der Sessionplan von MongoDB Munich nicht mehr online, ich habe ihn aber mal eingescannt. Die Konferenz fand im Hilton Hotel in der Nähe vom Tucherpark statt. Von außen eine sehr gute Location, von innen war ich aber etwas enttäuscht. Keiner der sogenannten Ballsäle hatte auch nur ein einziges Fenster, sodass einem im Laufe des Tages irgendwann die Decke auf den Kopf fiel – auch wenn die Sessions von Coffee Breaks und Mittagsbuffets im lichtdurchfluteten Hotelfoyer unterbrochen waren.
Die Teilnehmer kamen aus allen Bereichen: Entwickler und Systemadministratoren, MongoDB-Anfänger und -Kenner. Als etwas erfahrenerer MongoDB-Nutzer war ich anfangs etwas von den Low-Level-Vorträgen enttäuscht. Zugegeben: Die Session “Building Your First App with MongoDB” hielt genau was sie versprach und war eben nur eine oberflächliche Einführung. Auch von Marc Schwerings “Schema Design” hatte ich mir mehr neue Erkenntnisse erhofft. Die gab es dafür am Abend im persönlichen Gespräch mit ihm, wo er ein bisschen aus dem Leben eines jungen Solution Architect bei 10gen, dem Unternehmen hinter MongoDB, plauderte.

Mit zunehmender Dauer wurde es dann aber doch inhaltlich spannender. Bislang benötigte ich die Replication-Features von MongoDB noch nie, dafür sind die Daten, mit denen ich arbeite (noch!) zu gering. Und selbst wenn ich mir unsicher bin, ob Replication damit für mich in absehbarer Zeit überhaupt ein Thema wird, waren schon allein die theoretischen Probleme, die es im Falle eines Mehr-Rechner-Systems zu lösen gibt, sehr interessant. Und ein Punkt, wo ich wieder merkte, dass das Studium doch etwas bringt, hörte ich in dieser Session doch viele Begriffe aus den uulm Vorlesungen Algorithmen und Datenstrukturen, Rechnernetze, uvm.
Während ich bis dahin im BallSaal B war, der meist theoretische Sessions beheimatete, wechselte ich vor dem Mittag zu “Pizza Quattro Shardoni with comSysto” in den BallSall A, wo die praktische Anwendung des NoSQL-Vertreters im Vordergrund stand. Für die Motivation, warum man das ganze eigentlich macht, war das sicher nicht verkehrt :)

Vor Abflug in München zum letzten Mal Sonne tanken

Nach dem Mittagessen und dem zufälligen Treffen der Ulmer Kollegen von Transporeon ging es mit “Indexing und Query Optimization” weiter, gefolgt von “Map/Confused”. Ich hatte im Sommersemester meine Seminararbeit unter dem Titel “Google’s MapReduce Programming Paradigm as Basis for NoSQL Database Views” verfasst und war gespannt, wie MongoDB diesen Ansatz umsetzt, wo Abfragemöglichkeiten wie das Aggregation Framework in der Community ja viel verbreiteter sind. Der Vortrag war allerdings recht enttäuschend: Kaum Fachwissen und als Beispiel, warum MapReduce schlecht sei, wurde eine Abfrage gemessen, die man schlichtweg nie mit M/R (und auch manch anderem alternativen Vorschlag) lösen würde.
Den Abschluss bildeten für mich das wirklich spannende und unterhaltsame “Scaling Tips & Tricks” und anschließende “Build your own Foursquare with MongoDB’s Spatial Features & the Cloud”. Nach über acht Stunden im Hilton war die Konferenz dann gegen 17.15 Uhr in den gemütlicheren Teil über und ich konnte mich bei kostenfreiem Bier mit einigen netten 10gen Mitarbeitern unterhalten.

18.-19. Oktober: NodeDublin

Der nächste Tag begann hektisch: Ich hatte bei einer Freundin in München übernachtet und reichlich Zeit eingeplant, um vom Arabellapark mit U- und S-Bahn zum Flughafen der bayerischen Landeshauptstadt zu kommen. Doch an diesem Mittwoch kam irgendwie alles zusammen: Die erste S-Bahn zum Airport fiel aus und die nächste hatte 20 Minuten Verspätung – und fuhr “aus betrieblichen Gründen” nicht mal bis zum Flughafen, was man den Fahrgästen dann in irgendeinem Nest vorher (man konnte schon die Flieger ganz tief landen sehen!) sagte und sie rauswarf. So kam ich 75 Minuten später als geplant am Flughafen an, musste mich an der Schlange an Checkin und Sicherheitskontrolle vorbeimogeln und kam gerade rechtzeitig zum Boarding. Dafür sollte es dann aber auch für die nächsten Tage erstmal mit dem Stress vorbei sein.

In Dublin angekommen die erste positive Überraschung. Der Linienbus kostete nur ein bisschen über zwei Euro, hatte aber freies WLAN on board. Davon kann sich München mal eine Scheibe abschneiden, das mir für die Tortur wenige Stunden zuvor mal eben einen Zehner abgeknöpft hatte. Dank des Tipps von Timo war ich sehr günstig und zentral in Dublin untergebracht: Bei 18€ pro Nacht bei einem Fünfbettzimmer für einen alleine in einem ordentlichen Hostel kann man nicht meckern! Dank der Stunde Zeitverschiebung hatte ich noch den ganzen Tag Zeit, Dublin zu Fuß zu erkunden und bei für Irland gute Wetterverhältnisse einen ausgedehnten Spaziergang zum Konferenzort von NodeDublin zu nutzen: Stattfinden sollte das Event, zu dem sich zahlreiche node.js-Größen aus der ganzen Welt angekündigt hatten, die nächsten zwei Tage in einer riesigen Guinness-Brauerei im Herzen der Stadt.

O’Connell Street in Dublins Zentrum – in der Parallelstraße war mein Hostel

Für irische Verhältnisse gutes Wetter

Auch architektonisch macht Dublin so einiges her

Ort des Geschehens: das Guinness Store House in Dublin

Leckeres Frühstücksbuffet (NK)

Guinness Store House (NK)

Die Konferenz begann am Donnerstagmorgen dann – natürlich – mit der Registrierung und anschließendem, ausgesprochen leckerem Frühstücksbuffet. Das Guinness Store House, in dem die Konferenz eine Etage für sich einnahm und das sonst durchgehend von Besuchern durchströmt war, bot ein exzellentes Ambiente: Moderne Konstruktion, lichtdurchflutet, im Konferenzsaal große runde Tische für jeweils zehn Personen. An jedem einzelnen waren, als es pünktlich um 9.00 Uhr mit den Keynotes von Mikeal Rogers und Isaac Schlueter losging, jeweils zwei Plätze für Speaker vorgesehen, was das Motto der nächsten Tage unterstreichen sollte: Eine Konferenz von Node-Usern für Node-User, keinen extra Bereich für die Speaker. Und so waren keine zwei Stunden vergangen, als plötzlich Isaacs (der Mann hinter npm und heute quasi “Chefentwickler” von Node) sich neben mich setzte und wir uns locker unterhalten konnten. Und auch die nächsten Tage boten sich immer wieder zahlreiche Gelegenheiten, mit bekannten node.js-Größen ebenso zu reden wie mit enthusiastischen Entwicklern aus aller Welt.

Wo ich gerade bei Enthusiasmus bin: Der war enorm, sowohl wie er bei den einzelnen Sessions vorgetragen wurden, aber auch in den Gesprächen der Teilnehmer vorgelebt wurde. Hätte man eine Umfrage gemacht, so wären wahrscheinlich alle Kernbereiche der Informatik abgedeckt gewesen (“Machine Learning using Node.js”, wie geil ist das denn bitte?!). Auf der anderen Seite neigt so eine Konferenz wahrscheinlich per Definition zur Selbstbeweihräucherung. Kein Talk, in dem nicht – manchmal ja doch etwas unreflektiert – herausgestellt werden musste, wie awesome Node doch sei ist. Bei all den “Wir können die Zukunft gestalten!”-Talks fehlte mir dann irgendwann schon die Ernsthaftigkeit und wirklich neue Erkenntnisse, ich hätte mir in der Summe mehr technische Beiträge gewünscht. Felix Geisendörfers “Writing fast streaming binary parsers in node.js” war fantastisch, vom anderen deutschen Speaker Jan Lehnardt (“Community and Open Source, and the Node Community”) hätte ich lieber etwas zu CouchDB gehört als einen weiteren Talk im Keynote-Stile.

Ein Blick ins Plenum (NK)

Keynote von Isaac Schlueter (NK)

Alles in allem war für mich bei der Vielzahl an Talks und guten, bekannten Speakern aus der Szene am Ende zu wenig dabei, was ich an praktischen Tipps für meine Arbeit mit Node nun mitnehmen konnte. Das machten aber die vielen, vielen Gespräche mit anderen Entwicklern wieder wett. Die Zahl deutscher Teilnehmer war überschaubar, sehr sympathisch fand ich die vielen Iren, die die Konferenz organisierten oder einfach teilnahmen. Die Studentenquote hätte vermutlich auch höher sein können, die uulm-Kollegen und Mitblogger Benjamin und Michi konnten leider auch nicht mitkommen.

Am Freitag Abend stand dann die After Party in einem typischen Irish Pub mit leider wenig typisch irischer, sondern vielmehr gewöhnungsbedürftiger Technomusik an. Nochmal eine gute Gelegenheit, neue Bekanntschaften zu vertiefen, mal Jan Lehnardt nach Studentenpreisen für die JSConf EU zu fragen (wird es auch in Zukunft nicht geben) und ein paar Bilder mit Daniel Shaw mit Pferdekopf zu schießen. Da mein Flug bereits am Samstagmorgen um 6.30 Uhr gehen sollte, hatte ich geplant, die letzte Nacht in Dublin durch zu machen und gar kein Zimmer mehr. So bin ich also nach der Party um 3 Uhr in den AirCoach gestiegen, zum Flughafen gefahren, hab mich über McDonald’s aufgeregt und noch ein kleines Nickerchen machen können, ehe ich ins sonnige Frankfurt zurückflog.

Alles in allem war es eine äußerst interessante Woche. Nachdem wenige Tage später mein Notebook kaputtging, begann ich nochmal darüber nachzudenken, ob es das Geld, was ich für die beiden Konferenztickets, Flug und Hostel in dieser Woche ausgegeben hatte, tatsächlich wert war… – und ja, absolut! Der ganze Tripp war an sich schon unglaublich aufregend, es hat Spaß gemacht, diese vielen enthusiastischen Leute kennen zu lernen; manche, die man bislang nur von Twitter kannte. Und dass eine solche Unternehmung als Student durchaus erschwinglich ist, werde ich auch mal in einem kommenden Beitrag hier exemplarisch vorrechnen. Liebe Kommilitonen: Nutzt die Chance, jetzt habt Ihr wahrscheinlich noch eher die Zeit dafür, als später im Berufsleben.

Die mit (NK) gezeichneten Bilder sind von Nico Kaiser (CC BY 2.0), den ich in Dublin kennengelernt habe. Weitere Impressionen von NodeDublin findet Ihr in seinem Flickr-Album.

Wie wird man guter Programmierer? – Metaphorisch formuliert.

Eben noch von @maxogden rumgesponnen, wenige Minuten später online: realtimecats.com

ChanCE Conflict: How to access broken Intel SSDs

After almost three years of very heavy use my old Intel X25-M G2 (SSDSA2M160G2GC) got broken four weeks ago. Since my laptop’s fan was very messy too, the SSD’s dead was merely a matter of time. Despite of this fact I did not make any backup for years (yeah, I know…), so the failure of the one and only harddrive in my laptop was not only bad as I couldn’t use the notebook any longer, but also by losing all my personal data of the last two years. While waiting for the surrogate computer I used the time to try to get the SSD running again, just to save everything that can be rescued.

When I tried to boot from my good old X25-M the harddrive was indeed recognized in the BIOS but in 95 percent of the attempts it was rejected as a not bootable device. Plugged in to another computer via a SATA-USB-connector the partition table was not recognized at all and the harddrive was listed with an overall capacity of 8 MB instead of its 160 GB. Under Ubuntu it was annotated with a “ChanCE Conflict”. The same error message was displayed in the notebook’s BIOS in the SSD’s Serial Number field. Unfortunately Google does not know much about this strange “ChanCE Conflict”: There is an unanswered thread in the Intel support forum and a great many people in other forums having exactly the same problem: their Intel SSDs are recognized with either only 8 MB capacity or 480 TB, but not accessable at all.

My first try was to update the SSD’s firmware. You can download a newer version from the Intel website. Simply burn the 5 MB ISO on a CD and boot from it. It recognizes your Intel SSD and will update its firmware even if you could not access it before. But be warned: I could boot my Ubuntu from the flashed SSD exactly one time (and not successfully at all as some critical files are broken)! After another reboot the ChanCE Conflict will appear again and the firmware update can not be run again as it’s up-to-date now.

But there’s another trick: Just set a HDD password in the BIOS. After a reboot you will be asked for the SSD password. Enter it and shutdown the PC immediately. In my case I was able to access now 90 percent of my files on another PC by using a SATA-USB-connector. It seems that one of the separate flash chips got broken so only some very frequent changed files could not be restored. Make sure to use some tool like ddrescue which saves the rescue process in a logfile as one has to repeat the mentioned steps of setting a HDD password multiple times.

datalove @ Open Data Barcamp Friedrichshafen

Am gestrigen Freitag machte sich ein kleiner Teil der datalove-Hochschulgruppe auf den Weg nach Friedrichshafen, um am 2. Open Data Barcamp der Bodenseeregion teilzunehmen. Leider gab es noch kurzfristig einige Absagen, sodass für Stefan, Timo und mich letztlich ein Drei-Mann-BaWü-Ticket reichte. Leider musste Veranstalter Prof. Dr. Jörn von Lucke auch aus anderen Regionen kurzfristige Absagen vermelden, sodass die Gruppe nur 15 Teilnehmer umfasste – die dafür aber umso intensiver das Thema Open Data anging.

Bodensee und Alpenblick

Am Friedrichshafener Stadtbahnhof zehn Minuten zum Umsteigen - also schnell raus zum Bodensee!

Wo "Container" drauf steht, ist auch Container drin. Direkt dahinter die nächste Überraschung: Ein kleiner Hangar.


Wir wurden für die Anreise am Mittag bereits in der Friedrichshafener Innenstadt mit einem tollen Alpenblick belohnt. Der Nebel hat sich auch noch mit der Zeit gelichtet. Leider haben wir erst erfahren, dass die ContainerUni, in der das Barcamp stattfand, auch eine Dachterrasse hat, als es schon dunkel war. Apropos ContainerUni: Wir waren alle begeistert, was man aus einem Provisorium machen kann. Anfangs noch etwas verwirrt (Baucontainer und ein “Hangar”?!), war das dann doch alles sehr einladend und erfrischend. Das Konzept überzeugt – und die Räume wirken sehr viel freundlicher als so ziemlich jeder fensterlose Hörsaal der Uni Ulm.

Ganz im Barcampstile wurden nach Begrüßungsworten und einer Vorstellungsrunde Themen gesammelt. Trotz der überschaubaren Runde fanden sich insgesamt acht Sessions, von denen die vier meistgewünschten dann ausgewählt wurden:

Den Anfang machte Jörn von Lucke mit anregenden Beispielen für Open Data und Partizipation aus der Bodenseeregion und ganz Baden-Württemberg. Besonders interessant war dabei sicher auch, dass die Open Data Initiative aus Friedrichshafen auch bis zu den österreichischen Nachbarn übergegriffen hat – und dort zum Teil schneller umgesetzt wird als im deutschen Vorbild. In dieser, wie aber auch den folgenden Sessions, wurde jedoch auch deutlich, dass die Offenlegung behördlicher und anderer Daten zwar im Interesse der Bürger, jedoch nicht immer in dem der Politiker ist.

Der zweite Block zu OpenSpending brachte dann noch eine weitere Erkenntnis:


Die reine Bereitstellung der Daten reicht nicht aus. Selbst wenn etwa Haushaltsdaten maschinenlesbar sind, muss dies noch nicht bedeuteten, dass sie auch leicht zu verarbeiten wären. Dieses Problem haben wir etwa auch in Ulm: Zwar liegen uns die Haushaltsdaten der Stadt vor, jedoch fehlen den Programmierern die betriebswirtschaftlichen Kenntnisse, um diese zu visualisieren, und den Verwaltungsspezialisten die Programmierkenntnisse. Spontan wurde die anschließende Pause genutzt, um die Daten mal gemeinsam, aus beiden Perspektiven, zu betrachten. Ziel wird es sein, den Austausch auch in Zukunft auszubauen und fachliche Spezialisten, die wissen, wie die Daten zu interpretieren sind, mit den Programmierern an einen Tisch zu bringen.

Dass es noch besser wäre, wenn die Daten nicht nur maschinenlesbar und unter offener Lizenz veröffentlicht, sondern gleich ansprechend visuell aufbereitet würden, unterstrich Julia Stoffregen am Beispiel von Kenia: In Sachen Open Government hat dieses Land den meisten eruopäischen Ländern einiges voraus und Open Data als wichtigen Teil der politischen Partizipation, aber auch als Wirtschaftsmotor entdeckt.


Wenn A und B sich in 15 Minuten treffen wollen - wo könnten sie das dank ÖPNV in Ulm tun?

Zum Abschluss stellte Stefan unsere Aktivitäten in Ulm vor und widmete sich dabei insbesondere seinem Lieblingsthema: dem Ulmer Nahverkehr. Ulm hat Friedrichshafen dabei einiges voraus: was die Offenheit der Stadtwerke in Sachen Fahrplandaten angeht, aber auch, wie gut die Stadt generell per ÖPNV erschlossen ist. Money quote: “Nachtbus in Friedrichshafen heißt, dass ausnahmsweise auch von 20 bis 22 Uhr etwas fährt.” (Oder so.)

Gegen 19 Uhr machten wir Ulmer uns dann wieder auf den Weg Richtung Bahnhof. Neben Einblicken in andere Regionen und Länder und etwas Buchhaltung haben wir auch noch mitgenommen, dass wir uns so langsam an die Planung einer Neuauflage des OpenCityCamps in unserer Donaustadt machen sollten. Wäre doch schön, wenn die Barcamps in Friedrichshafen und Ulm im Halbesjahresabstand zu festen größen im Open Data Terminkalender würden!

Using Prolog as an incremental CHR constraint store

The work with Constraint Handling Rules (CHR) has many advantages. One of them is the so called online property: It’s possible to execute your CHR program by giving some constraints in a first query, wait for the result (or not!) and add further constraints later at any time. So a CHR program normally does not terminate but rather halts if it can’t execute any rule with the constraints currently in the constraint store. And so it simply waits for new constraints. That’s why it is called incremental constraint store.

Working with Prolog as the host language, you will detect that it doesn’t work in this way: Once you entered your query of maybe multiple constraints, Prolog plays the constraint handler and applies your rules until it’s no longer possible. And stop. While the resulting constraint store is printed, you neither can add any new constraint nor manipulate this constraint store in any way. So the big advantage of the online property, which is recited mechanically in every CHR lesson, gets lost.

I’ve written Jon Sneyers, one of the developers of the K.U.Leuven CHR System used by SWI-Prolog, if he knows a way to use Prolog as an incremental CHR constraint store. And the solution is as simple as short: Because Prolog uses backtracking, it will turn to the point before the query was executed once all rules have been applied. That’s why it can not be used as an incremental constraint store without a simple trick: By writing an own prompt which takes the queries, we can prevent Prolog to backtrack. So the main idea is the following:

main :- prompt.

prompt :- write('[CHRstore] ?- '),
                read(Query),
                call(Query),
                prompt.

This will result in a loop which produces a self-defined prompt to get new queries without forgetting the old ones. But this very basic example has some disadvantages: First you can’t stop the loop. And second there is no way to show the current constraint store once you have added a new query. So we will modify the Prolog rules a little bit:

main :- prompt.

prompt :- write('[CHRstore] ?- '),
                read(Query),
                callq(Query).

callq(show_constraints) :- writeln('[CHRstore] Stored constraints:'),
                get_current_module(Mod),
                chr_show_store(Mod),
                prompt.
callq(stop_store) :- writeln('[CHRstore] Stopped.').
callq(Query) :- call(Query),
                prompt.

By adding a callq predicate we can provide two special queries: show_constraints and stop_store. While the latter one will break our prompt loop, the show_constraints calls the built-in chr_show_store/1 predicate to print the constraint store of the module Mod. To get the current module you can either add a fact at the top, use some built-in predicates or something else.

I’ve wrapped up these snippets in a little Prolog module, which can additionally handle multiple modules too.

XML-Dokumente per XSD 1.1 mit Apache Xerces-J validieren

Seit April diesen Jahres ist XML Schema in der Version 1.1 offizieller Standard des W3C. Nachdem die Version 1.0 noch aus dem Jahre 2004 datiert, wurde die letzten Jahre eifrig diskutiert, ehe der neue Standard nun endlich in Stein gemeißelt wurde.

Dumm nur: Wenngleich seit 2004 über die Änderungen von XSD 1.1 diskutiert wurde, gibt es auch jetzt, nach Veröffentlichung der W3C Recommendation, nur sehr wenige Tools, die die neuen Schema-Elemente wie <assert> und <alternative> unterstützen, die XML Schema sehr viel mächtiger werden lassen. Da ich für ein Projekt gerade an einem ziemlich umfangreichen Schema arbeite, wollte ich die Vorteile der neuen Version, insbesondere die beiden eben erwähnten Möglichkeiten der Assertions und Typalternativen, natürlich gleich nutzen. Und benötigte dementsprechend einen XML-Validator, der XSD 1.1 beherrscht.

Nach meiner Recherche gibt es aktuell nur zwei Programme, für die das zutrifft: SAXON (Enterprise Edition) und Apache Xerces. Die aktuellste Version vom <oXygen/> XML Developer kann laut Foren wohl auch mit XSD 1.1 umgehen, ist aber auch nicht ganz billig.
So entschied ich mich für Apache Xerces2 Java, eine Open-Source Implementierung in Java. Zwar setzt sie nur den XSD 1.1 Working Draft von 2009 um, bisher konnte ich aber keinen Verhaltensunterschied zum nun offiziellen Standard feststellen.

Die Installation ist zwar auf deren Seite beschrieben, ich fand sie allerdings nicht sehr intuitiv, daher hier ein paar Bemerkungen: Unter xerces.apache.org kann im unteren Abschnitt “Binary Distributions” die aktuelle Version von Xerces2 Java (XML Schema 1.1) (Beta) heruntergeladen werden. Darin findet sich mit /samples/jaxp/SourceValidator.java schon ein Kommandozeilenprogramm, über das das fröhliche Validieren beginnen könnte:

java jaxp.SourceValidator -xsd11 -a schema.xsd -i file.xml

Könnte – denn am Anfang wird vermutlich eine Fehlermeldung wie Parse error occurred - No SchemaFactory that implements the schema language specified by: http://www.w3.org/XML/XMLSchema/v1.1 could be loaded den erfolglosen Versuch quittieren. Klar, irgendwie müssen die Xerces-Daten ja noch ihre Verwendung finden. Die Xerces-FAQ schreiben nur wenig hilfreich:

Use the Endorsed Standards Override Mechanism. Place the xalan.jar, serializer.jar, xercesImpl.jar and xml-apis.jar in the\lib\endorsed directory, whereis where the runtime software is installed.

Okay, was ist also zu tun? – Zu allererst benötigen wir den Java-Pfad. Unter Ubuntu ist das bei mir /usr/lib/jvm/{java-version}/jre, bei mehreren Java-Installationen findet man mittels java -version die richtige. Im Unterordner lib können wir nun den Ordner endorsed anlegen, wenn er noch nicht existiert. Dort packen wir die Dateien xml-apis.jar, xercesImpl.jar, icu4j.jar, cupv10k-runtime.jar, org.eclipse.wst.xml.xpath2.processor_1.1.0.jar aus dem Xerces Download hinein. Jetzt fällt auf, wer am Anfang fälschlicherweise doch die “Source Distribution” heruntergeladen hat, da sind die nämlich nicht dabei.

Sind die Dateien im endorsed Ordner hinterlegt, greift Java direkt darauf zurück. Der obige Aufruf des SourceValidators.java sollte nun also keinen Fehler mehr werfen und die XML-Datei wie gewünscht nach dem neuen XSD 1.1 Standard validieren.

Übrigens: Die im endorsed Ordner hinterlegten Jars können natürlich wieder zu Problemen mit anderen Programmen führen. Ich habe mir daher einfach in der ~/.bash_aliases zwei Aliases angelegt:

alias endorsed-off="sudo mv /usr/lib/jvm/java-6-openjdk-amd64/jre/lib/endorsed/ /usr/lib/jvm/java-6-openjdk-amd64/jre/lib/old_endorsed"
alias endorsed-on="sudo mv /usr/lib/jvm/java-6-openjdk-amd64/jre/lib/old_endorsed/ /usr/lib/jvm/java-6-openjdk-amd64/jre/lib/endorsed"

Gitlab: Freie GitHub-Alternative für geschlossene Projekte

Wer einmal mit einer Versionsverwaltung wie Git oder Subversion gearbeitet hat, möchte es für die eigene Arbeit nicht mehr missen: Nie mehr verzweifeln, weil der Texteditor nur die letzten X Änderungen über die allseits beliebte Tastenkombination Strg+Z zurücknehmen lässt. Kein leidiges Abgleichen von Dateien per Hand, wenn mehrere Leute am gleichen Projekt arbeiten.
Für die meisten dieser Versionskontrollsysteme ist ein zentraler Server, auf dem die Datenstände und Versionen allen Projektmitgliedern bereitgestellt werden können, zwingend erforderlich oder zumindest sehr empfehlenswert. In der Open-Source-Welt hat sich hierfür GitHub etabliert, was das kostenfreie Git-Hosting für öffentliche Projekte erlaubt. Wer – wie wir für unser Softwareprojekt (Sopra) im Rahmen des Informatikstudiums – im Team an einem privaten Repository arbeiten möchte, muss bei GitHub schon etwas Geld in die Hand nehmen: Zwar wäre es uns die sieben Dollar im Monat wert gewesen, da ich aber die Vorteile von Git auch für ein paar andere eigene (nicht öffentliche) Projekte verwenden wollte und einen vServer quasi brachliegen hatte, sah ich mich nach selbstgehosteten Alternativen um – und stieß auf Gitlab.

Gleich vorweg: Wenn man Git alleine nutzt, braucht man natürlich überhaupt keinen Server. Und wem grafische Oberfläche ohnehin ein Fremdwort ist, der kann seinen Server sicher auch nur als reinen Git-Server betreiben. Für unser Team waren in der Programmentwicklung jedoch die Features, die auch GitHub bietet, sehr wichtig: Wir wollten Issues online erfassen, Commits direkt im Code kommentieren. Ja, vielleicht sogar MergeRequests direkt über die Web-Oberfläche abarbeiten. All dies wurde durch Gitlab ermöglicht, wenn auch zum Teil erst nach ein paar Versionssprüngen.

Installation und Updates

Versionssprünge? – Ja, Gitlab steckt so gesehen noch in den Kinderschuhen. Oder anders formuliert: Es wird stetig verbessert. Wer sich ein wenig mit Ruby auskennt oder einfach ein paar neue Ideen einbringen will, kann ja mal bei Gitlab auf GitHub vorbeischauen.
Wir fingen im März unter Nutzung der Version 2.2 an, mit Gitlab zu arbeiten. Mittlerweile läuft auf meinem Server die 2.6er-Version, in den kommenden Tagen müsste das Update auf 2.7 veröffentlicht werden. Anfangs weigerte ich mich, das System zu aktualisieren, um das Sopra nicht unnötig zu gefährden. Es zeigte sich jedoch schnell, dass jedes einzelne Update sehr nützliche Features mit sich brachte – so kamen seit Beginn unserer Arbeit die Möglichkeit der Milestones, Taggen von Issues und das Annehmen von MergeRequests über die Web-Oberfläche dazu.

Die Installation auf dem eigenen Server geht relativ einfach von der Hand. Eine Schritt-für-Schritt-Anleitung dazu gibt es im Gitlab-Wiki, die ich eigentlich nur abarbeiten musste. Offiziell unterstützt wird nur Ubuntu, es finden sich im Internet aber mittlerweile genügend Hilfen, wie man Gitlab auch auf CentOS- oder anderen Servern zum Laufen bekommt. Einmal installiert gehen Updates so einfach wie nur möglich von der Hand: Ein einfaches git pull und rake db:migrate reichen in aller Regel aus, um das System auf den neuesten Stand zu bringen.

Features

Wie oben schon geschrieben: Im Prinzip bringt Gitlab alles mit, was man auch von GitHub kennt. Das große Vorbild schwingt in allen Diskussionen um neue Features mit. So birgt die Oberfläche von Gitlab erstmal auch kaum Überraschungen.
Da ich noch nie auf GitHub in einem Team gearbeitet habe, kann ich das leider nicht vergleichen. In Gitlab gibt es eine ganze Reihe an verschiedenen Rollen, vom “Guest” bis “Master”. Die Rollenverteilung auch im Team umzusetzen, erwies sich bereits nach wenigen Tagen gemeinsamer Arbeit am Sopra als sehr nützlich: Durch die Unterscheidung zwischen “Developer” und “Master” konnten nur noch zwei Mitglieder in unseren Master-Branch pushen und waren dementsprechend für das Mergen und Schließen der Issues hauptverantwortlich.

Letztlich nutzten wir im Team mit Ausnahme der sogenannten “Wall” alle Mittel, die uns Gitlab an die Hand gab. Am anschaulichsten wird das vielleicht, wenn man betrachtet, wie sich unser Workflow seit Benutzung von Gitlab geändert hat:

  • Gerade am Anfang war die intensive Arbeit mit Git für uns alle noch ziemlich neu. Das Wiki eignet sich sehr gut, um auch gemeinsam die wichtigsten Kommandos zusammenzufassen. Aber etwa auch um nochmal die Programmierkonventionen zu benennen.
  • Code wird nicht mehr per Skype oder Google Hangout unter Nutzung der Bildschirmübertragung diskutiert, sondern einfach über die Weboberfläche – und zwar gerne auch direkt mit Kommentaren im Code oder Commit.
  • Issues und Arbeitsaufträge werden nicht mehr über Rundmails verteilt, sondern einfach als neue Einträge unter Issues hinterlegt.
  • “Bei mir trat gerade ein Fehler in Deinem Modul auf.” – “Schick mir mal die Fehlermeldung per Skype”. Solche Dialoge gibt es nicht mehr. Wir nutzten Skype zwar natürlich weiter intensiv zur Teamdiskussion, lange Fehlermeldungen haben im Chat aber nichts zu suchen. Und wanderten somit in die Snippets, wo man ihnen eine Expire-Zeit zuweisen kann.
  • Jegliche Dokumente wie die Benutzerdokumentation werden auch im Gitlab hinterlegt. Und nicht wie zuvor über Dropbox verteilt.
  • Unverändert blieb jedoch die Nutzung von GoogleDocs. Für Dokumente, die sich häufig verändern, wie etwa das Projekttagebuch, ist das doch noch einfacher, da Gitlab im Gegensatz zu GitHub (noch?) nicht das Ändern von Dateien via Browser unterstützt.

Grundsätzlich gab es also nichts, was uns noch gefehlt hätte. Nervig waren hin und wieder lediglich die kleinen Aussetzer, auf die ich im nächsten Abschnitt mal kurz eingehen werde.

Limits

Auch wenn sich Gitlab und GitHub nicht nur optisch sehr ähneln, verfolgen beide Systeme eigentlich unterschiedliche Ziele: Gitlab beschränkt sich komplett auf das Hosting von privaten Repositories. Es ist also nicht möglich, Gitlab als selbst gehosteten Ersatz für Github zu nutzen, und seine Open-Source-Projekte damit zu verwalten. Klar, prinzipiell geht das natürlich auch, aber dann kann eben niemand den Code sehen. Im Gegensatz zu GitHub bietet der Klon nämlich keine Möglichkeit, auf Projekte ohne Registrierung zuzugreifen. Und neue Benutzer anlegen kann nur der Admin. Auch wenn in sehr regelmäßigen Abständen von etwa 2 Wochen ein neuer Issue an die Entwickler gerichtet wird, dies doch umzustellen, bleiben diese ihrer Linie treu und grenzen sich damit ganz klar von Github ab. Und das auch ganz explizit mit der Aussage, dass Open-Source-Projekte eben am besten zentral auf GitHub gehostet werden.

Das Bearbeiten von MergeRequests direkt über die Weboberfläche ist zwar sehr komfortabel, sollte naturgemäß aber nur bei einfachen Änderungen benutzt werden. Ohnehin prüft Gitlab, bevor es die Möglichkeit anbietet, ob es zu irgendwelchen Merge-Konflikten kommt. Doch auch wenn dem nicht so ist, habe ich Abstand davon genommen, umfangreiche Änderungen über diesen Weg zu übernehmen. Letztlich schien mir der traditionelle Weg über git merge und ggf. git mergetool doch immer noch am sichersten.

Etwas Schluckauf kann man Gitlab im Moment auch noch durch den intensiven Gebrauch von Umlauten bereiten: Commit-Messages, die Umlaute beinhalten, können mitunter dafür sorgen, dass ein ganzer Dateibaum in der Weboberfläche nicht mehr verfügbar ist. Umlaute in Dateinamen sorgen dafür, dass die ansonsten sehr hilfreiche Funktion, um ein komplettes Repository als *.tar.gz herunterzuladen, plötzlich nicht mehr funktioniert. Schade ist, dass das System in diesen Fällen keine ordentliche Fehlerseite liefert, sondern schlicht mit 404 quittiert. Und man dann händisch versuchen muss, die Sachen in der Datenbank zu korrigieren.
Generell hat die Zahl der Fehler mit jedem Update aber gut abgenommen, sodass man sich einfach auf die Vermeidung von Umlauten einlassen sollte und ein sehr gutes und stabiles System bekommt.

Screenshots

Eine Demo gibt es ebenfalls auf den Seiten von Gitlab.

Einfacher SMTP-Server zur Aufgabenverarbeitung

Häufig ärgere ich mich über Webanwendungen, die ihren Nutzern Mails schicken, wenn irgendein Ereignis eingetreten ist oder eine Aktion des Users benötigt wird, eine einfache Antwort auf die Mail aber nicht möglich ist. Ein typisches Szenario ist etwa das Bestätigen der Mailadresse, wenn man sich bei einem neuen Dienst registriert: Man gibt seine Mailadresse in ein Online-Formular ein, bekommt eine Aktivierungsmail zugeschickt und muss darin einen Link anklicken, der wiederum zum Webdienst führt und meine Mailadresse bestätigt. Wäre es nicht einfacher, die Mail so wie sie ist an den Absender zurückzuschicken um sie zu bestätigen?

Dies sei nur als ein Beispiel genannt. Beim nicht mehr gepflegten node.js-Modul smtpevent sind auch noch weitere Szenarien aufgeführt: Viele Mailinglists bieten etwa die Möglichkeit, sich über eine Mail an unsubscribe@mailinglist.de davon abzumelden. Bei Github kann man auf einen Issue direkt antworten, indem man die Benachrichtigungsmail einfach beantwortet. Weitere Szenarien sind leicht vorstellbar: Warum soll ich von unterwegs mit dem Handy eine Weboberfläche bemühen, um remote meine Heizung zu steuern, wenn ich schneller eine Mail mit dem Betreff “On” an heating@meinserver.de schicken kann?

Um eine solche Anwendung zu realisieren wird ein SMTP-Server benötigt. Node.js versteht sich sehr gut auf solche Protokolle und der eventbasierte Ansatz ist bei eingehenden Mails sicher auch nicht verkehrt. Und so gibt es bereits eine kleine Zahl an guter SMTP-Server-Implementierungen. Mir ist vor allem der estländische Programmierer Andris Reiman aufgefallen, der für node.js viele Module geschrieben hat, die sich mit dem Versand und Empfang von Mails beschäftigen. So reichen seine beiden Projekte simplesmtp und mailparser, um einen einfachen SMTP-Server aufzusetzen und die Mails und Anhänge zu parsen.

Zuerst bauen wir den SMTP-Server auf:

var simplesmtp = require('simplesmtp');
var MailParser = require('mailparser').MailParser;

var server = simplesmtp.createServer({
  validateSenders: false,
  validateRecipients: false
});

server.on('startData', function(envelope) {
  envelope.mailparser = new MailParser();
  envelope.mailparser.on('end', takeMail);
});

server.on('data', function(envelope, chunk){
  envelope.mailparser.write(chunk);
});

server.on('dataReady', function(envelope, callback){
  envelope.mailparser.end();
  callback();
});

server.listen(25);

Der Code ist relativ selbsterklärend: Bei Eingang einer Mail wird das startData-Event gefeuert, einzelne Datenchunks werden durch den data-Listener bearbeitet, und wenn die Mail vollständig übertragen wurde, feuert dataReady. Der Rahmen envelope wird dabei allen Funktionen übergeben, sodass envelope.mailparser auch in allen Funktionsaufrufen für eine Mail der gleiche ist. So werden bei zwei gleichzeitig eingehenden Mails diese nicht versehentlich vermischt.

Sobald die Mail vollständig übertragen wurde (dataReady), lösen wir mailparser.end() aus, was das Parsen der Mail beginnt. Fehlt noch die Definition, was mit unserer geparsten Mail denn passieren soll:

function takeMail(mail_object) {
    console.log('From:', mail_object.from); //[{address:'sender@example.com',name:'Sender Name'}]
    console.log('Subject:', mail_object.subject); // Hello world!
    console.log('Text body:', mail_object.text); // How are you today?

    // Irgendein Datenbankaufruf o.ä.
}

Hier kann die Mail nun also ausgewertet und so die gewünschte Aktion ausgelöst werden. Das tolle am Mailparser ist die Tatsache, dass Dateianhänge ebenfalls soweit wie möglich geparst werden. So enthält das mail_object auch einen Eintrag attachments, der etwa so aussehen könnte:

attachments = [{
    contentType: 'image/png',
    fileName: 'image.png',
    contentDisposition: 'attachment',
    contentId: '5.1321281380971@localhost',
    transferEncoding: 'base64',
    length: 126,
    generatedFileName: 'image.png',
    checksum: 'e4cef4c6e26037bcf8166905207ea09b',
    content: <Buffer ...>
}];

Attachments-Beispiel von mailparser

So könnte man leicht einen Service wie den von Twitpic einrichten, dass man durch das Senden an eine userspezifische Mailadresse ein Bild hochladen kann.

Wem das ganze zu unsicher scheint, weil ja sonst jeder, der die Mailadresse kennt, Dummheiten anstellen könnte, der sei auf die Serverkonfiguration ganz oben hingewiesen: Werden validateSenders und validateRecipients auf true gesetzt, können Sender und Empfänger in einer eigenen Funktion überprüft und ggf. zurückgewiesen werden. Die simplesmtp-Bibliothek bietet daneben auch noch andere Authorisierungsmechanismen.

Neulich beim Google Developer Day in Berlin…

Werden Studierende heute gefragt, in welcher Firma sie nach ihrem Studium am liebsten arbeiten würden, fällt ein Name besonders häufig: Google. Das Unternehmen, das gleichermaßen polarisiert wie inspiriert, liegt in Umfragen als beliebtester Arbeitgeber in Europa ganz vorn. Und das über alle Fachrichtungen hinweg.

Wie interessant Google gerade für Informatikstudenten ist, zeigte sich auch am dritten Novemberwochenende in Berlin: Auf der letzten Station der diesjährigen Google Developer Days (GDD) wurde das Internationale Congress Centrum in unserer Bundeshauptstadt zum Pilgerort für Entwickler aus ganz Europa. Auch ich machte mich am Freitagabend auf den Weg – nachdem das mit der Node.js Conference in Italien im September leider nicht geklappt hatte, bewarb ich mich in einem Anfall von Größenwahnsinn auf eines der Developer-Tickets. Und bekam eine Zusage.

Glücklicherweise kam ich auch noch kurzfristig in den Genuss günstiger Flugtickets. Ansonsten wäre der Wochenendtrip (mal eben für einen Tag nach Berlin) zum GDD sicher sehr viel stressiger verlaufen. Doch genug der langen Vorrede: Was gab es nun zu sehen?

Auf der Keynote wurden neue Services und das neue Android vorgestellt.

Wer die Akkreditiertung hinter sich gebracht hatte, sich vom großartigen Frühstücksbuffet loseisen konnte, auf den wartete die anderthalbstündige Keynote. Was in Apple-Manier anfing, scheiterte letztlich kläglich an mangelnder Technik. Und damit meine ich nicht nur versagende Mikros und ausfallende Internetverbindungen, sondern auch die vorgestellten Features ;) Irgendwie blieb ein richtiger Wow!-Moment leider aus.
Dafür sollten die anschließenden sieben Stunden, vollgepackt mit allerhand interessanter Themen, entschädigen. Den über 2000 Entwicklern boten sich insgesamt 35 Sessions in den Themenblöcken Android, Chrome & HTML5, Cloud und Google+. Einen eigenen Track füllten die Berliner Universitäten, die mit einigen wissenschaftlichen Themen aufwarteten. Eines von ihnen hieß “Internet architecture trends”, das ich auch als erstes besuchte.
Ich war beeindruckt, wieviel der Dinge, die dort als Pros und Contras zu alternativen Internetarchitekturen genannt wurden, ich doch schon richtig einordnen konnte. Es schien mir beinahe so, als hätte ich durch die letzten Wochen aus der Vorlesung “Grundlagen der Rechnernetze” gerade genug mitbekommen, um dem Thema folgen zu können. Insofern bot der Vortrag auf jeden Fall die Motivation, dass nicht alles, wofür ich in der Uni pauke, vollkommen umsonst ist.

Weiter ging es mit “Working Off the Grid: HTML5 Offline”. Durch die vielen guten Beispiele sind dort sicher viele Zuhörer rausgegangen in der Erkenntnis, HTML5 in eigenen Projekten sinnvoll anwenden zu können. Und sei es “nur” zur Ladezeitoptimierung. Mit Fallbeispielen zu den neuen HTML-Technologien hätte ich nach dem Mittagessen auch weitermachen können, aber ich entschied mich für etwas Abwechslung und eine Einführung in die neuesten Cloud Technologien von Google (“Building Integrated Applications on Google’s Cloud Technologies”). Vorgestellt wurden u.a. die Prediction API und Googles BigQuery. In meinem Kopf sprießen seitdem ein Haufen möglicher Anwendung. Die Begeisterung rührt sicher auch von der wirklich sympathischen Vortragsweise von @nTangledMichael. Wer irgendwo ein Video davon findet: Anschauen!

Auch die uulm war bei den Ausstellern vertreten!

Mit “These aren’t the Sites You’re looking for: Modern HTML5 Web Apps” verschlug es mich zurück in den HTML5-Track. Viele praktische Tipps, aber zugegebenermaßen auch kaum neues. Gerade die Erfolgszahlen von Unternehmen, die durch den Chrome Web Store unglaublich reich geworden sein müssen, wurden beginnend bei der Keynote in fast jeder Session nochmal vorgekramt.
Nicht so bei bei der Vorstellung der neuen “programming language for structured web programming”: Dart. Es war eine nette kleine Einführung – aber eben auch nicht mehr. Interessant war die Feststellung, dass ein Teil der ehemaligen GWT-Entwickler nun an Dart mitarbeiten würde. Leider erschließen sich mir aber immer noch nicht die großen Vorteile von Dart gegenüber Javascript. Aber das wird sich vielleicht auch erst mit der Zeit zeigen.

Zuletzt standen die beiden Blöcke “Monetizing Web Apps” und “DevTools – Tips and Tricks” an. Ersteres überzeugte vor allem durch die Einfachheit, die Google zur Abwicklung von Micropayment Entwicklern bietet. Wer im Laufe des Tages Ideen für eine tolle Web-Anwendung bekommen hatte, wusste nun auch, wie man sie zu Geld macht. Ein Überblick über die Tools, die Chrome Entwicklern bietet, brachte dann den Ausklang der Sessions.

Der Abend klang aus mit einem Meet’n’Greet im großen Foyer des ICCs. Bei Bier und Brezeln konnte noch über so allerhand Technik diskutiert werden. Für mich war der Abend damit aber trotzdem schnell beendet, denn nach der späten Landung am Vorabend, der frühen Anreise in den Westen Berlins und dem vielem neuen Input hatte ich dann auch langsam genug.

Mein Fazit? Googler sind unglaublich jung! In dem etwa 40 Mann umfassenden Team, das für den GDD nach Berlin angereist war, fanden sich nur junge oder junggebliebene Leute. Die Speaker, die sich stets als Product Manager von irgendwas (Chrome zum Beispiel) vorstellten, waren allesamt nicht älter als 35. Das spricht für flache Hierarchien und viel Vertrauen in junge Leute.
Ganz allgemein präsentierte sich Google unglaublich sympathisch. Das fing damit an, dass der Deutschland-Chef meinte, dass wir nicht den Googlern danken sollten, sondern die mehr als 2000 anwesenden Entwickler eben diesen Dank verdient hätten. Daneben überzeugte der Developer Day durch viele kleine Details, sei es nur, dass es beim Mittagsbuffet eben u.a. auch typisch Berliner Essen gab.
Schön fand ich auch, dass es seitens der Speaker keinerlei Engstirnigkeit gab. Als ich mich angemeldet hatte, fragte ich mich noch, ob man wohl besser nur von Google Plus statt Facebook, Android statt iOS und Chrome anstelle von Firefox sprechen sollte. Aber nichts dergleichen. Die Googler zeigten auch mit ihren vielen MacBooks, dass man eben immer damit arbeiten sollte, was für die jeweilige Aufgabe am besten ist. Und dies bedeutet beim Browser-Beispiel etwa auch, dass sie sehr am Fortschritt von Firefox und anderen Konkurrenten interessiert sind, da nur so die im Chrome bereits umgesetzten HTML5-Features Anklang bei der breiten Masse finden und zum Standard werden können.

Alles in allem also eine gelungene Veranstaltung, mit der Google nicht nur Werbung für neue Technologien gemacht hat, sondern vor allem für sich selbst!

Weiterführende Links:

Optimierung SQL-basierter Umkreissuchen – Teil 2: Vergleich der Lösungsideen

Im ersten Teil haben wir zwei einfache Lösungsstrategien entwickelt, wie sich Umkreissuchen der Form “Suche die nächstgelegenen 15 Orte heraus!” durch einen Subquery vorfiltern lassen: Die grundsätzliche Idee ist, über eine Näherungsformel eine Selektion von 15*faktor Datensätzen zu finden, aus denen dann die echt-nächsten Orte bestimmt werden können.

Als Näherung bietet sich so die Pythagorasformel an, die in diesem Beitrag in der simplen Form (Breiten- und Längengerade gehen gleich gewichtet ein) und der verbesserten (mit Gewichtung von 1:1,57 in Deutschland) untersucht wird. Dabei gilt grundsätzlich die Frage zu klären, wie groß in beiden Fällen wohl der faktor gewählt werden muss, damit in den meisten Fällen in der Näherungsselektion auch alle 15 echt-nächsten Orte enthalten sind. Daneben interessiert natürlich, wie groß der Performancegewinn beider Strategien ausfällt.

Dazu habe ich ein kleines Testscript in node.js geschrieben, das eine ganze Reihe Testfälle generiert und durchspielt. Insgesamt wurden für 200 zufällige Orte in Deutschland oder grenznahen Regionen jeweils die 1, 5, 10, 20, 50, 100, 150 und 200 echt-nächsten Orte gesucht. Das Script ermittelt dabei für die beiden Näherungsformeln, wieviele Datensätze durch diese geliefert werden müssen, damit die gesuchten Orte auch wirklich enthalten sind. Ein mögliches Ergebnis wäre also etwa, dass wir über die einfache Pythagorasformel für den Alexanderplatz Berlin mindestens 25 Datensätze erhalten müssten, damit keiner der 15 echt-nächsten fehlte.
Als Datenbasis dient dabei die Vereinsdatenbank von meinem nodeKO-Projekt, die etwa 2600 echte Vereine enthält und somit auch recht praxisnah für diesen Versuch ist.

Die entstandenen 1600 Messdaten und Auswertungen können bei GoogleDocs eingesehen werden. Das Testscript arbeitet so, dass nie zwei Queries gleichzeitig abgesetzt werden, die Zeitmessungen sind also ohne Last.

Als erstes soll es uns aber gar nicht um die Performance gehen, sondern viel mehr um die Ermittlung eines geeigneten Faktors für die beiden Näherungen. Im Limits-Sheet sind dabei die Messwerte zusammengefasst: Will man z.B. die 20 nächsten Datensätze ermitteln, so sollte man im Mittel über die einfache Pythagorasformel mindestens 35 Datensätze selektieren, bei der verbesserten Formel reichen dagegen 21 (!). Interessant sind auch die Maxima: Nach spätestens 97 Datensätzen waren in allen Testfällen alle 20 gesuchten bei der einfachen Formel enthalten, die verbesserte kam da mit einem maximalen Limit von 30 aus. Im Mittel über alle Tests ergibt sich, dass, wer die Pythagorasformel anwendet, den faktor wenigstens bei 1.75 ansetzen sollte. Bei Hinzunahme des Verhältnisses lon/lat reicht dagegen ein Faktor von 1.05. Wichtig hierbei ist natürlich, dass stets aufgerundet wird.

Der Mittelwert ist aber nur bedingt aussagefähig. Es bleibt immer noch die Frage: Wie häufig ist mein Ergebnis wohl trotzdem falsch, wenn die obigen Werte eingesetzt werden?
Hierfür habe ich die Versuchsergebnisse anders betrachtet: Mit welcher Wahrscheinlichkeit sind alle gesuchten Datensätze wohl enthalten, wenn bei der einfachen Pythagorasformel der Faktor 2 (wir sind mal großzügig…) genutzt wird? Für mich vor allem interessant, weil ich diesen Faktor bei meinem Projekt eingesetzt hatte. Und tatsächlich: Es zeigt sich, dass der Faktor 2 in gerade mal vier von fünf Fällen die gesuchten Ergebnisse liefert. Wer die Pythagoras-Näherung einsetzt, sollte diesen Faktor also doch lieber ein wenig großzügiger bemessen.

Anders ist das bei der verbesserten Pythagorasformel: Mit Faktor 2 hätte sie in allen 200 Testfällen die gesuchten Orte auch mit selektiert. Selbst der Faktor 1.5 ist noch mehr als ausreichend und lieferte in mehr als 99 Prozent die gesuchten Datensätze. Doch wie weit kann man noch runter gehen? Bei einem Faktor von 1.3 sind immer noch sehr annehmbare 98 Prozent der Anfragen korrekt, bei 1.1 fast 97 Prozent.

Und wozu das ganze? – Natürlich um Rechenzeit zu sparen. Die ermittelten Laufzeiten sind leider nur bedingt aussagefähig. Sie geben jeweils an, wieviel Zeit erforderlich war für eben jenen Query, der zuerst alle gesuchten Datensätze enthielt. In Ausnahmefällen kann das also schon mal deutlich mehr sein, als man erhalten würde, wenn man einfach einen fixen Faktor einsetzte. Und dennoch sprechen bereits diese Zahlen für sich: Durch die verbesserte Pythagorasformel erhält man einen Performancegewinn von fast 50 Prozent, die Anwendung lohnt also.

In meinem Projekt äußerte sich der Gewinn sogar noch deutlicher. Dort hatte ich direkt auf meine Tabelle gejoint und gleichzeitig die 15 nächsten Orte gesucht. Resultat: Alle Datensätze wurden erst gejoint und anschließend reduziert. Natürlich ist ein erster möglicher Schritt die Tabelle per Subquery sofort mit der exakten Entfernungsformel zu reduzieren, das bringt auch schon einen deutlichen Gewinn. Noch schneller geht es aber mit den beiden gezeigten Näherungen.
Insbesondere ist es durch die obigen Erkenntnisse möglich, einen Teil der Last auf den Client umzulegen. So wäre ein geeignetes Vorgehen etwa, dem Client stets limit*faktor genäherte Datensätze auf seine Anfrage zurück zu geben, was für den Server sehr viel schneller als die exakte Rechnung ginge. Der Client müsste jetzt selbst den letzten Schritt gehen und für die erhaltenen Orte die exakte Entfernungsberechnung durchführen, um die echt-nächsten limit Orte zu bestimmen.

ioexception.de

Benjamin Erb [] studiert seit 2006 Medieninformatik und interessiert sich insbesondere für Java, Web-Technologien, Ubiquitous Computing, Cloud Computing, verteilte Systeme und Informationsdesign.


Raimar Wagner studiert seit 2005 Informatik mit Anwendungsfach Medizin und interessiert sich für C++ stl, boost & Qt Programmierung, Scientific Visualization, Computer Vision und parallele Rechenkonzepte.


David Langer studiert seit 2006 Medieninformatik und interessiert sich für Web-Entwicklung, jQuery, Business Process Management und Java.


Sebastian Schimmel studiert seit 2006 Informatik mit Anwendungsfach Medizin und interessiert sich für hardwarenahe Aspekte, Robotik, webOs, C/C++ und UNIX/Linux.


Timo Müller studiert seit 2006 Medieninformatik. Er interessiert sich allen voran für Mobile and Ubiquitous Computing, systemnahe Enwticklung und verteilte Systeme, sowie Computer Vision.


Achim Strauß studiert seit 2006 Medieninformatik. Seine Interessen liegen in Themen der Mensch-Computer Interaktion sowie Webentwicklung und UNIX/Linux.


Tobias Schlecht studiert seit 2006 Medieninformatik und interessiert sich vor allem für Software Engineering, Model Driven Architecture, Requirements Engineering, Usability Engineering, Web-Technologien, UML2 und Java.


Fabian Groh studiert seit 2006 Medieninformatik. Seine Interessengebiete sind Computer Graphics, Computer Vision, Computational Photography sowie Ubiquitos Computing.


Matthias Matousek studiert seit 2007 Medieninformatik und interessiert sich besonders für Skriptsprachen, Echtzeitsysteme und Kommunikation.


Michael Müller [] studiert seit 2009 Medieninformatik. Er interessiert sich vor allem für Web-Technologien, Ubiquitous Computing, User-Interfaces, UNIX und Creative Coding.


Falco Nogatz [] studiert seit 2010 Informatik mit Anwendungsfach Mathematik. Er interessiert sich für Web-Technologien, Programmierparadigmen und theoretische Grundlagen.

Archiv

Februar 2015
M D M D F S S
« Mrz    
 1
2345678
9101112131415
16171819202122
232425262728