Umstellung von Webprojekten auf UTF-8

Im letzten Artikel habe ich die Grundlagen zusammengefasst, mit denen ich mich beschäftigen musste um mein aktuelles Projekt voran zu bringen. Das Problem war ursprünglich die nicht einheitliche Handhabung diverser Zeichenketten, was bei Benutzer-Inhalten und Sonderzeichen zum berühmten Mojibake führen konnte (aber eben nicht zwingend muss). Nun denn, gehen wir ans Eingemacht und stellen das Projekt auf UTF-8 um, damit habe ich hoffentlich dann einen wichtigen Schritt in Richtung Zukunftsfähigkeit getan. Außerdem bietet sich UTF-8 wegen seiner Kompatibilität zu ASCII an – Programmcode wird dadurch nicht angetastet und PHP ist dankenswerter Weise sehr einfach gestrickt war Text-Ausgaben mittels „echo“ oder ähnlichen Befehlen betrifft: Was hintendran als Argument kommt wird genauso wiedergegeben wie es reingekommen ist – Byte für Byte. Damit hat man wenig Probleme, auch wenn eine Seite eben mal doch Sonderzeichen enthält (wie es im Deutschen leider häufiger der Fall ist). Dieser Post kann als grundlegendes Howto verwendet werden, es gilt jedoch immer: „Keine Garantie“ und „your milage may vary“

Erster Schritt – Anpassen der Entwicklungsumgebung

Damit man in Zukunft mit der Entwicklungsumgebung weiterhin einfach arbeiten kann, ohne sich jedesmal Gedanken über irgendwelche Sonderzeichen machen zu müssen – wenn man mal eben drei Zeilen Kommentar schreibt, sollte man sich auf dessen Inhalt konzentrieren können. Je nachdem was man verwendet gibt es da verschiedene Stellen die eingestellt werden müssen. Ich verwende Eclipse, dort kann man das Encoding einmal generell (unter Window -> Preferences -> General -> Workspace:  Text-File-Encoding) einstellen.  Zudem sollte man für die verschiedenen Einträge unter „Content Types“ sicherstellen, dass per default dort auch UTF-8 genommen wird. Unter Linux habe ich festgestellt, dass es meistens schon vorab eingestellt ist, denn die meisten aktuellen Linux-Distris sind vom System aus schon löblicherweise auf UTF-8 als Standard umgestellt. Ein Blick in die Äste Web -> CSS Files und Web -> HTML-Files schadet auch nicht. Im Ast XML sollte es per Default auch schon passen, aber Nachgucken schadet auch hier nicht.

Nun muss man noch die Projekt-Einstellungen anpassen (wenn man bestehende Projekte hat) – wenn man den Fehler gemacht hatte und ein neues Projekt angefangen hat ohne sich vorher über die Verwendung von Zeichensätzen Gedanken zu machen (sowas sollte auf jeder Checkliste für Projekte stehen, aber wer achtet da schon drauf wenn es mal eben um eine kleines Projekt geht …. das dann später wächst …). Wenn man die Umstellung gemacht hat, kann man einmal Buchstabensuppe sehen, indem man eine Datei öffnet die Sonderzeichen enthält … die sehen nun etwas komisch aus. Alle händisch ersetzen ist nur was für Hartgesottene oder sehr sehr kleine Projekte.

Zweiter Schritt – Datein umwandeln / umcodieren

Es gibt ein praktisches Tool zum Umwandeln <code>iconv</code> das Werkzeug gibt es auch für Windows, aber so richtig mächtig und scharf wird das erst in Kombination mit ein wenig Scripting (bei mir in Bash)


#!/bin/bash

for file in $(find . -type f -name ‚*.php‘)
do
iconv -f iso88591 -t utf8 -o $file.utf8 $file
if [ $? -eq 0 ]
then
#echo „$file erfolgreich“
mv $file.utf8 $file
else
echo $file geht nicht $?
fi
done

Was machen wir und warum mache ich da so? Ersteinmal suche ich alle betroffenen Dateien heraus, da ich mit PHP arbeite sind das alle Dateien die auf <code>.php</code> enden. Jede dieser Dateien lasse ich durch Iconv laufen und als neue Datei abspeichern. Man sollte nicht auf die Idee kommen <code>iconv -f iso88591 -t utf8 -o $file $file</code> zu verwenden. Das klappt nur bei kleinen Dateien. Wenn das nicht der Fall ist, hat man evtl. unvollständige Dateien und wundert sich was passiert ist, denn <code>iconv</code> gibt in diesem Fall keine Fehlerme. Mit dem Speichern in eine separate Datei bleibt das Original erst einmal unberührt und man kann sich ggf. auf die Fehlersuche machen, denn: Wenn beim Konvertieren selbst etwas schiefgeht gibt es einen exit-Code > 0. Wo es geklappt hat, überschreibe ich das Original. Ansonsten ein kleines <code>echo</code> das mir die fehlerhaften Dateien angibt damit man dort nachsuchen kann, meistens hat man schon irgendwo mal etwas als UTF8 gespeichert oder die Zeichensätze verbeult, das findet sich aber meist recht schnell. Bei mir waren es von 500 Dateien zwei Stück die etwas Handarbeit erforderten. Das gleiche Schema kann man auf alle reinen Textdateien anwenden, wenn man es braucht, z.B. reine HTML-Dateien (Endung htm oder html) oder auch JavaScript-Code. Wichtig ist noch dass man seinem Webserver ggf. beibringt, per default auch in UTF-8 auszuliefern. Dazu sucht man in den Konfigurationsdateien die folgende Zeile:

AddDefaultCharset UTF-8

Nach einem Neustart des Daemons wird das dann als default verwendet. Warum aber nur im default-Fall? Klar es gibt noch ne Möglichkeit das einzustellen und zwar in den ganzen HTML-Headern. Dort gibt es das META-Tag mit dem man Vorgaben machen kann auch für den Fall, dass man auf dem Server keinen Zugriff auf die Einstellungen des Apache oder wie auch immer sonst gearteten Webserver-Prozess hat.

&lt;meta equiv="content-type" content="text/html; charset=utf8"&gt;

Damit sollte jeder aktuelle und die allermeisten der älteren Browser in der Lage sein zu erkennen: Jetzt kommt was in UTF8.

Wenn man nur eine statische Website hat, ist man jetzt schon fertig – nur wer hat das schon heute noch?

Datenbankumstellung (MariaDB/MySQL)

Die Website an sich sollte nach der Umstellung weiterhin funktionieren, denn der eingebettete PHP-Code ist besteht nur aus Zeichen des ASCII-Repertoires und ist somit nicht verändert. Über das was zwischen Klammern steht oder einfach „unverdaut“ ausgegeben wird, macht PHP sich praktischerweise keine Gedanken sondern gibt es einfach aus, egal wie viel Bytes das sind und ob das nun ein besonderes Zeichen ist oder nicht.

Unlustig sind die Dinge die jetzt noch dynamisch aus der Datenbank nachgeladen werden. Wenn man es bisher (wie häufig bei Standardinstallationen) versäumt hatte auf UTF8 umzustellen, dann muss das jetzt auch noch erfolgen. Ich halte nichts davon die Daten bei jeder Ausgabe in UTF8-Strings zu konvertieren – das ist viel zu viel Aufwand wenn das Projekt eine gewisse Größe erreicht hat. Im übrigen haben viele Leute noch per default den Zeichensatz auf „latin1-swedish“ stehen, ein Hinweis woher MySQL denn ursprünglich mal kam. Im 0815-Tagesgeschäft fällt das aber in Europa meist niemandem auf.

Praktischerweise gibt es die Funktion
ALTER TABLE xyz CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]

Damit kann man jeweils eine ganze Tabelle umstellen und eine Collation vorgeben, wir erinnern uns: Collations regeln die Sortierreihenfolge je nach dem wie es gehandhabt werden soll.

Das klingt nicht schlecht und klappt im Allgemeinen auch ganz hervorragend, wenn da nicht einige Fallstricke wären.

Der erste ist ja noch gut gemeint seitens der Engine-Designer: Möglicherweise zu kleine Felder werden in das nächstgrößere Format überführt, wenn der Ausgangszeichensatz einer mit nur einem Byte pro Character ist, der Zielzeichensatz aber mehrere hat oder zumindest haben kann. So werden Textfelder mit bis zu 256 Zeichen zu Mediumtext umgewandelt. Das ist von der Auswirkung her eigentlich zu verschmerzen, aber in meinem Fall habe ich das hinteher wieder manuell korrigiert. richtig problematisch wird das wenn man über die entsprechenden Spalten Indizes angelegt hat, denn Textspalten lassen sich nicht indizieren.

Womit wir beim nächsten Fallstrick wären: An einigen Stellen funktioniert das mit der Umstellung nicht wie geplant, Ursache sind die Foreign-Keys. Ich habe an einigen Stellen „sprechende“ Schlüssel anstelle von numerischen verwendet. Gerade dann wenn man in den referenzierten Tabellen wirklich nur Sateliten-Informationen stehen, wie etwa ein Icon und eine ausführliche textuelle Beschreibung zu einem bestimmten Zustand. Einige werden jetzt die Hände über dem Kopf zusammen schlagen, aber ich habe bisher keine negativen Auswirkungen auf die Performance feststellen können, eher positive Effekte bei der Fehlersuche. Wenn man schon anhand des Eintrags in der Tabelle selbst weiß was Sache ist, kann man sich einen zusätzlichen Join sparen. Das hat ja auch seine Vorteile.

Was also tun? Im Netz findet man praktische Anweisungen, die gesamte DB einmal per  mysqldump in eine Textdatei zu konvertieren, dort dann mit iconv das Gleiche zu veranstalten wie mit den Code-Files, danach noch die Tabellen-Definitionen automatisiert anpassen und den Dump wieder in die Datenbank kippen. Das funktioniert, ist aber bei größeren Datenmengen unhandlich.

Stattdessen habe ich mir die Information-Schema-Tabellen zu Nutze gemacht: dort stehen die Meta-Informationen zu den Tabellen in Tabellen, die man wie gewohnt mit SQL-Befehlen lesen kann – schreiben leider nicht, aber immerhin etwas. Dort sucht man sich nun die betroffenen Spalten und Tabellen heraus (Varchars und Texte), zudem schaut man auf die Foreign-Keys und merkt sich diese. Dann schmeißt man die Foreign Keys weg, führt die Veränderungen an den Tabellen durch (das geht ja dann). Wenn das durchgelaufen ist, kann man noch die vergrößerten Spalten wieder auf die Original-Größe zurück setzen (also Mediumtext => Text usw). Zu guter Letzt schaltet man die Foreign-Keys die man sich gemerkt hat wieder scharf. Fertig ist die Laube. Ganz so einfach ist es im Detail nicht, denn man muss stets vollständige Spaltendefinitionen verwenden, einfach nur den Typ ändern geht so leider nicht, auch wenn das eine praktische Sache wäre.

Jetzt hat man das gesamte Projekt umgestellt – zumindest was die Datenbasis und was die HTML-Seiten und den eingebetteten JS-Code betrifft. Das ist in aller Regel alles was man braucht.

Was noch an Problemen auftreten kann, beschreibe ich in einem weiteren Artikel. Stichwort sind hier externe Libraries und Frameworks.

Mojibake – Buchstabensuppe

Na da hatte ich mir doch eine lange währende Aufgabe ausgesucht, die ich in der aktuellen Pflegephase meines Softwareprojekts endlich einmal angehen wollte. Aktuell läuft das Produkt soweit zufriedenstellend, nur an einigen kleiner Ecken knackt und knirscht es immer mal wieder. Unter anderem das leidige Thema „Sonderzeichen und deren Darstellung“ – da nicht absolut zwingend für die Funktionsfähigkeit habe ich das längere Zeit nicht großartig beachtet.

