Ruby-on-Rails Datenbankoptimierung Teil 1

Anzahl der Datenbankabfragen optimieren

Eine typische Webanwendung stellt viele Datenbankanfragen, bevor sie die Antwortseite an den Webbrowser ausliefert. Bei jeder dieser Datenbankabfragen muss die Anwendung auf die Antwort warten, dazu kommen noch Prozessumschaltungen, die zusätzlich bremsen. Der Datenbankserver muss jede Anfrage analysieren, und auch die Kommunikation zwischen Datenbank und Anwendung braucht Zeit. Weniger Datenbankanfragen reduzieren die Gesamtbelastung des Systems, das System skaliert besser.
„Ruby-on-Rails Datenbankoptimierung Teil 1“ weiterlesen

Ilias-Funktionen verändern

Beispiele zur Umgestaltung

Das Lernmanagementsystem Ilias lässt sich mit Skins umgestalten. (Darüber habe ich in einem früheren Blogeintrag geschrieben.) Ein Ilias-Skin kann aber sogar die Funktionalität verändern. Hierfür gebe ich nachfolgend einige Beispiele.

Loginseite

Die Templates zu Login, Logout und zur Nutzungsvereinbarung finden Sie unter Services /init/default In unserem Projekt haben wir folgende Änderungen an der Loginseite durchgeführt:

„Ilias-Funktionen verändern“ weiterlesen

Attribut oder Property?

Eine Falle beim Update von jQuery

In einer bestehende Webanwendung wollte ich die JQuery-Bibliothek von Version 1.4.X auf 1.6.x aktualisieren. Zum größten Teil gab es keine Probleme, nur an folgender Stelle funktionierte es nicht. „Attribut oder Property?“ weiterlesen

Rails ActiveRecord: count, length oder size?

Die objektorientierte Datenbankschnittstelle „ActiveRecord“ bietet gleich drei verschiedene Methoden zum Bestimmen der Anzahl: count(), length() und size().

Alle drei Methoden liefern das gleiche Ergebnis. Was nehmen wir wann? Warum ist es überhaupt wichtig?
Nimmt man die falsche Methode, dann erzeugt unsere Ruby-on-Rails-Anwendung überflüssige Datenbankabfragen oder braucht mehr Speicher als eigentlich nötig. Die Anwendung skaliert dann schlechter. Um mir die Unterschiede zwischen den Methoden leichter zu merken habe ich folgendes Schema erstellt.

„Rails ActiveRecord: count, length oder size?“ weiterlesen

LwUIT 1.5 erste Erfahrungen

Sun hat mit „Java Mobile Edition“ (JME) die Softwareplattform geschaffen, die weltweit auf Milliarden von Handys funktioniert. Die Plattform ist inzwischen in die Jahre gekommen, und besonders für die Gestaltung der Benutzerschnittstelle bietet sie nur wenig, um die Möglichkeiten heutiger Handys auszunutzen.

Mit LWUIT  wurde ebenfalls von Sun eine Bibliothek für die Gestaltung von Benutzerschnittstellen vorgestellt. LWUIT unterstützt Touchscreens und Animationen. Ein Jahr lang konnte man zwar in dem Blog eines LWUIT-Entwicklers die Weiterentwicklung verfolgen, es gab jedoch keine neuen Versionen. Ich hatte schon befürchtet, dass der neue Eigentümer Oracle das Projekt ganz einschlafen lässt. Das der genannte Blog bei Google liegt und nicht bei Sun bzw. Oracle wertete ich ebenfalls als Indiz, dass das Projekt für die Firma nicht besonders wichtig zu sein scheint.

Anfang August 2011 ist schließlich doch noch die Version 1.5 veröffentlicht worden.

„LwUIT 1.5 erste Erfahrungen“ weiterlesen

Ilias Skins

Bedarfsgerechte Anpassung eines webbasierten Lernmanagementsystems

Ilias ist ein sogenanntes Lernmanagementsystem (LMS), d.h. ein System für webbasierte Bildungsangebote. Es ist ein sehr umfassendes System. Neben den Inhalten in Onlinekursen sind auch Kommunikationskanäle wie Foren, Mail und Chat integriert.

