Identicons

I really like the idea of Don Park's identicons.
His aim is largely to use it as a way to recognize commenters in blog posts by evaluating their IP address. Since the human eye or rather, the human brain is faster at telling images apart than it is at finding differences in written IP addresses, this makes commenter validation much easier. Alas, since I don't have many commenters I went for a different application. I implemented a .NET class that creates bitmaps from an integer input value, very much like Don described it here. The create method takes an integer and a size value and returns an Image.Bitmap which can be saved or used within the application. I didn't take a look at the source code provided since I don't understand like Java very much. I started from scratch using GDI+. There is a handy object available called GraphicsPath. It is a container for shapes like lines, polygons and so on. These objects can be manipulated through a transformation matrix. Just the right thing for the shapes that make up the identicon. The implementation is probably very ineffective in terms of runtime performance . I have tried to keep it as simple as possible in order to understand what's happening even later on! :-)

Here you can download the class. Feel free to use it. Feedback is appreciated.

Download identicon.zip

.NET 2.0 is required but only for the generic lists that hold the shapes, it should be easy to port it back to .NET 1.1.

Mitternachtsdebugging

Wieder mal ein Stück teuer erworbenes, aber fast nutzloses Wissen: In .NET spielen dll's unterschiedlicher Versionen normalerweise prima zusammen, man kann z.B. ein Executable mit der Version 1.9.1.0 mit einer älteren Library 1.8.0.0 zusammen laufen lassen. Aha! Aber es gibt eine Ausnahme.. ist die Anwendung ein Windows Service, so stürzt sie beim Start mit einer älteren Libraryversion mit dem nicht gerade sehr hilfreichen Fehler ab:
"Error 1053: The service did not respond to the start or control request in a timely fashion"
Wie bitte, timely fashion? Die Meldung erscheint nach etwa 3-4 Sekunden! Da mußte was faul sein, aber es hat wirklich gedauert bis ich drauf gekommen bin :-\

SRTM Daten

Dieses Wochenende hatte ich ein paar Stunden Zeit, so daß ich endlich mal den SRTM Viewer debuggen konnte, der hier schon so lange rumlag, daß sich bereits ein leicht unangenehmer Geruch breitmachte ;)
Hier gibt es dazu noch ein paar Bilder.

Wider dem Bankomat

Dies hier ist mal wieder ein höchst unterhaltsamer Hack. Irgendjemand erhält Zugriff auf die Betriebsanleitung einer Bankomat-Serie. Darin sind praktischerweise gleich die Standard-Passwörter hinterlegt. Er steckt seine Karte in den Automaten, versetzt ihn mithilfe des Passworts in den Administrationsmodus und manipuliert das Verhältnis Kontobelastung - Geldausgabe. Da er ein anonymes Konto benutzt und sein Äußeres geschickt gegen die Überwachungskameras abschirmt, kann er ganz leicht an Geld kommen.
Jetzt müssen alle Geräte gepatcht werden. Oh, es sind fast 75.000 Stück, die überall verteilt sind! ;-) Angeblich kann die Betriebsanleitung sogar er-googlet werden. Oh-oh!

Barcodescanner

Heute war mal wieder ein Tag der skurrilen Fehler. Irgendwelche doppelten Datensätze in der Kundendatenbank führten schließlich dazu, daß ich einen Barcode-Scanner aus dem Schrank kruschtelte, an den PC anstöpselte (PS2, Keyboardstecker) und eigenhändig Nummern in das System einbuchte. Funktionierte bei mir. Ganz komisch. Dann saßen wir alle vor den Tabellen mit den doppelten Datensätzen und ich dachte so bei mir.. Keyboard.. ';' .. ' ',.. Layout.. Aaaah! Die Erleuchtung traf mich. (Das tut sie nicht so oft, um so mehr freue ich mich, wenn es mal wieder soweit ist). Das Keyboardlayout war schuld. Vielmehr, die unterschiedlichen regionalen Layouts. Das betrifft natürlich im wesentlichen die Sonderzeichen. Ein Barcodescanner tut nämlich so, als wär er eine Tastatur. Sendet Key-Codes. Und die werden je nach Ländereinstellung unterschiedlich interpretiert. Wenn man z.B. die regionalen Einstellungen auf "US" setzt und drückt auf einer deutschen Tastatur 'z', kommt 'y' raus. Dann funktioniert der Dublettentest nicht mehr und schon hat man denselben Artikel zweimal im System. Hach, so was.