Nun gut, was ist das eigentliche Problem und woher kommt es? Die Ursachen liegen in der Historie des PCs ver- oder besser begraben: Da Speicher und Datenverarbeitung teuer war, hat man so sparsam wie möglich gearbeitet. Man stellte dabei fest: Inklusive aller wichtigen Zeichen der englischen Sprache und allem was man als Steuerzeichen (Zeilenumbruch, Tabulator, etc.) benötigt, bekommt man in 7 Bit unter. Das ist schon mal etwas krumm, denn gängig ist bei allem was Rechner betrifft doch eigentlich etwas eine Potenz von 2. Die ersten Rechner die ich verwendet habe (mit einem Intel 8088 als Unterbau) konnten nur 8 Bit parallel verarbeiten – immer mehr als die 7. Schon wenig später gab es 16Bit als Standard und mit der großen Verbreitung des PCs in die Büros war der Standard 32 Bit erreicht. Heute findet der sich bereits größtenteils in Ablösung durch 64Bit-Systeme. Was war der Sinn des 8. Bits? Man konnte es je nach Gusto verwenden: Entweder bohrte man damit den Zeichenvorrat auf, oder man konnte es zur Fehlererkennung und Korrektur einsetzen. Insgesamt muss man sagen: Alles mit Hand und Fuß.

Nur leider waren Rechner damals noch nicht gängigerweise vernetzt und die Standard-Definitoren etwas kurzsichtig – erst einmal wurde nur an die eigene Heimat gedacht, dass es möglicherweise andere Sprachen gibt, die nicht Englisch sind und einige Zeichen mehr mitbringen – wer konnte das schon ahnen? So kam was kommen musste: Einschränkungen bei diversen Dingen wie dem Betriebssystem: Umlaute oder Sonderzeichen in Dateinamen waren einfach nicht vorgesehen oder führten zu unvorhergesehenen Ergebnissen. Für das Verfassen und Verarbeiten von Texten war das natürlich keine Option, wer in Deutschland einen Text schreiben wollte, der sollte das auch tun können. Daher erweiterte man den Zeichensatz auf das 8 Bit und schon hatte man jede Menge Möglichkeiten auch Sonderzeichen abzuspeichern. Wichtig war nur, das jeder die gleiche Zuordnung traf und nicht einer ein ü für ein ö verwendete was die binäre Darstellung betraf. Soweit so gut oder auch schlecht.

Nun gehen leider bei verschiedenen Betrachtungen immer wieder einige Dinge durcheinander, auch ich habe hier am Anfag so meine liebe Mühe gehabt alles richtig zu verorten, daher hier einmal die Kurzfassung, zu allem was notwendig ist bzw. was sich auf die Darstellung und Handhabung von Texten am Rechner auswirken kann.

Binärer-Code

Eine Abfolge von 0en und 1en die irgendetwas darstellen – was ist für den Rechner erstmal unerheblich, dafür bedarf es einer Zuordnungs oder Code-Tabelle oder eines Algorithmus, der den Binärcode in etwas umsetzt, das dem Benutzer eher vertraut ist (leider sind wir Menschen nicht sonderlich gut binär veranlagt).

Code-Tabelle/Zuordnung/Algorithmus

Je nachdem was für eine Datentyp abgebildet werden soll, gibt es verschiedene Methoden dies zu tun. Am einfachsten sind ganze, positive Zahlen. Diese lassen sich aus der Abfolge von 0en und 1en entsprechend „errechnen“ – man muss nur noch wissen wo man anfangen muss (little endian vs. big endian). Für positive und negative Ganzzahlen hat sich das Zweierkomplement bewährt, für Fixkomma und Gleitkomma gibt es entsprechende Standards. Alles ein Thema für sich, denn wir wollen ja Texte bzw. Strings beleuchten. Hier hat sich eine Übersetzungstabelle als Mittel der Wahl erwiesen – sie ordnet jeder möglichen Abfolge von 0en und 1en eine menschenlesbare Bedeutung zu. So wird z.B aus der binären Folge 0110 1101  = 0x6D = O155 = „m“. Die Zuordnung an und für sich ist reine Willkür – man hat sich mal auf gewisse Standards geeinigt bzw. diese festgelegt, damit eben auf allen Rechner ein „m“ ein „m“ ist und nicht aus der „e-mail“ durch Willkür eine „e-nail“ wird. Der Urvater aller Standards dazu heißt ASCII (America Standard Code for Information Interchange) – wie der Name schon sagt ein nationales Standardformat. Auch bekannt ist diese Tabelle als Character-Set.

Windows-Codepages und Nornumg

Für verschiedene Regionen wurden verschiedene Verwendungen des verbliebenen 8. Bits (siehe oben) standardisiert – leider teilweise recht unterschiedlich, zum Teil nur an wenigen Stellen. Ziel war es, die in der jeweiligen Region verwendeten Sprachen möglichst gut abzubilden. Leider gab es da erst sehr spät eine Einigung auf einheitliche Standards, so dass zeitweise unterschiedliche Hersteller unterschiedliche Zuordnungen trafen. Ganz genauso wie wenn man Dateien ohne Angabe des verwendeten Zeichensatzes weitergab konnte es also passieren, dass der Zielrechner die Bit-Folge unterschiedlich interpretierte, weil bestimmte Bitfolgen eben etwas unterschiedliches bedeuteten. Dankenswerterweise hat man dabei die sichtbaren Zeichen (leider nicht so bei den Steuerzeichen) aus dem Urvater ASCII gleich belassen (das hatte sich ja bewährt, und für den internationalen Textaustausch reichte dieser kleinste gemeinsame Nenner auch aus). Gängig sind in der westlichen Welt die Standards der ISO 8859 in den Varianten 1-16, unter Windows die Codepage 1250 und unter DOS die Codepage 850.

Unicode

Mit der steigenden Internationalisierung und der immer stärker zunehmenden Vernetzung von Computern ist das mit den Nachschlagetabellen so eine Sache – man muss immer wieder etwas anderes berücksichtigen: Das Betriebsystem und die Region bzw. die Regionaleinstellungen des Anwenders – nur damit Text auch so ankommt wie er einegeben wurde. An einigen Stellen hat man sich beholfen oder die Probleme durch menschliche Intuition überbrückt – durch die Redundanz in der menschlichen Sprache kann man viele Worte ja auch lesen wenn Buchstaben vertauscht wurden oder nicht lesbar sind. Jeder Mensch der Lesen lernt kann das mehr oder weniger: Wenn aus einen Königreich dann plötzlich ein K$nigreich wird, dann wird der geneigte Leser das immer noch erkennen, auch wenn so ein Text etws mühsamer zu lesen ist. Ohnehin: wenn es international wird, dann ist die Sprache der Wahl in aller Regel doch Englisch und somit problemfrei. Aber wäre es nicht toll, wenn jemand eine Lösung hätte, damit ich auch chinesische Texte richtig angezeigt bekomme? Oder auch mal einen arabischen Text im Original anschauen? Das klingt weit hergeholt, aber diese Anwendungsfälle gibt es häufiger als man denkt. Die ursprüngliche Idee mit 32Bit und somit 4 Bytes pro codiertem Zeichen zu arbeiten (UTF-32) ist zwar einfach zu realisieren, aber ein wenig „over the top“ ist das schon: Wer überträgt schon gerne 3 komplett genullte Bytes wenn die Info doch nur in einem steht? Außerdem ist der Standard nicht abwärtskompatibel, er bricht mit den alten Vorgaben von ASCII, was bei älterer Software oder inkompatibler Software Ärger machen kann. Daher gibt es verschiedene Methoden mit variabler Anzahl von Zeichen, sozusagen das Beste aus beiden Welten: UTF-16 oder UTF-8 sind hierbei die bekanntesten Möglichkeiten.

Schriftarten und Glyphen

Wir haben uns nun langsam von der Bits & Bytes-Ebene nach oben gearbeitet hin zum abstrakten Begriff eines „characters“. Es gibt aber noch eine Ebene obendran – die Schriftarten oder auch Glyphen. Das ist im Prinzip eine weitere Tabelle die festlegt wie ein abstraktes Zeichen auf dem Ausgabemedium dargestellt werden soll. Jeder der sich einmal durch den Schriftenkatalog einer gängigen Office-Sammlung gewühlt hat, weiß das ein A ein A bleibt, auch wenn es etwas unterschiedlich geformt ist. Das beste Beispiel ist noch immer die eigene Handschrift im Vergleich zu einem beliebigen, gedruckten Werk. So lange eine gewisse Basis-Form erhalten bleibt, erkennt jeder Leser darin auch weiterhin ein A. Es gibt natürlich auch wieder Spezielle Schriftarten die als Darstellungvon Buchstaben Symbole haben, die nichts mit dem eigentlichen Zeichen zu tun haben – das bekannteste dürfte die Schriftarte Wingding oder auch Webdings sein. Besonders unpraktisch fällt mir diese immer wieder in e-mails aus Outlook auf, wenn man diese als Text ließt. Dort wird der Smily 🙂 automatisch in ein J umgewandelt und mit der Schriftart Wingdings formatiert – sieht zwar im ersten Moment richtig aus, aber mancher hat sich schon gewundert wo das „J“ denn nun herkommt. Ich merke es mir immer so: Ein Glyph macht aus einer Bit-Folge mittels einer Tabelle eine ganz bestimmte Grafik. Das ist zwar etwas vereinfacht, denn Schriftarten machen manchmal noch mehr, aber um den Überblick zu behalten reicht es allemal.

Collations

Was nochwas? Haben wir nicht alles endlich abgehandelt? Leider noch nicht ganz: Es gibt nämlich noch etwas was man mit Zeichenketten gerne macht: Aufreihen und Sortieren. Kling trivial, und es gibt doch Sortieralgorithmen wie Sand am Meer. Könnte man meinen, leider ist dem nicht ganz so (und das ist mit ein Grund weshalb man Sortieralgorithmen am besten an Zahlen erklärt …), denn auch wenn es im ersten Moment verlockend sein mag zu sagen: Man sortiert einfach nach der Größe der entsprechenden Ganzzahl der Bitfolge, das bringt leider nicht das gewünschte Ergebnis, denn schon bei ASCII haben wir ja große und kleine Buchstaben, ordnet man nun nach der errechneten Wertigkeit, so würde das folgende Sortierreihenfolge ergeben A,B,C…..,X,YZ,a,b,c – für die alphabetische Auflistung eines Materialkatalogs nicht das gewünschte Ergebnis – auch im Telefonbuch sucht man die Leute mit „von“ im Vornamen ja nicht unter „v“ sondern unter „V“ und dort irgendwo nach „Voldemort“…. und nun wirds ganz interessant: Wo ordne ich denn die Sonderzeichen wie Ä,Ö,Ü ein … sind das separate Zeichen am Ende? Oder soll ich sie behandeln wie „Ae“,“Oe“ und „Ue“? Das ganze nun noch auf die internationale Ebene gehoben und es wird ganz spannend: Je nach Land gibt es gleiche Zeichen, aber die werden unterschiedlich einsortiert, aber der Rechner soll es dennoch richtig machen. Das kann nur bedingt funktionieren, alles weitere regelt man über die Collation, die kann man zur Not auch bei der Sortierung mit angeben, und dem Sortierprogramm somit die Regeln vorgeben.

So jetzt habe ich einmal die Grundlagen zusammengefasst, die Auswirkungen und Mittel die man braucht um das alles umzusetzen behandle ich in einem separaten Artikel.

 

 

Die andere Seite der Laufveranstaltung – Herbstlauf 2013

An einer Laufveranstaltung teilnehmen ist eine Sache – je nach Streckenlänge auch entsprechend anstrengend aber jedesmal ein tolles Erlebnis für mich. Auch nicht zu verachten ist aber der Schritt auf die andere Seite, hinter die Kulissen. Mit der Organisation des Herbstlaufs 2013 der DJK habe ich auch dieses Jahr den Schritt wieder getan. Mittlerweile liegt die Veranstaltung etwas mehr als eine Woche zurück – Zeit ein wenig zurück zu blicken.

Nach dem Lauf ist vor dem Lauf – so ungefähr war das Credo nach der ersten Durchführung des Herbstlaufs 2012 – zum ersten Mal hatte die Triathlon-Abteilung die Organisation vollständig übernommen, zudem wurde erstmals eine Chipzeitmessung eingesetzt. Klar das da einiges noch nicht flüssig lief und die eine oder andere Erkenntnis mühsam gewonnen werden musste. Somit begann es bereits nach der ersten Nachbesprechung mit konkreten Beschaffungen – in diesem Jahr erleichterte uns schon ein Gabelhubwagen an vielen Stellen die Arbeit erheblich. Zudem wurde die Markierung der Strecke optimiert. Auch die Erfahrungswerte in Sachen Software und Hardware zahlten sich dieses Jahr aus: WLAN im Feld ist zwar nett, aber nicht zuverlässig genug. Daher diesmal gleich Kabel, das dauert auch nicht viel länger im Verlegen, wenn alles vorbereitet ist.