Beim Einsatz eines solchen Systems im Kontext einer bestehenden Organisation tritt meistens der Wunsch auf, die Gestaltung der Benutzeroberfläche zu verändern.

 

Gründe hierfür sind beispielsweise:

  1. Differenzierung: Man möchte sein Angebot nicht wie jedes andere aussehen lassen.
  2. Man möchte das System an das eigene Corporate Design anpassen, dazu gehört das Unternehmenslogo und die Farbgestaltung.
  3. Konkrete Bedürfnisse der Anwender: In unserem Projekt wollen wir die Bedienung vereinfachen, in dem wir selten benutzte Optionen weglassen.
  4. Vorschriften, die einzuhalten sind. Das können vorgeschriebene Benennungen sein, oder Ergonomierichtlinien für die Schriftgröße.

„Ilias Skins“ weiterlesen

Eins plus Zwei

Eine Überraschung in Ruby.

Selbst bei so etwas einfachen wie der Addition von Zahlen gibt es manchmal Überraschungen. Doch der Reihe nach. Wenn wir den interaktiven Ruby-Interpreter „irb“ starten, können wir in als einfachen Rechner nutzen.

irb> 1+2
=> 3

So weit so praktisch. In der Programmierpraxis liegen Zahlen häufig als String vor, z.B in Textdateien oder als Formularparameter in Webseiten. Probieren wir also folgendes:

> input="1"
> input+2
TypeError: can't convert Fixnum into String

Richtig, wir müssen in Ruby erst explizit den String in einen Integer umwandeln. Dafür gibt es die Methode to_i

> input.to_i+2
=> 3

Ok, damit es etwas besser aussieht, fügen wir ein Leerzeichen ein

> input.to_i +2
=> 1

Huch? Was war das? Ist unsere Variable vielleicht überschrieben worden? Probieren wir es mal direkt:
„Eins plus Zwei“ weiterlesen

Mehrsprachige Webseiten mit Ruby on Rails (3)

Teil 3 – Qualitätssicherung

Texte gehören zu den Teilen einer Anwendung, die häufig geändert werden. Wenn dann noch externe Übersetzer im Spiel sind, kann es leicht passieren, dass Übersetzungen fehlen.

Wir möchten deshalb automatisch testen, dass es zu allen Texten in Sprache A auch Übersetzungen in Sprache B vorhanden sind. Ein solcher Test allein hilft schon sehr, und sollte ja nicht so schwierig sein.
„Mehrsprachige Webseiten mit Ruby on Rails (3)“ weiterlesen

Classics reloaded: Das Assert-Makro von C

Die erste Version des folgenden Textes stammt noch aus dem Jahr 1996. Er enstand, weil ich bei den damaligen Arbeitgebern beobachtete, dass viele C-Entwickler nicht wussten, was es mit assert() auf sich hat. Hier kommt die Wiederveröffentlichung:

Selbstidentifizierende Fehler

Es gibt in ANSI-C einen Mechanismus, viele Fehler auch ohne Debugger aufzuspüren: Das Assert Macro. Ein Teil des Problems liegt in Deutschland wohl auch im Namen: Assert ist ein Wort, welches im allgemeinen im Englisch an der Schule nicht benutzt wird. Meine Übersetzung hierfür lautet Zusicherung. Das Assert Macro prüft diese Zusicherung, und druckt, falls es schief geht, seine eigene Datei mit Zeilennummer im Quelltext aus. Ein Beispiel:

int readFile(char * filename    char * buffer){
    int filehandle;
    assert( filename != NULL);
    assert(strlen(filename) > 0);
    assert(strlen(filename) < MAX_FILENAMELEN);
    filehandle = open(filename, READ_ONLY);    
    ...
}

Falls jetzt irgend jemand meine Funktion mit falschen Parametern aufruft, z.B. mit einem leeren String, passiert während des Programmlaufes folgendes:

assertion failed in file readfile.c, line 34:strlen(filename) > 0
program aborted