Patchwork

Meine Schwiegermutter ist ganz begeistert von Patchwork. Neulich erzählte sie was von einer neuen Decke und wir kritzelten dann verschiedene Muster auf ein Karopapier. Naja, warum einfach wenn es auch kompliziert geht? Darum gibt es jetzt die Patchworkvorschau, da kann man sich das Ganze besser vorstellen. Eigentlich aber nur wieder ein autodidaktisches Projekt, um etwas besser JavaScript zu beherrschen.

Dokumentation

Was passiert eigentlich, wenn der Kunde anruft und sagt, "Ich hab da ein Problem, bei Funktion X erscheint Y, aber da sollte eigentlich ein Fenster aufgehen und Z stehen!". In den meisten Fällen hat die den Anruf annehmende, liebliche Supportmitarbeiterin die Anwendung so gut im Kopf, daß sie rundheraus antworten kann "Ja guter Mann, Z gibt es seit Version 8.15 nicht mehr, jetzt erscheint Y!". Wenn es sich nun um eine äußerst komplexe Angelegenheit handelt, die Geschäftsvorfälle kompliziert und voller versteckter Abhängigkeiten sind, kann sie einen Rückruf ankündigen. Sie öffnet ihre Schublade und sucht in der Dokumentation nach dem entsprechenden Vorfall. Sie findet die Beschreibung der aktuell ausgelieferten Version und kann gleich entscheiden, ob es sich um einen Fehler handelt.
Hat sie keine (aktuelle) Dokumentation, greift Plan C. Abmarsch zu dem für diesen Kunden zuständigen Consultant. Der hat das Ganze ausgeheckt, er müßte es wissen.
Nun kann es sein, daß dieser Mensch das Ganze auch nicht mehr so richtig durchdringt. Wie war das noch gleich wenn Fall A und B zutreffen und der Kunde X aufruft?... Hm. Wir gehen auf Nummer sicher und holen einen Entwickler! Der hat in der Regel natürlich auch keine Antwort parat, da er es a) entweder gar nicht selbst implementiert hat oder b) aus Entwicklersicht gar nicht ohne weiteres beantworten kann, da er ja tagsüber entwickelt und nicht die Anwendung bedient. Es kommt zum Äußersten: Mit dem Debugger bewaffnet stellt der Entwickler die Situation beim Kunden nach und wurstelt sich Schritt für Schritt durch die Anwendung, bis er verstanden hat, weshalb Y auftaucht. Kein Fehler! Der Kunde hat nur vergessen, vorher N und M richtig einzustellen.
Ich sage mal voraus, das eine Firma nicht viel Gewinne machen kann, wenn der letzte Fall zu häufig vorkommt. Ähnlichkeiten mit mir bekannten Firmen sind rein zufällig und höchstens beiläufig beabsichtigt.

Licht und Schatten


Danny Goodman,
JavaScript & DHTML Cookbook,
https://www.puls200.de/wp-content/plugins/Sterne/img/icon-rating-star_f.gifhttps://www.puls200.de/wp-content/plugins/Sterne/img/icon-rating-star_f.gifhttps://www.puls200.de/wp-content/plugins/Sterne/img/icon-rating-star_f.gifhttps://www.puls200.de/wp-content/plugins/Sterne/img/icon-rating-star_f.gifhttps://www.puls200.de/wp-content/plugins/Sterne/img/icon-rating-star_h.gif