Die richtig heiße Phase ab Freitag beim Aufbau verlief denn auch entsprechend kühl, innerhalb weniger Stunden stand die IT-Infrastruktur vollständig zur Verfügung und der Annahmebereich für Nachmeldungen und die Abholung war eingerichtet. Auch der restliche Aufbau war sehr bald abgeschlossen. Einzig die Reinigung der Strecke zog sich etwas in die Länge, beim Herbstlauf hat man nunmal mit etwas Laub zu tun, sonst wäre es ja kein Herbstlauf. Die Beschaffung von Getränken und Werbematerial war auch flugs erledigt und so konnten wir deutlich vor der geplanten Zeit in die letzte Nachtruhe vor dem Lauf gehen. Abgesehen von einer Back-Aktion, der Kuchen für den Verkauf sollte ja frisch sein – aber auch das ist ja kein Drama, so ein Blechkuchen ist ja flugs gemacht und gebacken.

Da dieses Mal die Online-Voranmeldung recht gut lief, hatten wir deutlich weniger Nachmeldungen, und auch zusätzliches Personal bei der Eingabe – somit entfiel ein erkannter Flaschenhals. Auch der Trouble-Desk war diesmal auffällig ruhig, bis auf einige kniffelige Spezialfälle war nichts spektakuläres dabei, die üblichen defekten Startnummern aber alles sehr entspannt.

So konnte ich am Hauptlauf sogar noch fleißig Bilder machen, insgesamt etwas mehr als 2300 mal habe ich abgedrückt. Deutlich zu oft wie ich im Nachinein feststellen muss, dazu weiter unten etwas mehr. Schon sehr bald nach dem letzten Zieleinlauf konnte der Abbau hinter den Kulissen beginnen – wie üblich verlief das nochmals schneller als der Aufbau. Innerhalb weniger Stunden war alles Material verladen, verräumt und teilweise sogar schon retourniert. Durch die Verlegung des Erfassungsrechners in den Anmeldebereich konnte direkt in der Nähe des Druckers weitergearbeitet werden, während gleichzeitig der Abbau der Verkabelung am Zielkanal erfolgen konnte. Bis das demontiert war, konnte das Netzwerk schon wieder ein Stück weiter abgeschmolzen werden – so lange bis am Ende ein simples Cross-Over-Kabel für zwei Rechner erhalten blieb an denen noch gearbeitet wurde. Sämtliche anderen aktiven Komponenten wie Switches und APs konnten derweil schon abgebaut werden. Auch der Backup-Drucker war zu Hochzeiten zwar hilfreich, konnte aber für die wenigen Korrekturdrucke abgezogen werden. Nach und nach stapelten sich diverse Kisten für die Verladung ins Auto. Alles noch einladen – fertig.

Ebenso fix waren die Kollegen an anderer Stelle – nur noch wenige Einzelteile galt es zu verladen oder ins Lager zu schaffen. Somit konnte bereits deutlich vor der geplanten Zeit mit den Helferfeierlichkeiten begonnen werden. Natürlich freut das die Helfer, wenn sich nicht alles ewig hinzieht.

Etwas „Nachwehen“ gab es denn doch noch – das IT-Material musste ich bei mir auch wieder verräumen, auch wenn dank Vorsortieren das recht bald als „erledigt“ abgehakt werden konnte. Zudem noch den geliehenen Anhänger zurück bringen, aufgrund des matschigen Geländes musste der aber auch noch geschrubbt werden. Mein Auto hat dafür auch gleich eine Reinigung erfahren, damit es sich wenigstens lohnt.

Erstaunlich aufwändig gestaltete sich die Auslese der Bilder bzw. deren weitere Verwendung. Einerseits war es das schiere Datenvolumen, dass alleine anderthalb Tage Dauerlast am DSL-Anschluss benötigte um die Bilder auf einen Server zu übetragen. Ferner bringen Bilder einer Laufveranstaltung nichts, wenn sie nicht nach Startnummern gefiltert werden können. Mit meiner Erfahrung habe ich kurzerhand eine kleine Software in PHP geschrieben, die sich der Verwaltung und Ausgabe der Bilder annimmt. Auch dabei habe ich wieder etwas gelernt – diesmal über automatische Nachbearbeitung von Bildern auf der Kommandozeile, also praktisch im Blindflug. Mit einigen Hilfsmitteln kann man Bilder gleich passend rotieren lassen (ohne alles nochmal durch die JPEG-Mühle zu drehen). Die Verwaltung übernimmt dann eine Datenbank in der ich die Bilder direkt als Datensatz abgelegt habe, das erspart Probleme bei doppelten Dateinamen und die Verwaltung von Meta-Informationen ist auch deutlich leichter. Dennoch habe ich die folgenden Abende damit zugebracht die 2300 Bilder mit Nummern zu versehen, eine Multi-User-Fähigkeit muss ich noch einbauen, Ideen dazu habe ich schon. Auch am Layout muss ich noch ein wenig was machen, aber die Funktionalität stand ja erst einmal im Vordergrund.

Insgesamt wieder eine tolle Erfahrung die mein Leben bereichert hat, auch ich habe wieder einiges dazu gelernt – vor allem werde ich nächstes Mal weniger Bilder und dafür besser komponierte machen, Qualität schlägt Quantität. Wer Interesse an der Software hat,  kann sich ja einmal bei mir melden – ich denke wir sind nicht der einzige Verein, der viele Leute mit Kameras hat, aber keinen professionellen Bilderdienst engagiert.

Immer wieder eine Freude – Mailserver einrichten

Neue Dinge machen bekanntlich in der Regel richtig Laune und Spaß – sei es neues Auto, neue Wohnung, neues (Männer-)Spielzeug. Natürlich habe ich mich daher auch über einen neuen Server auf Arbeit gefreut. Aber bekanntlich ist es bei einigen Dingen mit der Anschaffung bzw. Bestellung und Lieferung nicht getan. Die neue Wohnung will bezogen werden, das neue Auto eingeräumt etc. – genauso ist es mit einem Server, auch der wird zwar voreingerichtet geliefert, aber diverse Details und Stellschrauben muss man noch anpassen.

Die gängigen Services die auf einem Linux-Server sind in der Regel schnell eingerichtet, sei es ein Datenbank-Backend in Form von MySQL oder MariaDB, Apache als Webserver ist in der Regel auch gut paketiert, PHP als Standard-Glue-Language ebenso. Damit ist LAMP zumindest einmal abgehakt. Die Kür sind dann noch die Konfigurationen von Apache für verschiedene virtual Hosts (also mehrere Domains auf einer IP), und ggf. die notwendigen Extras für PHP (z.B. Imagick für die automatisierte Bildbearbeitung, diverse Klassen aus dem PEAR-Verzeichnis wie Tools zum Excel-Export) – alles nicht wirklich kompliziert.

Einziger Knackpunkt der mich jedesmal nervt ist die Einrichtung des Mailservers. Zwar funktioniert der Server im ersten Moment auch ohne, aber spätestens beim Versand von Systemnachrichten oder beim Aufruf der Mailfunktion aus PHP kommt man um einen Mailserver nicht oder nur schwerlich herum.

Warum ist das so? – Zum ersten gibt es nicht den Mailserverprozess an sich – wenn man es mit Windows vergleicht wäre eine solche Lösung wohl etwas in der Art wie Exchange, das aber weit mächtiger ist als ein reiner e-mail-Server. Vielmehr müssen für eine Mailserver wie ihn der Nutzer wahrnimmt verschiedene Räder ineinander greifen – leider nicht nur zwei sondern eine ganze Menge mehr.

E-mail – als erstes denkt man hier einmal an das altbekannte SMTP (Simple Mail Transfer Protocol) – wie bei allem wo „simple“ dransteht ist es das leider nicht. Ebenfalls spielen noch andere Protokolle eine wichtige Rolle: IMAP (Internet Message Access Protocol) und POP3 (Post Office Protocol 3). Allein für diese drei Protocolle ergeben sich schon mal mindestens drei Serverprozesse. Auf POP3 kann man evtl. heute im Zeitalter von Flatrates verzichten, allerdings bringen ettliche IMAP-Server auch gleich die POP3-Funktionalität mit, schaden kann es auf keinen Fall, auch wenn der Abruf über eine Wählverbindung eigentlich nur noch eine Nischenlösung ist.

Was macht da eigentlich was und warum gibts da verschiedenes, es geht doch um ein einzelnes „Produkt“ bzw. eine „Dienstleistung“. SMTP dient der Weitergabe von e-mails – viel mehr ist darin gar nicht spezifiziert. Eine e-mail wird zwischen verschiedenen System damit weiter gereicht bis sie ihren Bestimmungsort erreicht hat. Das kann durchaus einmal mehrere Schritte umfassen, nachverfolgen kann man es in den Headern der e-mail, die man nicht immer angezeigt bekommt, aber jedes bessere Mailprogramm hat dafür eine Option. Wie das Zielsystem mit der Mail umgeht ist ihm überlassen. Früher war es üblich pro Benutzer einfach eine Textdatei zu nehmen und die Mails dort hintereinader einzutragen. Das sogenannte MBox-Format, für wenige und reine Textmails eine praktikable Lösung, beim heutigen Volumen (Attachments) und dem parallelen Zugriff von mehreren Endgeräten nicht mehr so ganz aktuell, auch weil es keine Ordner-Struktur unterstützt (oder nur auf Umwegen, die zwar „akzeptiert“ aber nicht wirklich standardisiert sind). Durchgesetzt hat sich als Ersatz das Maildir-Format, wie der Name schon andeutet gibt es da Directories also Verzeichnisse. Ferner wird für jede e-mail eine separate Datei verwendet. Je nach Dateisystem ist das nicht unbedingt platzsparend, aber Speicherplatz ist heute ja in Hülle und Fülle vorhanden.

In den allerwenigsten Fällen ist das Zielsystem der e-mail gleich dem verwendeten Endgerät (schon allein aus Gründen der Erreichbarkeit – ein e-mail-Server ist 24h am Tag erreichbar, das Endgerät im Zweifel nicht). Daher gibt es die Protokolle IMAP und POP3 um e-mails vom Mailserver abrufen zu können. POP3 ist dabei an der klassischen Post orientiert: Man holt seine Nachrichten aus der Box und was man dann damit macht ist nicht mehr Sache des Servers (es sei denn man setzt spezielle Optionen) – der Vorteil: Es bedarf keiner ständigen Verbindung, Nachteil: Habe ich ein Smartphone, einen Laptop, einen Rechner und will womöglich noch per Webmail-Interface auf meine Mails zugreifen, wird die Synchronisation haarig bis unmöglich. IMAP ist daher Stand der Technik – die Nachrichten verbleiben auf dem Server, die meisten Clients haben aber einen Offline-Modus um die Nachrichten vorzuhalten, wenn gerade keine Verbindung zum Server möglich ist.  IMAP und POP3 kümmern sich also um die „letzte Meile“ des e-mail-Verkehrs. Daher haben diese Protokolle auch schon immer eine Benutzer-Authentifizierung vorgesehen, denn ein Mailserver hat ja in aller Regel multiple Postfächer. SMTP hatte das anfänglich nicht, und das ist eine echte Design-Schwäche, die unter anderem für eine e-mail-Plage namens SPAM mit verantwortlich ist.

Soweit so gut, wir haben also 3 Prozesse, das sollte sich doch machen lassen oder etwa nicht? Naja, ganz so einfach ist es heute leider nicht mehr: Im vorangegangenen Absatz habe ich bereits über Authentifizierung gesprochen, also Zugriffsbeschränkungen. Damit nicht jeder einfach SPAM verbreiten kann, sollte kein Mailserver irgendwelche Mails, die nicht für ihn bestimmt sind annehmen und weiterleiten (sogenanntes offenes Relay) – früher war das eine praktische Sache, aber heute ist es schon fahrlässig bis strafbar so etwas zu machen – jeder der sich selbst um den Mailserver kümmert weiß wie viel SPAM angelandet wird (bei mir ca. 95% aller Zustellversuche!). Nun gut, Benutzername und Passwort das ist ja gängig – nur diese Information müssen sich dann auch noch die drei Prozesse teilen und sie sollten nach Möglichkeit synchron laufen. Dafür kann man das Benutzerverwaltungs-System des Zielhosts heran ziehen, das ist der klassische Weg. Die Serverprozesse arbeiten dann mit den Passwort-Mechanismen des Betriebssystems zusammen. Für kleine Server sicherlich eine gute Möglichkeit, aber was wenn man mehrere Domains verwalten möchte, die unterschiedliche Nutzer haben? Für jeden auch noch ein Systemkonto anlegen (mit allen Vor- und Nachteilen) das wird irgendwann anstrengend und schwer zu warten ist es auch noch. Auf alle Fälle aber bedarf es also eines vierten Teils, der sich um die Authentifizierung kümmert, das kann PAM (Plugabble Authentification Module) sein, oder ein andere Mechanismus. Sind wir also bei 4 Prozessen, die man beachten muss. Nicht mehr schön aber noch überschaubar …