Der Tester, wer immer das ist, kann in der angegebenen Datei die Zeile aufspüren, in der der Fehler auftrat, und erfährt dann, dass die Funktion readFile mit einem Leerstring aufgerufen wurde. Oft hat man damit schon die Fehler gefunden, in den anderen Fällen hat man zumindestens einen Anhaltspunkt.

Frage: Sollte man nicht eine wasserdichte Fehlerbehandlung machen?

Welcome to Reality! Die obige Lösung ist ein Einzeiler. In der Praxis bedeutet dieses: Ein assert() schreibt man auch hin, wenn man meint, das ein bestimmter Fall in der Praxis nie und nimmer auftreten wird. Im obigen Beispiel ist der Programmierer der Aufruffunktion dazu verpflichtet, der Funktion einen Buffer zur Verfügung zu stellen. Wenn der Buffer bei NULL liegt, hat er Mist gemacht.

Bei der Länge des Filenames kommt es auf die Anwendung an: Falls hier ein vom Endbenutzer eingegebener String direkt benutzt wird, ist die assert Lösung allenfalls während der Prototypphase erlaubt. Die Fehler, von denen man damit rechnet, dass sie während des normalen Betriebes auftreten, sollte man selbstverständlich auch korrekt abfangen.

Das Assert hat auch seinen Sinn, wenn es nicht feuert: Bei einer Fehlersuche kann ich sicher sein, dass ein bestimmtes Problem nicht aufgetreten ist, dass ich den Fehler also woanders suchen muss. Nicht zuletzt teile ich den armen Leuten, die mein Programm einmal warten müssen, etwas über meine Intention mit: Der Pointer darf kein NULL-Pointer sein, der Dateiname soll weniger als X Buchstaben haben, …

Das alles kann man auch in die Kommentare schreiben, aber nur Code lügt nicht.

Frage: In C++ und Java gibt es doch den Exception Mechanismus.

Ja der ist oft noch besser, aber leider auch noch etwas komplizierter. Vieles, was ich gesagt habe, lässt sich auch auf diesen Mechanismus übertragen. Leider kann man sich auch nicht immer aussuchen, in welcher Sprache man programmiert.

Frage:Wenn diese Fehlermeldung dann im laufenden Betrieb beim Kunden auftritt, ist das doch eher peinlich. Und das Programm wird doch bestimmt größer und langsamer? Das heißt doch, nachher muss ich alle assert() Anweisungen wieder entfernen?

Zum Glück nicht! Das Assert läßt sich durch einen Compilerschalter aktivieren oder deaktivieren. Wenn in irgendeiner eingebundenen Headerdatei steht:

#define NDEBUG

oder in der Make-Datei:

-DNDEBUG

so wird für das Assert kein Code erzeugt, so als ob man alle assert Zeilen rausediert hätte.

Frage:

Wie funktioniert das eigentlich?

Das Geheimnis liegt im Zusammenspiel von Preprocessor und Compiler. Das Assert ist als Macro implementiert, im allgemeinen in der Datei assert.h. Das Grundgerüst ist folgendes:

#ifdef NDEBUG
#define assert(exp)
#else
#define assert(exp) \
  ( (exp) ? (void) 0 : _assert(#exp, __FILE__, __LINE__))
#endif

Das sieht doch reichlich kryptisch aus, ist jedoch gar nicht so kompliziert: Makros sind Textersetzer. Mittels #ifdef...#else...#endif wird dafür gesorgt, das nur Code erzeugt wird, falls das Symbol NDEBUG nicht definiert ist. Wenn doch wird nämlich assert zusammen mit seinen Argument durch einen leeren String ersetzt, der Compiler bekommt die betreffenden Zeilen nicht einmal zu Gesicht. Im Debugfall setzt der Compiler die Wörter __FILE__ und __LINE__ durch die aktuelle Quelldatei (nicht assert.h, sondern die Datei der Aufrufstelle) und die aktuelle Zeilennummer. Der Ausdruck #exp wird durch den aktuellen Ausdruck als String ersetzt.

Die eigenartige Klammerstruktur (xxx ? yyy : zzz) gehört zum normalen C Sprachumfang, wird jedoch von wohlerzogenen Programmierern nur in Ausnahmefällen wie diesen verwendet. Es ist ein verkürztes if-statement. Die Backslashes am Ende der Zeile verlängern die Zeilen, da der Makromechanismus ausschließlich zeilenorientiert arbeitet. Insgesamt erzeugt der Preprozessor aus der Zeile

  assert(strlen(filename) < 0);

die Zeile

  ((strlen(filename) > 0) ? (void) 0 : _assert("strlen(filename > 0", __FILE__, __LINE__));

Die tief im Inneren einer Library definierte Funktion _assert() gibt die Argumente, z.B. mit printf(), auf den Bildschirm aus und bricht das Programm ab.

Frage: Alles schön und gut, aber ich programmiere mit einem Fenstersystem, manchmal programmiere ich auch Anwendungen ganz ohne Bildschirm. Was nun?

Viele Benutzer haben Glück: In einigen Entwicklungsumgebungen gibt es ein assert(), das ein Pop-up-Fenster öffnet. Ansonsten lohnt es sich für solche Fälle, ein assert-Macro selbst zu schreiben. Das prinzipielle Vorgehen ist dabei, eine Ausgabefunktion zu schreiben, die die betreffende Ausgabe irgendwohin ausgibt, die Datei assert.h zu kopieren und statt des _assert die eigene Ausgabefunktion aufzurufen. Die Ausgabe kann in eine Logdatei, über die Soundschnittstelle, als E-Mail, SMS, Fax, Lavalampen, oder als was auch immer erfolgen.

Ähnlich ist auch in anderen Programmiersprachen zu verfahren. Meistens bieten die Hersteller irgendeine Entsprechung zu __FILE__ und __LINE__ an, selbst wenn es nicht im offiziellen Sprachstandard ist.

Frage: Das ist ja toll, was man mit Macros alles machen kann, ich habe da gerade eine Idee …

Vorsicht: Wer Macros einsetzt, nur um ein paar Zeilen Code zu sparen, wird es irgendwann bitter bereuen. Ich habe mal bei einer Firma ein Macro entdeckt, das dazu dienen sollte, Teile eines Records in einen anderen zu kopieren. Dieses Macro war schon mehrere Jahre bei dieser Firma im Einsatz, leider war es nur manchmal korrekt. Ich habe mit mehreren anderen Entwicklern lange vor dem Macro gesessen, um herausfinden, was es eigentlich tat. Im Prinzip wirkte es sehr praktisch. Je nach dem, mit welchem Record man es aufrief, überschrieb es jedoch einen verbotenen Speicherbereich. Dieses Macro war bestimmt für etliche Abstürze verantwortlich, auch bei ausgelieferten Systemen. Die Firma war übrigens kurze Zeit später pleite …

Zurück ins Jahr 2009

Im Jahr 2009 werden Assert-Methoden oft in Unit-Tests verwendet. Dagegen ist auch nichts einzuwenden. Beim vorliegenden Text ging es mir aber um etwas anderes: die Verwendung von Assert im Programmtext selber. Diese Asserts können auch bei unerwarteten Fehler helfen. Sie sind auch allgemeiner: Sie prüfen Aussagen über das Programm, die immer gelten sollen, nicht nur bei bestimmten Testdaten. Asserts im Programmtext selbst sind deshalb auch bei Nutzung von Unit-Tests nützlich.

Rotierende Reklametafel mit jQuery

Billboard with changing picturesIm Jahre 1998 habe ich „Meiers Billboard“ vorgestellt: Eine virtuelle Anzeigentafel, die Bilder durch Rollen austauscht. Technisch ist es ein Java Applet. Der Ruf von Java im Browser wurde immer schlechter, auch mein Applet war vor allem wegen des Bild des Rahmen verlinkt.

In der Zwischenzeit ist sind die Netze leistungsfähiger, die Rechner schneller geworden und dank CSS gibt es neue Gestaltungsmittel. Bei der Beschäftigung mit dem JavaScript-Framework „jQuery“  stieß ich auf die animate()-Methode und ich fragte mich: lässt sich das Billboard nicht auch mit JavaScript realisieren? „Rotierende Reklametafel mit jQuery“ weiterlesen