Seit längerer Zeit liegen auf meinem Schreibtisch zwei neue Bücher zur Webentwicklung. Gekauft in einem Anflug von Begeisterung und der Erwartung, bald wieder etwas neues zu entwickeln lagerten sie bald etwas Staub an. Schade. Am Abend ist die Fähigkeit etwas Neues in den Kopf reinzudrücken doch etwas reduziert. Jetzt bin ich schlußendlich doch dazu gekommen, mich mal darum zu kümmern :) . Das eine Buch, "JavaScript & DHTML Cookbook" beschäftigt sich mit dem Schwerpunkt Javascript und dem den HTML Seiten zugrunde liegenden DOM Objekt. "Foundations of Ajax" dreht sich ausschließlich im die (etwas gehypte) neue Technologie. Grundverschieden auch die Ansätze. Das Cookbook liefert genau das, was der Titel verspricht: Rezepte, wie man auftretende Probleme am besten löst. Großartig gemacht sind dabei auch Rezepte, die in diesem Zusammenhang eigentlich keine sind sondern eher die Grundlagen von JavaScript. Macht nichts, hat man meistens eh wieder vergessen wenn man sich nicht ständig damit beschäftigt. Und darin liegt der große Vorteil dieses Buchs: Man hat es neben sich liegen beim Tippen und findet bei auftretenden Problemen eigentlich sofort eine Lösung. Das ist aber dann auch kein reines Abgetippe, sondern jedes Rezept enthält einen Diskussionsteil, in dem noch Grundlagen und Alternativen besprochen werden.


Asleson/Schutta,
Foundations of Ajax,
https://www.puls200.de/wp-content/plugins/Sterne/img/icon-rating-star_f_grey.gifhttps://www.puls200.de/wp-content/plugins/Sterne/img/icon-rating-star_f_grey.gifhttps://www.puls200.de/wp-content/plugins/Sterne/img/icon-rating-star_n_grey.gifhttps://www.puls200.de/wp-content/plugins/Sterne/img/icon-rating-star_n_grey.gifhttps://www.puls200.de/wp-content/plugins/Sterne/img/icon-rating-star_n_grey.gif

Die Foundations auf der anderen Seite gehen eher den Weg, die Entwicklung dieser Technologie aufzuzeigen. Das liest sich mitunter ganz unterhaltsam, ist allerdings für die praktische Entwicklung eher irrelevant. Da gibt es dann seitenweise Beispiele von Webseiten, die Verfahren X oder Y einsetzen oder Diskussionen von irgendwelchen Frameworks. Solche Informationen sind in der Regel nur Minuten nach dem Erscheinungsdatum interessant. Von den Frameworks verschwinden ohnehin wieder die meisten in der Versenkung, so daß dieses Buch in ein paar Jahren sicherlich nicht mehr als Nachschlagewerk dienen kann. Obendrein habe ich bereits 2 fehlerhafte Codebeispiele gefunden. Nicht so schön.
In dem Zusammenhang habe ich eine kleine Testseite gebaut, an der ich ein paar der Verfahren ausprobiert habe.

Kommandozeile

Eine Shell unter Windows? Bisher nur mit äußerster Skepsis zu genießen. Von mir bislang unbemerkt gibt es endlich eine neue Shell für Windows, kräftigerweise gleich PowerShell genannt (früher hieß es mal "Monad"). Zusammen mit einer passenden Console, die mehrere Shells gleichzeitig in Tabs darstellen kann ergeben sich fast schon UNIX-artige Zustände! Ich bin entzückt.
Mit Eingabeumleitung und ähnliche Spezereien aus der Unixwelt reichlich ausgestattet. Aber das interessanteste ist die Verbindung mit .NET. Eine Variable nimmt immer implizit den Typ des entsprechenden .NET Datentyps an, mit der Folge, daß alle dazu gehörenden Methoden verfügbar sind.
Beispiel:

PS>$a = "bla di blub di"
PS>$a.Split(" ")
bla
di
blub
di
PS>

Abgefahren. Ich kratze hier ja nur an der äußersten Spitze des Eisbergs. Alle wichtigen Keywords sind ebenfalls vorhanden, so daß man in der Shell jetzt eigentlich richtige .NET Programme ausführen können müßte. Die Integration mit .NET (2.0!) ist gleichzeitig auch ein gewisser Nachteil, es dauert eine ganze Weile, bis das Teil gestartet ist und auch der von .NET her bekannte Ressourcenhunger ist vorhanden. So, jetzt muß ich noch ein bißchen weiterspielen..
Cheat Sheet

Sortierbare Spalten

Diesmal ein eher technischer Eintrag, dessen Zweck eher eigene Gedankenstütze als öffentliche Erheiterung ist. Hoffe ich zumindest.

Im .NET Framework 2.0 gibt es zusätzlich zum bekannten DataGrid Steuerelement das neue DataGridView. Dessen Fähigkeiten wurden gegenüber dem Vorgänger stark erweitert, so daß es inzwischen nur noch Sekunden dauert, um eine Datenquelle über ADO oder eine eigene Implementierung an die Tabelle anzuschließen. Das Ding bringt bereits nette Fähigkeiten mit, z.B. die Spalten umzuordnen. Die Spalten allerdings (durch einen Klick auf den Spaltenkopf) automatisch umzusortieren ist leider nicht so einfach, wie es zunächst aussieht. Das Sortieren der Datenquelle funktioniert nur dann problemlos, wenn ein Datagrid bzw. ein Dataview angebunden ist. Kommen die Daten direkt aus der Datenbank ist das auch kein Problem. Hat man jedoch die anzuzeigenden Objekte woanders her, z.B. aus einer Liste, funktioniert das leider nicht mehr. Die Liste weiß nicht, nach welchen Kriterien sie sortieren soll. Die Lösung besteht darin, eine eigene Listenimplementierung einzuführen, die von der ursprünglichen Liste erbt und zusätzlich IBindingList implementiert.

public void ApplySort(PropertyDescriptor property, ListSortDirection direction)
{
Trace.WriteLine(string.Format("sorting column {0}",property.DisplayName));
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(AISShip));
this.sortProperty = properties.Find(property.DisplayName, true);
this.Sort(this.Comparison);
this.OnListChanged(resetEvent);
}

Diese Methode ist ein Teil der Implementierung von IBindingList. Sie wird beim Sortieren der Liste implizit (vom DataGridView durch ein callback) aufgerufen. Das spaltenrelevante Sortieren habe ich so gelöst, daß die entsprechende Spalte lokal gespeichert wird und die Suchfunktion mit einem Vergleichs-Delegaten aufgerufen wird. Das wirkt etwas ungewöhnlich, es ist auch eine Neuerung in .NET 2.0.
Die eigentliche Vergleichsfunktion sieht etwas lahmarschig aus, man hätte hier sicher noch eleganter mit Reflection arbeiten können (wenn auch weniger performant):

protected int Comparison(AISShip a, AISShip b)
{
if (this.sortProperty.Name.Equals("Timestamp"))
return a.Timestamp.CompareTo(b.Timestamp);
if (this.sortProperty.Name.Equals("Name"))
return a.Name.CompareTo(b.Name);
if (this.sortProperty.Name.Equals("Callsign"))
return a.Callsign.CompareTo(b.Callsign);
if (this.sortProperty.Name.Equals("IMO"))
return a.IMO.CompareTo(b.IMO);
// usw.
return 0;
}

Eine weitere Verbesserung kann man noch einbauen, wenn man sich beim Suchen außerdem die letzte Sortierrichtung merkt und diese dann umdreht, falls sich die Spalte nicht geändert hat. Damit erreicht man dann das typische Verhalten, daß der Benutzer aus dem Windows Explorer her kennt.