Lustig wird es erst bei weiteren Maßnahmen, die man heute aber leider treffen muss: SPAM-Abwehr und Virenschutz. Jede e-mail muss beim Eingang also überprüft werden, dazu gibt es verschiedene Mechanismen. SPAM bekämpft man klassischer Weise mit Spamassassin – ein recht ausgefeiltes (und wiederum modulares) System zur automatischen Inhaltsanalyse (z.B. Abfrage von Blacklists bekannter SPAM-Schleudern, Bayes-Filter und noch einiges mehr), für die Viren und Trojaner gibt es Virenscanner (so viele man möchte, bzw. soweit es der Server von der Leistung hergibt). Bewährt hat sich im Linux-Umfeld mittlerweile der OpenSource-Scanner ClamAV. Sind wir numher also bei 6 Teilen die man zusammensetzten muss, von der jeweiligen Einzelkonfig mal ganz abgesehen. Damit das Filtern leichter geht und auch eine gewisse Fehlerbehandlung (Virenscanner schmiert ab, Spamassissin hängt, etc.) zu erreichen, gibt es die Glue-Software „amavisd“. Macht in Summe schon einmal 7 Prozesse die es zu beherrschen gilt. MySQL bzw. Maria-DB kommt ggf. noch dazu wenn man die e-mail-Adressenverwaltung und ggf. auch die Speicherung der e-mails in einer Datenbank realisieren möchte.

Weiter kann man die Komplexität noch nach oben treiben, wenn man Verschlüsselte Verbindungen wünscht…. Insgesamt also doch ein recht umfangreicher Brocken nur für e-mail, das ja eigentlich bei einem Webserver „nur“ im Hintergrund mitlaufen soll. Die Einrichtung von Clients oder einem Webmail-Interface ist hingegen recht leicht wenn die Infrastruktur einmal steht. Diese stützen sich in aller Regel auf die oben genannten Protokolle und Schnittstellen. Damit der Post hier nicht zu lange wird, mache ich in der näheren Zukunft mal einen zu einer Konfiguration die ich am Laufen habe und mit der ich recht zufrieden bin.

 

 

So bitte nicht – Schnittstellen

Es ist an der Zeit die lose Reihe mal wieder etwas weiter zu führen, mit einem Thema das mich die letzten Tage wiederholt beschäftigt hat: Schnittstellen.

In der IT-Welt beschreiben Schnittstellen verschiedenste Dinge – den meisten vertraut sind die Begrifflichkeiten aus der Hardware – hier erkennt man auch noch recht klar die Eigenschaft einer Schnittstelle, sie bildet die Grenze zwischen zwei Geräten, verallgemeinert von Systemen. Welches System an einer Schnittstelle andockt ist im ersten Moment unerheblich – die meisten Schnittstellen sind universell gehalten: Ob man eine Tastatur oder eine Maus in eine USB-Buchse einstöpselt ist im ersten Moment unerheblich. Die Schnittstelle ist so ausgelegt, dass über verschiedene Ebene hinweg eine Kommunikation nach einem bestimmten Muster stattfinden kann. USB beispielsweise gibt verschiedene Operations-Modi für unterschiedliche Anwendungszwecke – von der Maus als Eingabegerät über den GPS-Sensor bis hin zum Speichermedium. Die häufig verwendeten Hadware-Schnittstellen sind durch verschiedene Normen und Vorschriften festgelegt. In der Industrie gibt es zudem verschiedene Eigenentwicklungen für spezielle Zwecke, diese sind nicht zwingend so universell wie USB, aber sie erlauben auch weiterhin den Austausch von Informationen von einem System zu einem anderen hin. Im Fahrzeug z.B. per CAN-Bus: Dort meldet die Klima-Regelung an die Klima-Anlage die gewünschte Temperatur und die aktuelle Temperatur, der Klima-Kompressor wird daraufhin entsprechend in der Leistung geregelt.

Soweit einmal der Sinn und Zweck von Schnittstellen an anschaulichen Beispielen, aber mit der Hardware ist ja noch lange nicht Schluss. Vielmehr ist das ja noch alles nachvollziehbar und man kann sich unter der Definition einer Schnittstelle sehr leicht etwas vorstellen. Aber auf etwas höherer Abstraktionsebene existieren weiter Schnittstellen. Diese sind nicht so leicht erkennbar, aber dennoch vorhanden.

Jeder Programmierer der nicht absolut blutiger Anfänger ist, kennt die Erzeugung von wieder verwendbarem Code – nahezu jede Programmiersprache (von einigen Exoten einmal abgesehen) kennt den Begriff einer Funktion oder Methode. Das Prinzip dieser Konstrukte lehnt sich an der Mathematik an: Meist gibt man eine bestimmte, wohldefinierte Menge von Werten in eine Funktion hinein, die daraus etwas errechnet, etwas auslöst etc. in aller Regel gibt es auch noch einen Rückgabe-Wert (je nach Programmiersprache gibt es auch Möglichkeiten mehrere Werte zurück zu geben, entweder über den Stack oder einen reservierten, gemeinsam genutzten Speicherbereich, oft als Heap bezeichnet – das hier zu erläutern würde allerdings zu weit führen …). Wenn man das Prinzip der Funktionen einmal verstanden hat, sind diese einfach praktisch zu verwenden. Wichtig ist hierbei immer die Parameter-Reihenfolge (wie in der Mathematik auch) und je nach Programmiersprache auch noch der Werte-Typ der Parameter (starke oder schwache Typisierung: In Skriptsprachen wie PHP und Perl ist der Typ egal, in Java oder C müssen auch die Typen übereinstimmen – für beide Standpunkte gibt es gute Argumente, ich tendiere mittlerweile eher zu starker Typisierung und würde sie mir auch in PHP wünschen … aber auch das würde diesen Artikel leider sprengen). In ganz ähnlicher Weise lässt sich das auf objektorientierte Programmierung ausweiten. Auch dort gelten die gleichen Grundsätze, zusätzlich gibt es noch ein paar nette Gimmiks on top.

Gehen wir noch eine Abstraktionsstufe höher, dann sind wir bei Abläufen und Prozessen und eigentlich nicht mehr zwingend in der Softwarewelt verhaftet. Jeder Austausch von Daten über Systemgrenzen hinweg benötigt eine Schnittstelle. Egal ob die beiden Systeme nun Rechner sind, Menschen, Unternehmen oder sogar jede beliebige Kombination aus den vorgenannten. Überlegen Sie einmal inwiefern ein Rechner ihnen bestimmte Schnittstellen eröffnet und wann sie diese nutzen. Etwas Hirnakrobatik, aber wenn man es mal gemacht hat, sind viele Dinge am Rechner mit einmal logisch verständlich.

Was leider immer wieder schief geht ist die Spezifikation entsprechender Schnittstellen in dieser Abstraktionsebene. Oftmals sind sich die beiden Kommunikationspartner nicht bewusst, dass eine klar definierte Sprache/Syntax/Form der Kommunikation notwendig ist um Missverständnisse und Fehler zu vermeiden. Das beginnt meist mit solchen Sprüchen „wir bekommen dann eine Datei, da steht alles drin was uns unser Partner mitteilen möchte und was wir wissen wollen…“. Wie diese Datei am Ende aussieht ist bei solchen Sachen meisten leider erst einmal egal – dank der Intelligenz vor dem Monitor ist es dem Betrachter auch egal ob ein Textdokument als reiner Text, Word-Datei, Vektorgrafik oder als pixelbasierte Bilddatei vorliegt. Lesen und verstehen kann der Mensch das alles. Problematisch wird es wenn es dann an die Automatisierung geht. Da sind nicht alle Formate wirklich gut geeignet – jeder der einmal versucht hat aus einem abfotografierten Text wieder einen editierbaren Text zu machen weiß wovon ich spreche: Ohne Optial Character Recognition (OCR – Texterkennung) geht da gar nichts und selbst die ist meist nicht sonderlich fehlerfrei, von der Semantik der einzelnen Texteile und dem Layout mal ganz zu schweigen. Besser sind dann schon Excel oder Word-Dateien wobei die auch nicht immer kompatibel untereinander sind. Es gilt auch hier das alte Mantra: Je einfacher, je simpler um so besser. In der IT hat man für diverse Datentypen gut erprobte Ablage-Möglichkeiten entwickelt. Tabellen kann man recht gut in SQL oder CSV ausdrücken, wenn es etwas weniger stark strukturiert ist, kommen XML-Varianten in Frage.

Was lernen wir aus diesen Sachen?

Erstens: Es geht nicht ohne Schnittstellen, selbst innerhalb eines Programms gibt es in der Regel verschiedene Module oder Funktionen die Daten untereinander austauschen und so zum Gesamtsystem beitragen. Diese Schnittstellen sind in der Regel durch die verwendete Programmiersprache und die Programmierweise vorgeben (funktionale, prozedural oder objektorientiert).

Zweitens: Schnittstellen nach außen hin (egal ob Mensch oder Maschine) müssen klar erkennbar und definiert sein. Man denke hierbei immer an die Zukunft und überlege ob es vielleicht sinnvoll ist, an einigen Stellen bereits die Option für eine externe Schnittstelle zu schaffen, später nachrüsten ist immer schwierig und bestehende Schnittstellen verändern ist wie beim Auto plötzlich Kupplungs- und Gas-Pedal zu vertauschen: Die Konsequenzen sind bestenfalls amüsant, schlimmstenfalls gefährlich und es kostet sehr viel Nerven…

Drittens: Bereits bei der Planung von Systemen berücksichtigen welche Daten mit externen Systemen automatisiert ausgetauscht werden sollen und wie. Einerseits muss klar definiert sein, welche Daten an externe Systeme bereit gestellt werden sollen. Evtl. ändert sich durch solche Anforderungen der Erfassungsbedarf in der eigenen Anwendung/dem eigenen System oder lässt einigen Sachverhalten eine neue Priorität zukommen. Auch wichtig ist das Format – dieses muss für den Anwendungsfall geeignet sein, Bilder in Word einzufügen um sie daraus wieder zu extrahieren ist ungeschickt – einfacher geht es wenn man Bilddateien direkt verschickt. Ist die Information tabellenförmig, so kommen Excel oder die simple Variante CSV (comma separated values) in Betracht. Für komplexere und ggf. nicht immer einheitliche Datenaustausche kann man sich mit XML behelfen. Wobei immer zu beachten ist: In aller Regel steht hinter jeder XML-Datei und jedem System auch wieder ein relationales Backend (aus Performance-Gründen) – es lohnt also, ggf. einmal auch die Betreuer und Entwickler des Partner-Systems über deren Struktur zu fragen.

 

 

So bitte nicht – bad / worse practices – ein Kessel Buntes

Das die Welt nicht grau in grau ist (oder zumindest aktuell sehr zügig endlich der Frühling mit seiner Blüten und Farbenbracht Einzug hält), erfreut das Gemüt. Anders geartet ist da der Datenbank-Entwickler – wie jeder Informatiker ist er „kühl und dunkel“ zu lagern und zu halten, damit er optimal arbeitet.  Somit einher geht eine verstärkte Reaktion auf Restlicht (auch das des Monitors), allerdings messerscharf in schwarz/weiß oder zumindest in Graustufen. Spaß beiseite: „Ein Kessel Buntes“ ist eine finde ich recht treffende Umschreibung für das was landläufig oftmals als „Datenbank“ verkauft und verstanden wird. Leider wieder eine Praxis die auf Dauer nicht tragfähig ist.

Was ist der „Kessel Buntes“ und warum ist er keine gute Idee? – Generell bezeichne ich mit diesem Ausdruck nicht richtig getrennte und beschriebene Entitäten. Teilweise trifft das auch nicht richtig spezialisierte Entitäten. Immer wieder trifft man auf diese Art des Datenbank-Designs: Oftmals wird sie aus der Not heraus geboren, oder aus dem Missverständnis, dass eine Datenbank doch nur eine etwas bessere Excel-Tabelle sei. Eine Excel-Tabelle per se ist ja nicht einmal schlecht – sie bringt immerhin etwas Ordnung ins Chaos und ist für viele tagtägliche Anforderungen das flexible Werkzeug, wenn man mal eben eine Analyse machen muss, oder einfach nur eine „Kleinigkeit“ visualisieren soll. Eine Tabellenkalkulation ist hierzu sehr flexibel und bietet alle Möglichkeiten die man sich wünschen kann – von Layout bis hin zur Berechnung – nichts ist beschränkt. Genau diese Flexibilität ist es jedoch die bei größeren Projekten schnell vom Vorteil zum Hindernis werden kann. Mit der Flexibilität einer Tabellenkalkulation kann man sich oftmals die doch eher lästige tiefgehende Analyse eines Sachverhaltes für eine Datenbank sparen. Problematisch wird es, wenn Tabellenkalkulationen dann zum Allheilmittel erkoren werden. Ehe man es sich versieht werden da komplexe Matrizen aufgestellt, die dem menschlichen Benutzer die Information schön handlich aufbereiten. Nur die Maschinenlesbarkeit ist dann nicht mehr unbedingt gegeben, und selbst einfach Analysen im Datenbestand arten zur Sisyphus-Arbeit aus, vor allem wenn die Flexibilität voll genutzt wird und jede Matrix ein klein wenig anders aussieht.

Besonders ärgerlich aus Datensicht ist hierbei die Verquickung von Äpfeln und Birnen zu Obstsalat. Ich selbst durfte hierzu ein sehr schönes Beispiel einer gewachsenen Datenbank erleben: In einem Unternehmen gibt es verschiedene Aufträge, mit unterschiedlichen Qualitäten und Eigenschaften. So gibt es Aufträge die intern erzeugt werden und nur innerhalb von Abteilungen verrechnet werden, wenn überhaupt, zudem gibt es Aufträge, welche mit externen Elementen (auch als Kunden bezeichnet) abgewickelt werden. Nun war der Entwickler etwas faul oder es hat sich erst im Laufe der Zeit ergeben: Für die beiden Typen sind unterschiedliche zusätzliche Informationen notwendig. Initialer Weg um Zeit und Arbeit zu sparen: „Es ist ja nicht viel was da dazu kommt, wir fügen einfach Spalten an“. Recht zügig kann man in einer Datenbank der Einsteigerklasse (die sich tatsächlich auch noch als Datenbank bezeichnet) solche Änderungen realisieren. Die Rede ist hier von einem recht bekannten Produkt aus dem Hause „Winzig-Weich“. Problematisch ist bei diesem Produkt schon die Tatsache, dass Datenhaltung und Repräsentation scheinbar nahtlos ineinander übergehen. Für Anfänger ohne große Vorkenntnisse senkt das die Hemmschwelle doch ganz erheblich. Auch das ist ja für sich genommen eine löbliche Sache, nur auch dieses Produkt hat einen Einsatzbereich (der ist zugegebener Maßen recht breit) – wenn man über diesen hinaus wächst (und viele Projekte haben die Tendenz dazu), merkt man irgendwann recht heftig, wo es zwickt und kneift.

Nun haben wir eine aufgebohrte Datenbank-Tabelle – etwas, dass man mit ein klein wenig Aufwand auch in anderen Datenbanksystemen machen kann. Aus Erfahrung weiß ich nur zu gut, dass es immer wieder Fälle gibt, in denen man sich aus gutem Grund dafür entscheidet eine Spalte „Overhead“ zu spendieren, die nicht immer gefüllt wird, oder sogar nur in wenigen Fällen einen von NULL unterschiedlichen Wert hat. Man hat zwar dabei ggf. ein leichtes Bauchgrimmen, aber es gibt durchaus Szenarien in denen es weniger auf die Performance im Speicherverbrauch oder die absolute Performance ankommt, es aber mit den zusätzlichen Spalten recht schnell greifbare und brauchbare Ergebnisse gibt.

Das Ganze kann man jetzt noch weiter auf die Spitze treiben, in verschiedenen, nicht gegenseitig-exklusiven Geschmacksrichtungen (oder vielleicht doch besser Geschmacksverirrungen):

Man nehme einen weiteren Auftragstyp dazu, weil das aktuelle Projekt es erfordert: Da man in der Tabellen-Ansicht ja jetzt Felder hat die unbelegt sind und man die spezifischen Daten des neuen Typs ja auch noch speichern muss, fängt man kurzerhand an zu Tricksen und zu sparen: Bestehende Felder werden je nach Auftragstyp umgewidmet. Je nachdem was für einen Auftrag man gerade hat, bekommen die Felder jetzt eine Abhängigkeit, eine Semantik. Das macht die Arbeit bei den Masken recht einfach, auch eine tabellarische Übersicht ist kein Problem  – man muss nur wissen wie die einzelnen Felder jetzt zu interpretieren sind. Besonders spaßig ist dann natürlich die Verwendung falscher Datentypen, weil es halt doch nicht mehr so recht gepasst hat: Man kann auch ein varchar-Feld dazu verwenden um Datumsangaben oder Integerwerte zu speichern. Typecast gemäß Semantik und die Sache ist geritzt…

Die Performance und Wartbarkeit dieses Konstruktes kann sich der geneigte Leser dann mal selbst überlegen – vom Wechsel des Datenbank-Unterbaus hin zu einem professionellen Server mit ggf. sehr scharfer referenzieller Integrität wollen wir lieber einmal gar nicht träumen, diese wird dann oftmals auch einfach „geopfert“.

Zweite besonders zu empfehlende Möglichkeit die Performance noch weiter zu minimieren und dem ganzen ein unbeschreibliches „Geschmäckle“ zu verpassen: Die Unterscheidung der Typen ist nicht eindeutig oder klar umrissen, sondern kann womöglich sich zur Laufzeit noch ändern. Viel Spaß schon einmal beim Umsortieren und uminterpretieren der oben missbrauchten/umgewidmenten Felder. Auch Typecast-Mortale genannt (nicht unmöglich und bei heutiger Rechenpower fällt es nicht mal so sehr auf, zumindest für kleinere Datenmengen). Damit die Änderung leicht fällt bzw. weil man sich diesmal um die Felder und die notwendigen Anpassungen des semantischen Codes drücken will (wir erinnern uns: Das ist so sonderlich gut wartbar), macht man es wie in der Realität so häufig auch: Man verwendet „sprechende Schlüssel bzw. sprechende Identifikatoren“. Man kennt diese zur Genüge au vielen Bereichen – so lange der Benutzername beschränkt war auf 8 Zeichen, hat man einfach den ersten Buchstaben des Vornamens plus die 7 ersten des Nachnamens genommen. Wenn es doch mal zu Überscheidungen kommt, gab es eben fortlaufende Endziffern. Nicht schön aber es funktioniert. Ähnliches kann man teilweise bei Dokumenten aus Buchhaltungs-Systemen beobachten: Die ersten Zeichen definieren den Typus des Dokuments, die weiteren sind ggf. noch an das Datum gekoppelt oder gleich einfach fortlaufend. Gängig sind Angaben wie „ANG-xyz“ für Angebot Nr. xyz odr der LS-4711 für den Lieferschein mit der Nummer 4711. Weitere Beispiele kann man sich leicht vorstellen.

Die Performance wird allerdings besonders grottig, wenn man diese Typ-Information aus bestimmten Gründen nicht in einer separaten und indizierten Spalte (sehr einfach und dennoch effektiv sind z.B. Enumerations sofern die Datenbank mit dieser „Mini-Foreign-Key-Lösung“ umgehen kann) sondern einfach die gesamte Nummer in ein Varchar-Feld packt. Wenn man nun nach unterschiedlichen Typen filtern möchte, muss man doch nur die ersten Zeichen betrachten (vorzugsweise noch unterschiedliche Längen wie etwa: ANG und LS von oben, zusammen mit ANS für Kostenvoranschläge…). Mit dieser Technik bekommt man jede Datenbankengine ins Trudeln. Anti-Performance ist at its best …

Nun gut, genug gemault und Augen verdreht – woher der Ausdruck „Kessel Buntes“ kommt dürfte nun jedem klar sein: Man hat verschiedenste Obst (und ggf. auch Gemüse)-Sorten (im Datenbank-Bereich auch Entitäten genannt) in einer Tabelle zusammengeführt und über die Zeitachse das ganze gut durchgerührt und etwas ziehen lassen … Zeit dafür Lösungen zu präsentieren wie man es besser macht.

Oberstes Gebot bei der Modellierung bzw. dem Abbild der Realität: Entitäten trennen, wie Eiweiß und Eigelb. Beides gehört zwar zur Entität „Ei“ aber die Eigenschaften unterscheiden sich schon von der Farbe und dem weiteren Verwendungszweck beim Backen 😉 Daher: Wenn sich zeigt, dass eine weitere, vielleicht auf den ersten Blick sehr ähnliche Entität hinzugenommen werden soll, sehr sehr kritisch prüfen ob man diese unbedingt in das bestehende Schema „pressen“ muss. Im ersten Moment mag es zwar mehr Arbeit sein separate Entitäten zu verwalten, aber die Erfahrung zeigt: Jedes Datenbankschema hat auf die mittlere bis lange Frist die Tendenz sich weiter auszudifferenzen und detaillierter zu werden. Also besser gleich von Anfang an verschiedene Tabellen verwenden (ich werde auch noch einen ausführlichen Beitrag zum Thema „one true lookup table – OTLT“  verfassen) – diese im Zweifel per UNION erst einmal wieder zusammen zu führen (was nicht immer vermeidbar ist, oder zumindest für einen Teil der Daten sinnvoll sein kann) ist der bessere Weg.

Im letzten Absatz ist es schon angeklungen, ein Problem das man häufiger hat: „Aber die Dinger aus der Realität sind doch zu 80% ident …“ – in der objektorientierten Programmierung ist das ein klarer Fall für die Verwendung von Vererbung ggf. in Kombination mit abstrakten Klassen. Die übergeordnete Klasse stellt die gemeinsame Basis samt Funktionen bereit, und die spezialisierten Klassen kümmern sich um die 20 verblieben Prozent der Details. In einer relationalen Datenbank klappt dieser Ansatz nicht direkt. Hier muss man auf die Kombination von Geschäftslogik und einzelnen Tabellen zurück greifen: In der Geschäftslogik verwendet man den objektorientierten Ansatz wie gerade beschrieben, in der Datenbank führt man Surrogate ein, die es erlauben vom Kleinen auf das Größere zu schließen – dabei muss man ggf. aufpassen, dass keine Doppeldeutigkeiten entstehen (teilweise sind diese jedoch auch wünschenswert, das muss man situativ entscheiden) gibt. Auch bekannt ist das Konzept unter dem Namen „Vererbung für Arme“. So bekommt man zwar auch ein wenig Overhead, aber die Struktur bleibt klar erkennbar und man braucht nicht erst noch eine Tabelle die einem sagt, wie jetzt welcher Wert zu interpretieren ist.

Was auf keinen Fall eine Option sein darf, ist die Integration von Typinformationen in ein anderes Feld – diese Information muss man wo immer möglich in separate Felder auslagern, die man im besten Fall noch mit einer Referenz (Fremdschlüssel) auf eine andere Tabelle mit entsprechenden Meta-Informationen absichert. Sonst passiert es leicht, dass der Benutzer (aus Schusseligkeit oder gar mit Intention) einen neuen Typ einführt der gar nicht definiert ist (z.B. ein Tippfehler der Form „AND“ anstelle „ANS“) – welche Semantik dann greift bzw. welch kuriose Fehlinterpretationen und Fehlermeldungen dann auftreten können liegt im Bereich der Spekulation und der Admin-Belustigung. Über die notwendigen Operationen der String-Extraktion denkt man in diesem Fall auch besser nicht nach, geschweige denn daran wie häufig diese Operation angewandt werden muss…

Fazit: Es mag verlockend sein, eine Datenbank möglichst flexibel und „platzsparend“ zu gestalten, wie man es auch in einer Tabellenkalkulation machen würde. Aber die gewonnene Sicherheit ist absolut trügerisch und der Performance und Wartbarkeit tut man sich mit einem Kessel Buntes mit absoluter Sicherheit keinen Gefallen. Besser gleich überlegen ob das wirklich notwendig und sinnvoll ist, so klein das Problem aktuell auch sein mag – die Wahrscheinlichkeit, dass man irgendwann einen großen Scherbenhaufen hat ist erheblich vergräßert und dann ist nichts gewonnen, aber viel verloren.

Update-Erfahrungen DELL Streak

Nun habe ich mein geschätztes DELL Streak als Smartphone ja schon eine ganze Weile … liebevoll auch Backstein, Army oder „back to the roots-phone“ genannt. Immerhin ist das Ding nicht gerade ein Leichtgewicht, aber es hat schon seit Beginn einen schönen großen Bildschirm. Anfänglich war das etwas arg groß, aber im Vergleich zu den aktuellen Geräten braucht es sich nun nicht mehr zu verstecken – auch die Geräte von Samsung sind ja deutlich größer geworden (Websites im Miniformat lassen sich nunmal schlecht lesen).

Einziger Wermutstropfen: Es gibt keine offiziellen Updates mehr für das Gerät und die Bedienung des alten Androids 2.2.2 war doch reichlich hakelig, von diversen unmotivierten Abstürzen in der letzten Zeit einmal ganz zu schweigen. Ein neues Gerät wäre eine Lösung, zumal es ja mehr Leistung bieten würde…. auf der anderen Seite: Warum ein neues Gerät wenn ich für das bestehende doch die ganze Infrastruktur samt Ladekabel und Fahrzeug-Halterung habe …

Schon länger steckte mir ja die Idee in den Fingern das Ding software-mäßig aufzubohren – also ein Jailbreak oder ein Rooting zu machen. Nun habe ich mir endlich einmal die Zeit genommen. Das Ergebnis ist noch nicht ganz das was ich erwartet habe – immerhin war die alte Version schön deutsch und ich hatte mich an diverse Dinge gewöhnt.

Mit ein wenig Geduld bekommt man über ein Recovery-Image der Version 350 (so etwas wie ein Live-Linux nur für Android, das aber fest auf das Gerät geflasht wird) auch die Möglichkeit das letzte offizielle Update von DELL zu installieren. Soweit zumindest die Theorie – in der Praxis sind die Ergebnisse interessanter: Das Update wurde für den Koreanischen Markt (passenden zu den aktuellen politischen Spannungen dort …) vor etwas mehr als einem Jahr veröffentlicht … Leider ohne Support für die Deutsche Sprache und mit der Installation komplett in Koreanisch! Mit ein wenig Mühen bekommt man es dann auch wieder zumindest auf Englisch – da finde ich mich dann ohne Probleme zurecht …

Für alle die wie ich immer ein wenig Scheu vor den etwas technischen Beschreibungen in den diversen Foren haben: Wenn man sich einmal ein wenig mit dem Ablauf auseinander gesetzt hat ist alles halb so wild: Auf dem Telefon befinden sich mehrere „Betriebssysteme“, ein wenig ist das vergleichbar mit den unterschiedlichen Kerneln die man unter Linux schon beim Start auswählen kann – wer wie ich noch Kernel selbst kompiliert hat, der weiß was ich meine – nur hatte man beim Rechner etwas mehr Eingriffsmöglichkeiten. Zusätzlich zum „produktiven“ System gibt es noch ein Recovery-System das auf einer separaten Partition vor sich hinschlummert – das braucht zwar Platz, aber Speicherplatz kostet heute ja fast nichts mehr und so ein Rettungsanker macht die Sache in vielen Fällen doch etwas leichter.

Leider sind diese Recovery-Systeme oftmals vom Hersteller vorgegeben und wehren sich auch gerne mal dagegen, dass der Benutzer damit Schindluder treibt. Bei einem Rechner würde man jetzt einfach einen USB-Stick mit alternativem Image verwenden, oder eine andere CD zum Booten (etwa ein PartedMagic oder ein Knoppix) einlegen. Beim Smartphone klappt das nicht … Aber dafür gibt es andere Wege und USB ist auch hier der Schlüssel. Über das Fastboot-Protokoll und dem entsprechenden Tool (gibt es für Windows und für Linux) kann man das Recovery-System von extern ersetzen. Je nachdem welches Recovery-System man installiert, stehen einem unterschiedliche weitere Möglichkeiten offen – bei den Herstellern ist man meist eingeengt, dafür gibt es zumindest während der Garantie auch entsprechend Support. Mit alternativen Revocery-Images lassen sich aber auch ältere Geräte auf Stand bringen.

Die wichtigsten Infos gibt es gesammelt im sehr aktiven xda-devolpers-Forum bzw. deren Wiki. Unter anderem gibt es eine sehr brauchbare Anleitung zum Flashen und den damit verbundenen Startmodi, Angaben zur DELL-spezifischen  Versionierung (ein Kessel Buntes: Für jede Region und für jeden Anbieter gibt es verschiedene modifizierte Systeme, auch Branding genannt – nur ärgerlich, dass man irgendwann keine Updates mehr erhält) und natürlich eine Liste mit offiziellen und inoffiziellen (community-basierten) Versionen.

Nun war ich ja schon mal den Weg des Updates gegangen – und hatte dabei die Klippe mit den koreanischen Zeichen erwischt (man lernt manche Dinge nur auf die harte Tour) – aber so richtig wollte da keine Freude an dem neuen System aufkommen – immerhin war es ja auch schon wieder etwas älter und hatte auch noch ein koreanisches Branding (was unter anderem im App-Store mit deutschen Apps wie Tagesschau.de ein wenig Hindernisse aufwirft). Außerdem waren einige Funktionen verschütt gegangen, etwa die Konfigurierbarkeit des Launchers (DELL Stage) – sicherlich hätte man sich daran gewöhnen können oder irgendwo in den Tiefen des Systems wohl auch die Möglichkeit zur Einstellung gefunden.

Aber mit dem ohnehin angefertigten Backup lag natürlich noch eine andere Option auf der Hand – nachdem es von DELL ohnehin keinen Support mehr geben wird, könnte man ja auch mal nach weitergehenden Alternativen suchen und vielleicht einmal zur aktuellen Generation von Android aufschließen. Der Weg zurück zum Ursprung war ja keineswegs verbaut – vielleicht ein wenig Arbeit, aber im Zweifel hätte man einfach die alte Recovery-Version wieder einspielen können und dann das System wieder in den Ausgangszustand zurück bekommen können.

Also nicht lange fackeln, wenn man schon mal dabei ist. Also habe ich mir gleich mal die aktuelle Entwicklung „Longhorn“ angeschaut. Mit der gewonnen Routine war das Installieren dann bei weitem nicht mehr so aufregend wie das Aufspielen der koreanischen Version, wenn man mal verstanden hat was da grob abläuft, und wo man hinpacken muss ist mir zumindest gleich mal viel wohler. Ausgangspunkt war für mich das Recovery-Image „Streakdroid“ (ganz unten in der Liste). Damit lassen sich noch mal sicherheitshalber Backups anstoßen, bevor man mit dieser Anleitung weiter macht.

Das dauert eine gefühlte Ewigkeit und zwischenzeitlich dachte ich schon ich hätte wohl eine etwas längere Nachtschicht vor mir um wieder ein funktionsfähiges Telefon zu bekommen. Aber Geduld zahlt sich aus, am Ende startet das Gerät doch durch und zeigt den Startbildschirm an. Das wäre mal geschafft. Etwas lästiger ist das Rückspielen der ganzen persönlichen Einstellungen. Praktischerweise funktioniert das mitgelieferte (und vorher natürlich anzuwendende) Backup-Tool von DELL in Kooperation mit Nero auch auf dem modifizierten Gerät. Damit lassen sich unter anderem die Kontakte, SMS-Nachrichten, Hintergrundbilder und einiges mehr nach der notwendigen Totalbereinigung wieder zügig auf das Gerät schaffen. Sowas lob ich mir echt. Mühsam ist hingegen die Installation der verschiedenen Apps diese muss man einzeln wieder anstoßen (ein wenig fühle ich mich wie früher in den Sommerferien, als ich regelmäßig meinen Rechner frisch aufgesetzt habe – genauso wie damals fliegen hier einige Apps aus der Sammlung raus, die ich ohnehin nicht mehr benötigt habe – Frühjahrsputz nennt man das).

Bis jetzt bin ich echt super zufrieden mit der Leistung der modifizierten Software, der HOLO-Launcher gefällt mir mit seinen Einstellmöglichkeiten richtig gut. Ein paar Sachen wie etwa das „Start-Menü“ für wichtige Funktionen des Handys (Kontakte, SMS, AppSammlung/Menü) weiß ich schon jetzt echt zu schätzen – da kann DELL Stage einfach nicht mithalten. Man muss aber auch zu Gute halten, dass mittlerweile einige Jahre Entwicklung im Smartphonebereich ins Land gegangen sind. Jetzt heißt es einfach abwarten wie sich das Gerät im täglichen Leben schlägt. Es war zwar Aufwand und ein wenig Überwindung gefragt um in das Neuland vorzustoßen, aber es gefällt mir deutlich besser als nur wegen einer Software ein neues Gerät zu kaufen.

 

 

 

So bitte nicht – bad / worse practices

Nachdem ich mich immer wieder mal grün und blau (und nicht blau weil ich beim THW tätig bin) über diversen Software-Design-Schwachsinn ärgere, habe ich mich entschlossen in loser Folge immer einmal wieder eine schlechte Art der Programmierung / Modellierung und natürlich auch Wege wie man es besser machen kann vorzustellen.

Für heute will ich erst einmal mit einigen Grundlagen beginnen, die sicherlich nicht nur für die Programmierung und Software-Entwicklung hilfreich sind, sondern für jeden der ein Projekt in irgendeiner Form betreut.

Ad 1) Klar festlegen was ich eigentlich will – jeder hat es sicherlich schon mal erlebt: „So hab ich mir das aber nicht gedacht gehabt …“ Die Ursache ist meist leicht gefunden: Es mangelt an klarer und eindeutiger Vorgabe – da gehört hinein was man will, aber auch was man gerade nicht will. Es ist sicherlich nicht immer leicht alles möglichst eindeutig und klar zu beschreiben, aber alleine wenn man sich darum bemüht ist schon eine große Menge Missverständnissse aus dem Weg geschafft

Ad 2) Klare Definitionen und einheitliches Vokabular: Jeder Mensch ist einzigartig, mit all seinen Vorlieben, Stärken, Schwächen und Erfahrungen. All diese Einflüsse prägen uns und haben eine Auswirkung auf die Rezeption und Reaktion gegenüber unserer Umwelt. Daher ist es keineswegs selbstverständlich das jeder unter einen Begriff anfänglich genau das gleiche versteht und ihn genauso abgrenzt wie ein anderer Mitarbeiter. Daher klar festlegen was unter einem bestimmten Begriff zu verstehen ist, und was nicht – es mag lästig erscheinen jede Entität und deren Bedeutung im Prozess-Zusammenhang einmal ausführlich zu beleuchten und zu beschreiben, aber es macht im weiteren Verlauf das Leben deutlich leichter. Wichtig ist hierbei: Jeder muss das Vokabular auch entsprechend anwenden, was abgestimmt wurde ist fest, ein „aber ich hab doch eigentlich 0815 anstelle 4711 gemeint“ ist ein absolutes no-go

Ad 3) Kenne deine Werkzeuge: Nicht jeder in einem Projekt muss mit jedem Werkzeug umgehen können – eine Führungskraft muss nicht zwingend mit einem Code-Editor und Compiler hantieren (es schadet nichts wenn sie sich dennoch einmal damit auseinander setzt), aber das tagtägliche Handwerkszeug mit den Routine-Funktionen muss nahezu blind bedienbar sein. Dazu muss auch klar sein: Für welchen Zweck welches Werkzeug? (Das kann von Projekt zu Projekt ein wenig schwanken, auch hier hilft es ggf. niederzulegen welche Mittel zur Verfügung stehen und für welchen Zweck benutzt werden sollen). Wichtig ist gerade in der Software-Entwicklung der sichere Umgang mit der persönlichen Entwicklungsumgebung (da kann jeder Entwickler verwenden was er für richtig hält, es sei denn es gibt zwingende Vorgaben. Gerade im Code ist es aber egal ob jemand eine vollwertige IDE wie Netbeans, KDevelop, Eclipse verwendet oder doch lieber einen schlichten Text-Editor mit ein wenig Syntax-Highlighting. Ebenso gehört der Umgang mit Team-Werkzeugen wie e-mail, Versionskontrolle, Bugtracker, Requirement-Management etc. zum Routine-Werkzeug. Hier muss ggf. geübt werden, aber nach einer gewissen Zeit darf es kein Bremsklotz mehr sein. Für die Arbeit am Rechner empfiehlt sich auch ein flüssiges Tippen und Arbeiten mit reduziertem Mauseinsatz (Shortcuts).

Ganz wichtig: Die ganzen Punkte da oben gelten für alle im Projekt, Neueinsteiger oder auch weitere Führungsebenen muss man da etwas heranführen und klar kommunizieren wie der Hase läuft. Absolut hinderlich ist es, wenn Leute die sehr viel an einem Projekt mitwirken diese einfachen Regeln nicht gebacken bekommen. Das geht auf die Nerven und somit auf die Performance des restlichen Teams.

So weit mal für den Anfang, wie geschrieben: in loser Folge kommen weitere Grausamkeiten der Software-Entwicklung (alles leider Dinge die man immer wieder erlebt, auch das oben ist keineswegs aus den Fingern gesaugt).

Ist sachlogisches und strukturiertes Denken schwer oder gar gesundheitsgefährdend?

Ich glaube ich habe vor einigen Stunden die Klimax bezüglich einer weiteren Episode meines Lebens überschritten. Nachdem sich meine berufliche Entwicklung über die letzte Monate in verschiedenen Akten voran gekämpft hat, ist es nun zur Katastrophe gekommen. Schon seit einiger Zeit, bemerke ich an mir deutliche Zeichen von Überlastung und ständigem Stress. Spätestens wenn meine Haut beginnt sich mit Veränderungen zu äußern, weiß ich, dass ich etwas langsamer machen sollte oder gerade mal wieder eine stressige Phase ist. Das ist für mich nichts Neues, aber wenn es über mehrere Wochen anhält und partout nicht besser wird, dann ist wirklich etwas faul.

Doch zurück zum Thema, was genau ist das Problem? Als ich vor etwas mehr als zwei Jahren meinen Job begonnen habe, war bereits klar: Es geht um eine webbasierte Datenbank. Also durchaus ein Thema in dem ich schon Erfahrungen sammeln konnte – angefangen mit den ersten Schritten in PHP und Administration zu Schulzeiten, bis hin zur intensiven beruflichen Verwendung im zweiten Praxis-Semester. Abgerundet natürlich durch immer weitere Verfeinerungen und Lerneffekte aus Fehlern oder anderen Entwicklungen.

Erste Aufgabe war es eine bestehende Datenbank für den Übergang ins Netz vorzubereiten. Soweit halb so wild, nur sollte sie ja auch insgesamt besser werden. Also habe ich mir mit allem Sachverstand und logischer Analytik das bestehende System vorgenommen und bin fast aus allen Wolken gefallen. Das System war völlig ausgereizt und bestand aus mehr Flicken und Workarounds als ich es mir zu träumen gewagt hatte. Mit jedem weiteren Analyseschritt wurde mir klarer, dass die bestehenden Performance-Probleme kein Problem des Datenbankservers oder der verwendeten Programmiersprache (Access und VBA) waren, sondern das hier ein wesentlich grundlegenderes Problem bestand: Die Modellierung war im besten Falle unpräzise oder sehr ungeschickt ausgeführt (Entitäten nicht getrennt oder über die Anfangsbuchstaben in einem varchar-Feld unterschieden => warum die Performance hier mau ist, sollte klar sein: Wenn ich erst jedes Teil in einer Kiste untersuchen muss um festzustellen ob es aus Holz oder Stein gemacht ist, dann dauert es länger, als wenn man von Beginn an Stein und Holz in getrennte Kisten packt).

In den vergangenen Jahren habe ich also nichts anderes gemacht als die Datenbank von Grund auf neu zu entwickeln. Dabei habe ich alle Register meines Könnens gezogen, sicherlich nicht an jeder Stelle sofort mit den brilliantesten Ideen.

Leider musste ich feststellen, dass analytische und logische Arbeitsweise nicht immer das sind, was der Anforderer eigentlich möchte. Aber ich kann da nicht so ganz raus aus meiner Haut: Ich bin stets darum bemüht ein möglichst gutes und langlebiges Produkt zu entwickeln. (Das heißt nicht, dass ich nicht auch mal für eine kleine Arbeit oder automatisierte Korrektur ein Quick’n’Dirty-Skript schreibe – passendes Werkzeug für die jeweilige Aufgabe – auch das ist eine Kunst). Durch die Analyse und meine Stärken im organisatorischen Bereich (ja es zahlt sich gelegentlich auch aus, in der Jugendarbeit tätig gewesen zu sein) in Kombination mit den Erfahrungen und Techniken die ich während der Diplomarbeit entwickelt habe (ja GQM klingt zwar hoch gestochen, aber es ist ein sehr schöner Ansatz), stand relativ schnell eine grundlegende Struktur fest: Einerseits sollte das System überwachen, welche Aufgaben/Arbeiten zu erledigen sind, andererseits diese auch mit den notwendigen Details wie Arbeitszeit, Materialverbrauch, Erkenntnisse usw. dokumentieren. Für mich eine klare Sache: Vom Symptom oder der Aufgabe in mehreren, wohl dokumentierten Schritten. Ein absoluter Standardablauf wie er in jedem CRM/ERP-System tagtäglich mehrere Milliarden Mal auf der Welt gelebt wird.

Wichtiges Kennzeichen dieses Ablaufs ist die Orientierung an der Kostenrechnung – zu Beginn erstellt man einen Plan, in diesem sind geplante/abgeschätzte Werte zu finden. In der Dokumentation findet sich dann was tatsächlich passiert ist – und man erhält einen Einblick ob man gut geplant hat, oder ob man möglicherweise Korrekturbedarf hat.

Soweit die graue Theorie wie man sie aus der Hochschule bereits kennt oder auch in der Literatur des häufigeren findet. Die Realität ist leider etwas anders als man sich das vorstellt. Zum einen sind die Zusammenhänge oftmals nicht wie im Lehrbuch sondern etwas verzwickter. Klar, denn im Lehrbuch geht es um das Konzept im Ganzen, da sollen die Beispiele auf möglichst wenigen Seiten möglichst klar und gut verständlich sein. Die Ideen und Prinzipien dann zu erweitern ist für den Fachmann dann nur ein kleinerer Schritt in die entsprechende Richtung.

Richtig problematisch wird aber der Faktor, den man bis dahin als Techniker überhaupt nicht berücksichtigt hat – auch als Layer 8 oder HAF (human acceptance factor) genannt. Nun war ich eigentlich der Meinung (und habe das auch so vielfach erlebt) dass man es in der Geschäftswelt und bei den Vorgesetzten mit entsprechend fähigen (größtenteils ja sogar studierten) Menschen zu tun hat. Denen sollte eine gewisse Abstraktionsfähigkeit und die Fähigkeit logisch zu denken und strukturiert zu arbeiten doch eigentlich nicht fremd sein. Sicherlich, es gibt auch Studiengänge im künstlerischen Bereich, aber dieser Menschenschlag ist seltener in einem technisch ausgerichteten Unternehmen zu finden. Im konkreten Fall weiß ich sogar, dass es nicht zutrifft, sondern eine technische Ausbildung und ein Studium vorliegt.

Leider scheint logisches und strukturiertes Denken, Handeln und Arbeiten aber nicht mehr so recht in Mode zu sein – über viele Dinge macht man sich heute keine Gedanken mehr, weil man es nicht mehr muss – teilweise ist das von Vorteil (wer schleift heute noch ein papiernes Telefonbüchlein mit sich herum – im Handy ist doch alles gespeichert). Allerdings verleitet das Ganze auch an anderer Stelle zu einer gewissen Schludrigkeit, es ist ja eben alles on-the-fly möglich, das macht man dann halt irgendwie nebenher mit. Vorbereitung und Planung von Arbeiten ist heute nicht mehr en vogue oder es gibt im produzierenden Gewerbe mittlerweile Spezialisten die sich minutiös um die Gestaltung von Abläufen vorab kümmern und alle Möglichkeiten ausloten (z.B. bei der Optimierung der Arbeit am Band bei den Automobilherstellern). Im Service-Umfeld ist das meist etwas schwieriger zu leisten, aber auch hier kann man durchaus mit klaren Abläufen und sauber definierten Schnittstellen die Arbeit effektiver gestalten – immer unter der Bedingung, dass man das auch möchte. Denn eine vorgegebene Struktur (und in gewisser Weise macht eine Datenbank ja nicht anderes) verhindert oftmals das Arbeiten „nebenher“ – alles ist klar geregelt.

Besonders schwierig wird es, wenn bisher mit Excel-Listen oder Datenbanken „light“ (aka Access) gearbeitet wurde, in denen die Struktur nicht übermäßig wichtig war und die eben auch auf Veränderungen recht flexibel zu sprechen waren. Die Mitarbeiter sind es somit nicht (mehr?) gewohnt klar Angaben zu machen, es findet sich ja ohnehin irgendwie alles in einem großen Haufen, man muss nur ein wenig danach „wühlen“/“blättern“/“filtern“. Das diese Form der Datenerfassung nicht für automatisierte Datenauswertungen tauglich ist, liegt klar auf der Hand, zumindest für denjenigen der schon einmal aus der Form geratene Excel-Tabellen mit doppelt genutzten, gesplitteten und zusammengeführten Tabellen in der Hand hatte. Im Gegensatz dazu sind Datenbank-Tabellen definitiv „flach“ – die in Excel erzeugte Mehrdimensionalität wird in der Datenbank durch den Mechanismus der Fremdschlüssel abgebildet – eine 1:n Beziehung zweier unterschiedlicher Entitäten bedeutet immer auch den Einsatz von zwei Tabellen.

Aber bereits an der Unterscheidung von Objekten und den damit verknüpften Entitäten scheitert es oftmals – da werden ganze Pakete als ein „Datensatz“ bezeichnet, egal wie viele unterschiedliche Entitäten beteiligt sind (aus Benutzersicht vielleicht noch nachvollziehbar, aber nicht wenn man sich ein wenig detaillierter damit auseinander setzen will/muss: Die Identifikation von Abläufen und den daran beteiligten Artefakten ist nicht immer einfach, aber zur sauberen und maschinenlesbaren Aufbereitung ist sie leider unerlässlich.

Da es mir trotz mehrerer Anläufe nicht geglückt ist (es ist teilweise nicht einmal gewünscht sich auch nur etwas näher erklären zu lassen, da müsste man ja womöglich mitdenken und die graue Masse zwischen den Ohren mal wieder umquirlen) den Sinn und Zweck dieser Analysen und der strukturierten Vorgehensweise näher zu bringen, habe ich es jetzt erst mal aufgegeben – kein schönes Gefühl muss ich sagen, man fühlt sich vielmehr ins Mittelalter zurück versetzt: Der Chef als allmächtiger Papst, der über jegliche Analytik und naturwissenschaftliche Argumentation erhaben ist und sie nach Gutdünk sogar für „nicht zulässig“ erklären kann.

Mir persönlich ist nicht klar, wie man sich heute als Mensch mit einem technischen Hintergrund nicht auf eine logische Analyse (die wie beschrieben ja notwendig ist für das Ziel der automatischen Auswertung) einlassen will oder kann. Läuft da evtl. in der Bildung mit Laisez-Faire schon etwas falsch? Oder wird Mathematik und Logik in der Gesellschaft mittlerweile wieder als „böses Teufelszeug“ gesehen, vor dem man sich schützen muss  – vielleicht weil es immer nur schlechte Noten gab/gibt?

Insgesamt bleibt mir nur die Frage des Artikels wie folgt zu beantworten: Logisches Denken und strukturiertes Arbeiten ist nicht gesundheitsschädlich – einzig das Erläutern und Näherbringen bei betonharten, festgefahreren Strukturen (das haben wir schon immer so gemacht) mit dem Ziel der Verbesserung kann derart nervenaufreibend sein, dass der damit verbundene Stress für den Logiker zum echten Problem werden kann.

 

Wenn der Postmann zweimal klingelt – MBox, Thunderbird, Maildir und IMAP

Na da hatte ich mir doch mal wieder eine nette kleine Bastelaufgabe gestellt, als ich einem Kumpel versprochen hatte ihm bei seinen e-mail-Problemen ein wenig zu unterstützen. Ausgangssituation war ein Rechner-Zuwachs bzw. die Nutzung von Smartphone, Laptop und Festrechner. Den e-mail-Account hatten wir schon vor ettlichen Jahren eingerichtet – das war schon so lange her, dass ich mich kaum daran erinnern konnte. Ein deutlicher Hinweis auf das Alter war die Verwendung des Post-Office-Protokolls Version 3 (kurz POP3) – damals noch die Standard-Technik zum Abruf von Mails. Bisher war mein Kumpel mit dem System recht gut gefahren und auch Thunderbird als Mail-Client kommt ja problemlos mit POP3 zurecht.

Was sind die Rahmenbedingungen für POP3 und warum wird es heute nicht mehr verwendet oder besser gesagt nur noch da wo es nicht anders geht? – Sicherlich nicht weil es einfach nicht mehr „in“ ist. Vielmehr war zu den frühen Zeiten des Internets (die ich noch erleben durfte) eine unbeschränkte Verbindung ins Netz nicht gegeben (ja es gab eine Zeit vor den Flatrates und DSL – heute kaum mehr vorstellbar) – damals wählte man sich per Modem ins Netz ein – bezahlt wurde nach Minuten-Tarifen. Daher war es wichtig die Leitung möglichst effektiv auszulasten, zumal man in der Regel mit nur einem Anschluss pro Haushalt in der Zeit nicht telefonieren oder Faxe schicken konnte (ISDN war damals das Zauberwort – zwei Kanäle, drei Rufnummern gab es standardmäßig – ich gehörte leider nicht zu den glücklichen Nutzniesern). Nach dem Aufbau der Verbindung holte man seine Mails ab, surfte diverse Seiten an und trennte die Verbindung wieder wenn man sie nicht benötigte. POP3 unterstütze genau diese Funktionalität: Alle Mails aus der Mailbox nacheinander herunterladen auf den eigenen Rechner und dann war erst mal Ruhe. E-mail war ja schon schnell, aber dennoch musste man damals nicht sofort bei jeder e-mail informiert werden (was ich auch heute nur sehr bedingt brauche). Man beantwortete die Mails und sammelte sie, danach baute man die Verbindung für den Versand wieder kurz auf und speißte die Mails ins Internet zur Verteilung ein.

Die Vorteile liegen klar auf der Hand: Die damals wertvolle Bandbreite und Übertragungszeit wurde so möglichst effektiv ausgenutzt. Klar sind aber auch die Nachteile: Verteilte Nutzung von e-mails auf mehreren Rechner war nicht vorgesehen, auch wenn man die Mails in der Mailbox belassen konnte (die dann irgendwann überlief und man keine Mails mehr empfangen konnte – damals waren 5-10MB Mailspeicher schon sehr viel, aber es wurde ja auch nicht jeder Sch… per e-mail weiter verteilt). Schon zu meinen ersten Gehversuchen existierte das konkurierende Protocol Internet Message Access Protocol (IMAP) – das löste das Problem mit der Synchronisation durch eine zentrale Speicher-Instanz. Leider zu dem Preis, dass man in der Regel eine permamente Internet-Verbindung benötigte oder zumindest eine zum e-mail-Server. Gegenüber POP3 war IMAP ein deutlicher Fortschritt – Serverseitige Filterung war ebenso möglich wie verschachtelte Unterordner in der Mailbox (alles was man heute als nahezu selbstverständlich wahrnimmt) – ursprünglich entwickelt für den Mailverkehr innerhalb von Firmen (die schon damals oftmals eine Standleitung hatten). Indirekt populär wurde das Protokoll durch die Entwicklung von Webmail-Services – auch meine erste e-mail-Adresse nutze ich auf diese Art und Weise, da sie unabhängig von weiterer Software war, die auf Schulrechnern ohnehin nicht installiert werden durfte. Als Schnittstelle wurde das Common Gateway Interface genutzt – in aller Regel werkelte dahinter eine Reihe Perl-Skripte.

In den ersten echten Genuss von IMAP kam ich durch das Aufsetzen eines internen Mailservers für Heimzwecke – der holte die Mails per POP3 in festen Intervallen ab und stellte sie dann intern wieder per IMAP zur Verfügung – ich wusste schon zu der Zeit die Vorzüge zu genießen. Selbst ist der Admin 🙂

Der langen Rede kurzer Sinn – Ziel war es nun, das eingerichtete e-mail-Konto von POP3 auf IMAP über zu siedeln. Ich selbst habe diesen Schritt schon häufiger durchgeführt – auch mit Thunderbird. In der Regel ist das kein Problem: Ein zusätzliches Konto per IMAP einrichten, den POP3-Abruf stilllegen, damit er nicht die gerade hochgeschobenen Mails gleich wieder abholt und löscht (den Fehler merkt man recht flott …) und dann kann man mit einer schönen Operation „Drag&Drop“ die e-mails aus den lokalen Ordnern auf den Server verschieben. Eine Sache von wenigen Minuten in der Regel.

Doch grau ist bekanntlich alle Theorie – irgendwie wollte das nicht so recht funkionieren – der Transfer zog sich ewig in die Länge und brach dann irgendwann einfach ab. Da es bereits etwas später am Abend war, haben wir es erstmal vertagt.

Ich habe mich dann mal etwas genauer schlau gemacht was da ursächlich sein könnte bzw. wie man das optimieren kann. Kurze Recherhe mit „Prof Dr. Dr.  Google“ liefert einen Ansatzpunkt: Thunderbird verwendet für lokal gespeicherte e-mails ein standardisiertes und weithin bekanntes Format zum Speichern von Mails: das gute alte MBox-Format – ein recht einfaches Text-Format in dem alle e-mails in der Reihenfolge des Eingangs hintereinander weg geschrieben werden. Einfache Techniken sind ja in der Regel begrüßenswert, aber in diesem Fall ist die Extraktion nicht wirklich einfach (Regular-Expressions sind sicherlich hiflreich, aber auch die diversen Fragen zum Escaping der From-Lines – näheres siehe im Link). Damit es etwas schneller geht fertigt Thunderbird eine Index-Datei an. Unterordner erhalten bei Thunderbird eigene Dateien.

Eingangs hatte ich anklingen lassen, dass man früher nicht gerade große e-mail-Postfächer hatte – daher war das Mbox-Format auch zielführend. Aber man bedenke etwaige Beschränkungen die jeder PC-Nutzer meiner Generation wohl irgendwann einmal kennen gelernt hat: Beschränkuingen des Dateisystems erlauben nicht, dass eine Datei eine gewisse Größe überschreiten darf – mit FAT32 sind es 4GB, früher unvorstellbar groß – heute noch nicht mal ausreichend für einen Film auf DVD. Nun kann man sich natürlich auch vorstellen wie performant die Arbeit in entsprechend großen Text-Dateien ist, wenn man darin Mails sucht … für große Datenmengen gibt es deutlich besser Aufbewahrungsmethoden, zumal man in der Regel die Mails ja nicht auf Endlos-Papier ausdruckt sondern doch eher Stück für Stück liest. Was Thunderbird so flügellahm machte war die simple Tatsache, dass aufgrund des vielen Inhalts fast 3 GB Mails in einer Datei lagen – in Zeiten von dicken Anhängen und den unvorstellbaren Mengen Speicherplatz aktueller Rechner eigentlich nicht mehr verwunderlich.

Was also tun? Wenn Thunderbird ins Straucheln kommt, dann sinnt man auf Abhilfe mit einfachen Mitteln, zumal ja alles standardisiert ist: Protokolle, Format, da sollte sich doch etwas machen lassen. Mittel der Wahl als Administrator ist für solche „Quick’n’Dirty“-Arbeiten die Programmiersprache Perl. Flexibel, teilweise wirklich sehr kurz und unsauber, aber halt einfach das Schweizer Offiziersmesser wenn es um das stapelweise verhackstücken von Dateien geht. Praktischerweise gibt es mit CPAN ja auch für fast jeden Anwendungszweck passende Module. Recht flott habe ich ein Skript zusammengezimmert, das mir die einzelnen Dateien durchgeht und den Upload per IMAP übernehmen soll. Doch, wa soll das schon wieder – auch dieser Weg scheitert – die Perl Module laden nach und nach die gesamte Datei in der Arbeitsspeicher, bis das Betriebssystem meint „jetzt ist aber gut, und den Prozess abwürgt“.

Nun gut, als Admin fühlt man sich nun doch heraus gefordert – wenns so nicht geht, dann gibts ja immer noch Mittel und Wege. Ich entscheide mich dem Tool das Leben etwas leichter zu machen und die Mail-Datei schon einmal etwas vorzuverdauen. Will heißen wir spalten die große Datei in kleinere Happen auf. Mittel der Wahl für mich in diesem Fall ist das Maildir-Format, das sich als Alternative zum Mbox-Format etabliert hat und das mittlerweile viele Mailserver und auch Clients einsetzen (interessanterweise gibt es auch Ansätze ob Thunderbird das lokal verwenden sollte…) Im Maildirformat ethält jede Mail eine eigene Datei – etwas weniger effizient was den Speicherplatz betrifft, aber der ist ja heute reichlich verfügbar und e-mails sind heute meist derart umfänglich, dass dieser kleine Overhead auch nicht mehr ins Gewicht fällt. Generell ist der Zugriff auf eine einzelne Nachricht nun wesentlich direkter möglich.

Auf zu Versuch Nummer 2 als, diesemal dann mit einem Perl-Modul, das e-mails in Maildir-Verzeichnissen lesen kann. Und wieder ein Griff ins Klo … ich zweifle schon an meinen Fähigkeiten, als ich dann doch diverse Reports im Netz finde, dass die Iteration über Mailboxes mit dem Perl-Modul wohl einen Bug hat und den allokierten Speicher nicht mehr rechtzeitig frei gibt. Ein klassisches Memory-Leak also.

Weiter verfolgen muss ich das nun aber nicht mehr, mein Kumpel hat in der Zwischenzeit eine wesentlich bessere Variante gefunden, als Brute-Force alles auf den Server zu transferieren: Einfach vorher das Postfach mal grundlegend entrümpeln und wirklich nur die erhaltenswerten Mails auf den Server verschieben. Das ist natürlich auch eine Lösung, auch wenn sie für mich technisch natürlich nicht an den Charme eines Skriptes heran kommt. Aber was immer hilft soll mir in diesem Fall ja recht sein.

Was haben wir also gelernt: POP3 ist nur noch in Ausnahmefällen eine sinvolle Alternative, vor allem weil heute ja kein echter Mangel an Bandbreite und Dauererreichbarkeit mehr besteht. Selbst für den Offline-Fall bringt heute jeder IMAP-Client notwendige Mechanismen zum Caching der Mails mit. Zweitens: Auch das MBox-Format ist inzwischen mit Vorsicht zu genießen, ich selbst verwende es ja schon seit den Anfängen des eigenen Mailservers nicht mehr (auch weil qmail es damals nicht aktiv unterstützte sondern die Grundlage für Maildir legte). Aber das allerwichtigste ist wohl: „Schmeiß auch mal weg, trenne dich von Dingen die du eh nicht mehr brauchst“ – das regelmäßige Bereinigen eines Postfachs macht zwar auch Mühe, aber man kann es ja auch wieder automatisieren: Wer hat jemals e-mails angeschaut, die älter als drei Jahre waren? Wirklich wichtige Informationen speichert man ohnehin als Datei ab oder druckt sie dokumentenecht auf Papier aus. Die ganzen restlichen Alltagsmails kann man nach einer gewissen Zeit gefahrlos löschen. Es lebe der Frühjahrsputz. So und jetzt greife ich dann auch mal zum digitalen Schrubber – das könnte etwas länger dauern – derzeit habe ich rund 5 GB an e-mails herum liegen … da hilft wohl doch eher der Hochdruckreiniger denn ein Schrubber …