Mittwoch, Dezember 12, 2007

Das 2 Millionen-Studium

2 Millionen Minuten -- so lange dauert ein vierjähriges Studium. Das rechnet uns der Filmemacher Robert A. Compton in seinem Film "Two Million Minutes" vor. Die Flash-Animation zur Filmwebseite baut eine bedrohliche Kulisse auf: Indische und chinesische Studierende nutzen die zwei Millionen Minuten ihres Studiums deutlich mehr und umfassender als amerikanische Studierende. Es scheint nur eine Frage der Zeit zu sein, bis dieses Potential an Bildung der amerikanischen Vorherrschaft in den Naturwissenschaften, in den Ingenieurswissenschaften und in der Informatik die Ränge abläuft. Anbei: Wir Europäer kommen in dem Film gar nicht vor.

Wenn Sie mögen, hier der Trailer:



Ist es wirklich so schlimm? Heute hat die Bertelsmann-Stiftung die Ergebnisse einer Repräsentativbefragung vorgestellt: "Wer regiert die Welt?". Befragt wurden 8.999 Bürger aus Brasilien, China, Deutschland, Frankreich, Großbritannien, Indien, Japan, Russland und den USA. Wie sie die internationale Rolle ihrer Länder sehen etc. Für das Jahr 2020 rechnen die Befragten mit einer gleichberechtigten Rolle Chinas als Weltmacht neben den USA. Mit deutlichem Abstand folgen fast gleichauf Russland, die EU, Japan und Indien.

China, Russland, Indien -- das sind keine Überraschungskandidaten. Wenn man in jüngster Zeit erlebt, wie sehr gut ausgebildete russische und indische Informatiker mit StartUps und mit Innovationen auf die Märkte drängen -- man kann ans Grübeln kommen.

Fazit? Work smarter, not harder?! Ja, immer doch, aber ich glaube -- ehrlich gesagt -- das wird nicht reichen, wenn wir dem Wettbewerb stand halten wollen. Ein guter Teil der Informatik-Ausbildung und des Könnens ist reines "Handwerk", so wie in vielen anderen Studiengängen auch. Da bekommt Übung und Erfahrung nur der, der etwas tut. Mit Smartheit allein wird niemand ein guter Pianist; mit viel Übung kommt man allerdings schon sehr weit.

Sonntag, Dezember 09, 2007

Googles Chart-API und seine Nachhaltigkeit

Am Nikolaustag hat Google das Web um ein weiteres API (Application Programming Interface) bereichert: das Chart-API. Der Gebrauch des APIs ist einfach und das Resultat schön anzusehen. Kein Wunder also, dass sich die Ankündigung des Chart-APIs wie ein Lauffeuer in der Bloggosphäre verbreitet. Mit einem einfachen HTTP-Request wie diesem als src-Attribut in einem img-Tag

http://chart.apis.google.com/chart?cht=p3&chd=s:Uf9a&chs=200x100&chl=A|B|C|D">

ergibt sich der folgende visuelle Effekt:



Das API scheint wirklich nützlich zu sein, wenngleich das Interface für Menschen wenig intuitiv ist. Insofern darf man gespannt sein auf die ersten Webseiten, die einem mit einer graphischen Oberfläche beim Erstellen solcher Charts helfen und ein einfaches Experimentieren mit den Parametervarianten ermöglichen. Das sollte mit ein wenig HTML-Code und JavaScript zu machen sein.

Solche APIs gehen in die richtige Richtung: Sie machen Web-Seiten rein beschreibend (deklarativ), die Kern-Information und damit die Semantik von Daten bleibt erhalten und sie verführen zum Gebrauch, da sie sinnvoll und nützlich sind. Es würde mich nicht wundern, wenn in Zukunft solche deklarativen Service-APIs, zusammen mit den sogenannten Microformaten und Meta-Daten (z.B. in Form von Tags) das Web mehr und besser um semantische Information bereichern als es die ganzen bisherigen Standardisierungsversuche des W3C zum semantischen Web geschafft haben. Zumindest dann, wenn Menschen bei der Erstellung von webfähigen Inhalten zur Anreicherung um semantische Informationen verleiten werden sollen.

Ein Problem jedoch bleibt beim Einsatz von APIs: Was, wenn der Google-Dienst einmal ausfällt oder nicht verfügbar ist (z.B. da man offline ist)? Dann durchziehen eine Webseite Informationslöcher. Was, wenn Google das API ändert ohne kompatibel zu früheren Versionen zu sein?

Es wird zunehmend wichtiger, sich mit der Problematik der Nachhaltigkeit (um den Begriff auch mal in so einem Kontext zu verwenden) von Web-Seiten auseinander zu setzen. Wie können Webseiten zuverlässig gerendert (d.h. vollständig visuell aufbereitet) werden, auch wenn die dazu benötigten Web-Dienste nicht jederzeit und immer zur Verfügung stehen? Ein Grundproblem aller verteilten, dezentralen Systeme. Dabei sind einfache Ein-/Ausgabedienste wie Googles Chart-API noch das geringste Problem.

Eine simple Möglichkeit besteht darin, ein einmal über das Chart-API angefordertes Bild abzuspeichern und als Alternative lokal oder auf einem Webserver vorzuhalten. Um diesen Vorgang im Hintergrund zu automatisieren, kann man etwa mit Erweiterungen zum Browser arbeiten oder einen Webserver diese Arbeit machen lassen. Mir fallen einige Lösungsstrategien dazu ein. Und das ist genau der wunde Punkt daran: Lösungsmöglichkeiten zur Nachhaltigkeit von Webseiten gibt es viele. Doch was hilft es, wenn es so viele Nachhaltigkeitslösungen wie Service-APIs gibt? Man wird sich in Zukunft mit offline-Techniken als nahtlose Fortsetzung des online-Zustandes befassen müssen -- und sich gleichzeitig um die Nachhaltigkeit der Darstellung deklarativer Informationen kümmern müssen. Dienste wie Google Gears sind dabei ein Teil möglicher, brauchbarer Lösungsansätze.

Donnerstag, Dezember 06, 2007

Körpersprache für Informatiker?

Dem Informatiker, besser: dem Hacker (dem "guten" wie dem "bösen"), hängt ein Vorurteil an: Wir sind Menschen, die bis tief in die Nacht vor unseren Maschinen hängen -- und tagsüber Räume notfalls abdunkeln. Wir beschallen uns via Kopfhörer mit Musik, um uns akustisch von der Welt zu isolieren. Wir tauchen für Stunden ab, sind nicht ansprechbar. Die totale Versenkung. Wir sind eins mit der Maschine, mit dem Programm, mit dem ByteCode. Das Programm bin ich, ich bin das Programm. Und zum Glück kann man zum Mittagessen um 2 Uhr morgens noch Pizza beim Pizza-Service bestellen.

Stimmt alles! ;-)

Nur sind wir deswegen noch lange keine sozialen Krüppel, die solche Videos benötigen, um das Verhalten unserer Mitmenschen zu disassemblieren und zu interpretieren.



Amüsiert frage ich mich, welche Berufsgruppe oder Menschengruppe solche Videos wirklich braucht -- die schon fast wieder gut sind, so schlecht wie sie sind.

[Video entdeckt im "Mixing Memory"-Blog: "Who Does This Remind You Of?" posted on: December 2, 2007 8:23 PM, by Chris.]

Dienstag, Dezember 04, 2007

Ein neuer Markt: Von Wissenschaftsblogs und Kunstgalerien

Liebe Wissenschaftsblogger,

das Web 2.0, dieses Mitmach-Web, ist ein Medium, das findige Unternehmen nach Marktpotenzialen ausloten. Wir Wissenschaftler bzw. Wissenschaftsjournalisten sind offenbar eine interessante Zielgruppe. Wir produzieren Content, der gefragt ist. Und dagegen ist überhaupt nichts zu sagen!

Aber ach, was red ich. Wollte ich Ihnen nicht eine Geschichte erzählen von einem Freund im Geiste, einem Künstler?

Da war ein Künstler, dessen Bilder einem Großgaleristen gefielen. So sagte der Galerist zu dem Künstler: "Ich will eine Künstler-Community aufbauen! Ich biete Dir meine Galerie zur Ausstellung Deiner Bilder an. Nicht allein, Deine Bilder zeige ich zusammen mit Werken anderer Künstler. Du wirst Deinen Wirkungskreis erhöhen und Du wirst weitere Künstler kennenlernen. Bist Du dabei? Übrigens, das Ganze kostet Dich nichts; ich leg' Dir noch ein paar Euro im Monat drauf."

Der Künstler freute sich. Dass zwischen den Bildern Werbeplakate hängen sollten, nahm der Künstler seufzend zur Kenntnis. Aber irgendwie muss ja auch der Großgalerist Geld bei der Sache verdienen können. Kunst und Kommerz -- das muss sich ja nicht ausschließen.

Dann kam der Vertrag vom Galeristen mit der Post. Da stand zum Beispiel, er solle doch nach Möglichkeit an jedem Werktag ein Bild malen. Wie das?! Er malte ein Bild im Monat, manchmal sogar zwei oder drei, wenn es sehr gut lief vier oder fünf -- aber Fließbandkreativität? Seltsam, das klang alles so anders als im Gespräch mit dem Galeristen. Der Künstler verstand nicht viel von Juristerei, also zog er einen Anwalt zu Rate. Und der sagte ihm: "Laß die Finger von dem Vertrag. Der Galerist erhält alle Rechte an deinen Bildern, sie gehören dir nicht mehr. Er darf deine Bilder sogar übermalen, wenn er Lust dazu hat. Und übrigens: Gegen Diebstahl und Vandalismus musst du deine Bilder selber versichern. Ich kenne keine Versicherung, die das für 'ein paar Euro' macht."

Da sprach der Künstler mit dem Galeristen. Der fiel ihm sogleich ins Wort: "Warum so ein Misstrauen, mein Lieber?! Du glaubst doch nicht, dass ich reich werde mit meiner Galerie. Die paar Werbeverträge! Und wer spricht denn von Zensur, wer hat dir denn diese Flausen in den Kopf gesetzt? Ich kann mir doch gar nicht die Mitarbeiter leisten, all die Bilder von dir und deinen Künstlerkollegen durchsehen zu lassen und sie zu 'korrigieren'. Was sollte ich für ein Interesse daran haben. Klar, wir werden mal einen Bildband mit den besten Werken von der Künstler-Community herausbringen. Aber das ist doch alles in Deinem Sinne, oder?"

Der Künstler unterschrieb den Vertrag nicht. Er war froh, sich einen Rechtsbeistand geholt zu haben. Und so malte er weiter: frei!

Sie sehen, ich blogge immer noch unter Google. Gebt auf Euch acht, liebe Wissenschaftsblogger. Freiheit kann man einem Künstler gleich auch in kleinen unabhängigen Galerien genießen. Oder in einem Wissenschafts-Cafe! Man sieht sich ;-)

Mittwoch, November 28, 2007

"Dienst oder Dienstmerkmal nicht möglich."

Letzte Woche war ich auf der USAB 2007 (Usability & HCI for Medicine and Health Care; HCI steht für Human Computer Interaction) und begeisterte mich an der Keynote von Harold Thimbleby, der an der Swansea University (UK) lehrt. Thema: "User-Centered Methods are Insufficient for Safety Critical Systems". Irgendetwas hat er in mir losgetreten, und seitdem laufe ich etwas aufgeweckter durch die Gegend, was die Gestaltung von Mensch/Computer-Schnittstellen betrifft. Zwei Beispiele aus den letzten Tagen:

Flughafen Frankfurt am Main. Ich bin eben gelandet, bin zum Ausgang raus und steure die Automaten an, um mein Parkticket für das Auto zu bezahlen. Ich schiebe die Parkkarte in den Automaten, das Geld hinterher, bekomme die Parkkarte zurück und realisiere erst in dem Moment, dass ich eine Quittung über die Parkgebühr benötige. Schnell noch die Quittungstaste gedrückt -- die mir den Dienst verweigert. Ihr fehle eine Parkkarte! Also schiebe ich die Parkkarte wieder in den Automaten in der Hoffnung, nachträglich eine Quittung anfordern zu können. Geht nicht, "Parkgebühren bezahlt". Mir bleibt nichts anderes übrig als mich an der Ausfahrtschranke an den Parkwächter zu wenden und ihn um eine Quittung zu bitten. Der Vorgang dauert etwa 3-4 Minuten, wobei der Parkwächter sich einmal am Rechner vertippt, um festzustellen, ob meine Karte bereits bezahlt ist.

Verblüffend, wie die Entwickler der Bezahlautomaten das Szenario der nachgeforderten Quittung schlicht ignoriert haben, gell? Vor mir war ein Mann beim Parkwächter an der Reihe, der überraschenderweise exakt dasselbe Problem hatte. Vermutlich kommt das an einem Flughafen wie Frankfurt etliche Male am Tag vor. Wie kann man sowas übersehen?

Gestern. Ich rufe meine Frau im Büro an. Die Leitung ist besetzt. Ein Stimme fragt mich, ob ich gerne den automatischen Wiederwahl-Dienst bei Freiwerden der Leitung nutzen möchte. Ich möge dazu "Ja" in den Hörer sprechen. Ich sage "Ja" und bekomme zu hören: "Dienst oder Dienstmerkmal nicht möglich."

Warum in aller Welt bekomme ich eine Option angeboten, die nicht ausgeführt werden kann? Kann der Computer das nicht vorher ermitteln und mir den Service nur anbieten, wenn er verfügbar ist? Gut möglich, dass mir jetzt ein Software-Entwickler lang und breit erklären kann, warum das so sein muss. Die Software könne das nicht vorher erkennen. Das war ein Punkt in Thimblebys Keynote: Ist ein schlechtes Design eine Entschuldigung? Wenn eine Software nicht vorher ermitteln kann, ob sie dem Nutzer ein Leistungsmerkmal anbieten kann oder nicht, dann ist sie schlecht entworfen.

Haben Sie ähnliche Erfahrungen gemacht? Wenn Sie mögen, berichten Sie mir davon!

Samstag, November 24, 2007

User, Domain and Realization Models

In my previous post on "Modeling Illusions" I distinguished between the illusion, manifested by a domain model, and the model that does the trick, the realization model. The interesting question is: How do these two models relate to each other?

If I managed to explain things well, you should have understood that both models implement the same interface and that they behave exactly the same for an external observer. Otherwise, it would be useless to talk about an "illusion". From the outside, there is no way to tell which model is actually operating "behind the wall". From this viewpoint, both models are interchangeable.

Note that this statement highlights a very crucial point. If you cannot say what's behind the wall, you experience and develop a consistent mental model of the interface and it's behavior from the outside. We call this mental model the user model of the interface.

So we are having three models: From an external viewpoint, we have a user model a user associates with the interface; it is the user's perception of the illusion. Behind the wall, from an inner perspective, the interface is either implemented by a domain model, describing the illusion from an inner perspective, or by a realization model, an alternative description for the illusion.

The relation between the models is as follows: In terms of size, better: information content, the following formula holds:

user model <= domain model < realization model

Ideally, the user model and the domain model match. However, the realization model must be "bigger" than the domain model. Both, the domain model and the realization model, must have the capability to generate the same external user experience. But there must be more to the realization model. Otherwise why should you call it a realization? You could also say that the realization has more information content than the domain model by definition.

From a software engineering standpoint, the realization model should be developed in such a way that it can be easily verified against the domain model(!). It should be easy to show that the state model the realization model implements includes the state model of the domain model. Alas, this is not standard practice. Only very few software engineers know and understand the cascade of these three models: user model (external interface experience), domain model and realization model (alternative interface implementations). To distinguish and actually use domain and realization models is a very powerful technique to manage complexity. This technique is, however, of limited use, when there is no way to show that the realization model actually realizes the domain model.

There are some techniques around to keep the realization and the domain model "in sync". One is to use generative techniques to generate the realization model out of the domain model (catchword "Domain Specific Modeling"). Another is to use Aspect-Orientation, which enables a designer to add realization aspects to an domain model. Formal methods may help prove that the realization model is consistent with the domain model. So there are some important tools around in the toolbox of a software engineer.

By the way: User models are crucial in (User) Interface Design!

Montag, November 19, 2007

Modeling Illusions

A very important tool in software engineering (SE) is modeling illusions. In SE, engineers most often focus solely on realizations not illusions. However, illusions are the magic to create self-contained worlds (or domains), to separate design spaces and thereby simplify design. Modeling illusions is an art which is rarely understood and applied.

What do I mean by illusions? Let me give you some examples: Look at your desktop on your computer screen -- it's an illusion. There is no desktop in your computer. See the little small icon you call a dustbin or trash can? It's an illusion. Take a screwdriver and open your computer; you won't find a dustbin in there. Your files on your hard disk are organized in directories which are nested in a hierarchy. It's an illusion. Your hard disk actually has multiple platters and read/write heads, and each platter is organized in tracks and sectors (see also "How Hard Disks Work"). You work with databases, handle tables, keys, relationships? The world implied by SQL is an illusion. Look at any serious, high-performance database implementation. It's about B-trees and similar stuff.

The essence is: You have to distinguish an illusion from it's realization. What they share and have in common is the (user) interface. It's the interface that creates an illusion!

You got it? What I'm after is the following:

Any interface creates an illusion. A software engineer should describe the illusion from two different viewpoints: One model describes the elements of the illusion, how they can be used, how they relate and interact and so on. It's a domain model of the illusion. The other model describes how the illusion was done; it unveals the trick of the "magician". It's a realization model of the illusion. Others might also call it an "implementation model".

My point is: Software Engineers usually miss the point to consider each model as a model in it's own right. They are sloppy with the domain model but careful with the realization model. This is bad, because domain models are one of the most valuable modeling techniques to reduce complexity for system's understanding. A domain model can be taken as serious as a realization model and being made executable. Then, you have a choice: You can look at your interface and work either with an executable model of the illusion or you can look at your interface and work with an executable model of the illusion's realization, thereby looking behind the scenes. The domain model lets us ignore the complexities of the realization; but the domain model is complete and creates a self-contained illusion. It is as if the magic were true. The realization model opens up a new level of complexity.

Let me give you a final example -- it also complements my criticism on "The law of leaky abstractions":

What kind of illusion does TCP create for you? The TCP user interface provides a connection-oriented communication service. It creates the illusion of a reliable connection to communicate data with someone else (you asked to accept the connection beforehand). That's the illusion.

If we look at how the trick is done, the realization, we see a state machine realizing a nice rendezvous with a remote state machine sending IP datagrams back and forth. These two state machine implement the so-called TCP protocol. TCP relies on IP.

If you do socket programming (that's using TCP connections, for the ones who do not know), the socket library of your favorite programming language offers you to work with the illusion of a TCP connection. Beyond that socket libraries fall short of the notion of a connection. Nobody really cares about a rock-solid domain model of TCP, they all do in Unix/Linux and Windows is creating realizations. In a rock-solid domain model a TCP connection would be associated with some statistic properties. You could ask the connection about some statistic properties: How reliable is the connection, how many data packages got lost and had to be retransmitted etc.? If a domain model of TCP were carefully done and accessible in socket libraries, nobody would be so naive to believe that TCP would come at no costs and actually be 100% reliable. If you abstract these details away, you might do so for the purpose of simplification, but you should know what you're doing.

Donnerstag, November 15, 2007

E8 und die "Theory of Everything"


Das lässt Sie sicher auch stutzig werden, wenn Sie hören, jemand habe die "Theory of Everything" gefunden -- auch wenn es dabei "nur" um Physik geht. In der Tat suchen die theoretischen Physiker nach so einer Theorie, die alle physikalischen Phänomene unter einen Hut bringt. Klingt hart und ziemlich schwer.

Nun will ein Surfer (nein, so ein Wasser-Surfer, der in Hawaii surft) genau diese Theorie gefunden haben, so berichtet der Telegraph in "Surfer dude stuns physicists with theory of everything" (Roger Highfield, 6:01pm GMT 14/11/2007). Klar, so mal eben beim Surfen drauf gekommen! Unsinn. Doch wenn Sie den Artikel weiter lesen, dann wird die Sache schon ernster. Da ist ein Fachmann am Werk. Das mit dem Surfer verkauft sich halt ein bissel besser. Unser "Dude" Garrett Lisi scheint's drauf zu haben. Quellensuche.

Lisis Artikel hat den schlichten, anspruchsvollen Titel "An Exceptionally Simple Theory of Everything", Sie können ihn bei arXiv.org runterladen. Ich verstehe darin zwar ehrlich gesagt kein Wort, aber das Ganze wirkt solide, ist sehr schön geschrieben (lesen Sie mal Einleitung und Schluss) und hat das Entscheidende, was so eine Theorie braucht: die Theorie macht Vorhersagen, die sie falsifizierbar, sprich widerlegbar machen. Lisi zeigt einen Weg auf, wie die vier fundamentalen Grundkräfte (die starke und schwache Wechselwirkung, die elektromagnetische Kraft und die Gravitation) in eine mathematische Struktur namens E8 abgebildet werden können. Bei dieser Abbildung bleiben ein paar wenige Plätze "unbesetzt". Lisi sagt damit neue Phänomene (Teilchen) voraus, womit seine Theorie entweder bestätigt oder ad absurdum geführt werden kann.

Jetzt bin ich doch gespannt, was die anderen "Surfer" (genau, die Physiker) dieser Welt dazu zu sagen haben. Ist unser Universum wirklich E8?

Wollen Sie meine Meinung dazu hören? "E" ist der fünfte Buchstabe im Alphabet. "E" mal 8 macht 40. Die Antwort auf alles lautet aber 42. Ich fürchte, Lisi muss nachbessern ;-)

Update: Ich scheine mit "E" * 8 = 40 <> 42 nicht allein zu sein, wie ich gerade in einem anderen Blog entdecke. Nur gibt es Leute, die solche Kritik (da sie vielleicht davon etwas verstehen) besser ausdrücken können. Letztlich bin ich jedoch ahnungslos. So ist das, wenn ich nicht über Informatik schreibe. Spaßig finde ich solche Sachen trotzdem. Es ist dem Glauben an den Fortschritt geschuldet.

Donnerstag, November 08, 2007

Mini-Laptops

Seit über zwei Monaten sind Zimtsterne, Marzinpankugeln und all die vielen Weihnachtsleckereien in den Supermärkten zu haben. Mir ist es unergründlich, warum die Marktstrategen glauben, uns auf einer monatelangen "Freßspur" zum Fest führen zu müssen.

Allmählich erinnern auch die PC-Hersteller an das große Fest. Heute schon gewünscht? Ich bin vor zwei, drei Tagen auf den Eee PC von Asus gestoßen. Irgendwie macht mich das Ding an. Klein, portabel, WLAN, alle wichtigsten Anwendungen dabei, USB- und Beamer-Anschluss. Kleine Tastaturen stören mich nicht. Der Preis macht Appetit! Damit können sich auch viele Studierenden einen kleinen aber feinen Rechenzwerg leisten. (Zur Software-Entwicklung ist der Laptop sicher weniger geeignet und man muss sich vermutlich auf sehr einfache Werkzeuge beschränken.) Das Gerät wäre mir ein schöner Reisebegleiter. Die ersten Testberichte klingen auch gut, siehe z.B. bei heise mobil. Lieber noch hätte ich einen XO Laptop, der mir brillant konzipiert zu sein scheint und den ich allein deshalb gerne einmal genauer unter die Lupe nehmen möchte. Doch es wird vermutlich schwer sein, in Europa an solch ein Gerät zu kommen.

Nun bin ich gespannt, mit welchen Konkurrenzprodukten andere Hersteller im "Mini-Laptop-Segment" aufwarten werden. Denn noch hat's ja ein bissle Zeit mit dem Wünschen.

Update 19. Nov.: Wie spannend, die Preise für ähnliche Produke beginnen zu purzeln, siehe "VIA und FIC wollen beim EeePC-Preis mithalten" (heise news, 2007-11-18).

Donnerstag, November 01, 2007

Hey Django!

Wie lässt sich zügig eine webbasierte Anwendung entwickeln, die auf einer relationalen Datenbank aufsetzt?

Da ich gerade ein Projekt betreue, bei dem es genau auf diese beiden Punkte ankommt (webbasiert und datenbankgetrieben), gab ich mir selber einen Tag, um mir eine "moderne" Entwicklungsumgebung und ein "modernes" Framework anzuschauen. Der erste Kandidat: Zoho Creator; der zweite: Django.

Zoho ist eine Firma, die sich -- wie einige andere auch -- dem Nachbau von Desktop-Software auf rein webbasierter Basis widmet, meist ergänzt um Features zur Kollaboration. Darunter finden sich Nachbauten von Word und Excel, eine Projektmanagement-Software, ein Wiki. Meine Aufmerksamkeit erregte jedoch bereits vor einiger Zeit ZOHO Creator, eine vollständig browserbasierte Entwicklungsumgebung zum Bau von Datenbank-Anwendungen. Zoho wirbt mit einer kinderleichten Programmierung, die selbst Amateuren Erfolge bescheren soll.

Dieses Versprechen kann Zoho Creator nicht einhalten. Der Einstieg gelingt zwar schnell, aber ich verzweifelte schon an relativ einfachen Problemen. Die erzwangen das Verlassen der visuell-orientierten Programmierumgebung (die wirklich fein gemacht ist!). Der Wechsel ins "Free-flow Scripting" erwies sich aufgrund einer mageren Dokumentation als Frust- und weniger als Flow-Erlebnis. Nach drei Stunden gab ich auf.

Django reiht sich ein in die Schlange der Frameworks, die "Ruby on Rails" gleich eine ungekannte Leichtigkeit der Webprogrammierung proklamieren. Meine Wahl fiel auf Django, da ich eine exzellente Dokumentation vorfand und mit einer mir vertrauten Programmiersprache operieren wollte. Django läuft unter Python.

Der Einstieg quälte sich etwas dahin, da es eine Menge Lesematerial zu verdauen gilt -- die Intros sind sehr gut und aktuell. Ich wurde jedoch skeptisch, da ich vieles "fressen" musste ohne es zu verstehen. Dann, nach zwei Stunden, als mein Datenbankschema endlich stand, durfte ich die Vorzüge erfahren, die "late binding"-Programmiersprachen mit sich bringen: Änderungen am Code übernimmt der Webserver automatisch; man kann unmittelbar am Browser den Erfolg der Bemühungen austesten. Die Entwicklung wird flüssig, man hat permanentes Feedback. Nach etwas mehr als einem halben Tag hatte ich einen guten Teil des Projekts umgesetzt. Von Null! Das nenne ich "Flow-Scripting". Allerdings muss man sich mit Python auskennen, sonst steht man bei Fehlermeldungen etwas verloren da.

Interessant ist, dass man bei Django sehr deklarativ programmiert (wie auch bei Ruby on Rails). Man beschreibt, konfiguriert, hat funktional so gut wie keine Zeile programmiert und bekommt ein vollständiges Administrations-WebInterface "geschenkt". Ähnlich deskriptiv geht im Grunde auch Zoho Creator vor -- nur mangelt es dem Produkt entweder an Reife oder an Dokumentation.

Mein Resümee: Zoho Creator macht vor, wie man ausgezeichnete interaktive Oberflächen mit Ajax-Technologie entwickeln kann; da kann sich manch andere Firma ein Scheibchen von abschneiden. Frameworks wie Django oder "Ruby on Rails" zeigen, wie flüssig und leicht die Entwicklung von webbasierten Anwendungen von der Hand gehen kann. Das ist weniger eine Frage der IDE als vielmehr des Frameworks.

Montag, Oktober 29, 2007

Billigflug: Gun Fighter


Erinnern Sie sich noch an Tetris? An die herabfallenden Klötzchen? Es ist eine kleine Ewigkeit her, gell?! Mit Tetris verbindet mich die faszinierende Erfahrung, dass man nach acht oder zehn Stunden ununterbrochenem Tetris-Spiel davon träumt und die ganze Nacht über weiter Klötzchen dreht, sie nach links oder rechts bewegt, Space-Taste drückt und sie herabfallen lässt. Eine ziemlich gute Simulation, die das Hirn da vollbringt; der sogenannte Tetris-Effekt. Das hat mich seinerzeit wirklich beeindruckt. Am frühen Morgen, wieder vorm Computer sitzend (wach, aber eigentlich macht es keinen großen Unterschied ;-), ist der Highscore vom Vorabend mühelos gebrochen. Das Hirn hat im Schlaf gelernt, Tetris noch besser zu spielen. (Dazu gibt es übrigens auch einen netten Artikel auf ScientificAmerican.com von Kristin Leutwyler: Tetris Dreams, October 16, 2000.)

Denk ich an Tetris, denk ich an Space Invaders, Phoenix, Pac Man, Ping Pong und ähnliche Spielchen -- die Computerspiele meiner Jugendjahre. Das ist ein Weilchen her. Vielleicht können Sie sich vorstellen, mit was für großen Augen ich Ende August in Halle in einem Supermarkt diese Pappschachtel entdeckte (siehe Bild). Ballerspiele aus den 80igern im Format zweier handlicher "Joysticks" mit Fernsehanschluss für sagenhafte 6.49 Euro. Klar, das musste ich haben. An dem Abend schwelgte ich mit meinem besten Freund in den guten alten Zeiten. Wir steuerten Raumschiffe, lenkten Panzer, fuhren Autorennen, eroberten den Weltraum, ballerten uns den Weg frei -- und hatten eine Menge Spaß dabei.

Die Nacht schlief ich dann ganz normal. Keine Träume in Pixelgraphik. Schade.

Freitag, Oktober 26, 2007

Sloppy Abstractions

There is a very powerful engineering technique, computer scientists make also use of: abstraction. But did you know that abstractions can be leaky?

I had heard about "The Law of Leaky Abstractions" some time ago; now, it again caught my attention, because Philip Wadler mentioned it on his blog. Reason enough to read Joel Spolsky's post (written November 2002) more carefully.

Spolsky's "Law of Leaky Abstractions" says

All non-trivial abstractions, to some degree, are leaky.

He explains his "law" mainly on the example of the TCP protocol (his actor analogy is brilliant and funny) and concludes:

I said that TCP guarantees that your message will arrive. It doesn't, actually. If your pet snake has chewed through the network cable leading to your computer, and no IP packets can get through, then TCP can't do anything about it and your message doesn't arrive.
[...]
This is what I call a leaky abstraction. TCP attempts to provide a complete abstraction of an underlying unreliable network, but sometimes, the network leaks through the abstraction and you feel the things that the abstraction can't quite protect you from.

Spolsky is absolutely correct with his description on TCP -- but I do not agree to his conclusion. There's nothing leaky here. Take network designers. They are fully aware of the services and the quality of the services TCP provides to the next layer in a protocol stack; they also know the limitations of TCP. They know that TCP can fail. And you do as well! What makes ebay so freaky exciting? To deliver your last bid on the very last moment before the auction is over -- and hope the very best for your network connection. You are very much aware that your network might go down in that very moment; TCP won't safe you! Right?!

If you forget that TCP might fail completely, you weren't that pedantic on understanding TCP. You were quite sloppy with your abstraction -- that's all.

The difference between a junior and a senior developer is that a senior doesn't have that many sloppy abstractions a junior has.

Dienstag, Oktober 16, 2007

Merk Dir mal ein Bit!


Haben Sie schon einmal daran gedacht, sich einfrieren und später, irgendwann in der Zukunft, wieder auftauen zu lassen? Das würde etwa die Wartezeit bei einem Flug zum Mars erheblich verkürzen. Was auch immer Ihr persönlicher Grund für eine solche Aktion sein möge, lassen Sie die Finger davon. Mal abgesehen davon, dass das Einfrieren und Auftauen von Zellen eine äußerst heikle Angelegenheit ist -- es kostet Sie nur Geld und lässt Sie strohdumm werden! Ganz richtig: Es macht Sie dumm! Warum? Lassen Sie mich mit einem kleinen Exkurs beginnen: Wie wird Information gespeichert?

Es gibt zwei Arten der Speicherung von Information. Ich möchte Ihnen das anschaulich an zwei Beispielen erläutern:

Nehmen Sie ein kleines Behältnis, eine Schatulle etwa, die ein Steinchen aufnehmen kann. Ist die Schatulle leer, hat die Schatulle den Wert Null gespeichert. Ist das Steinchen in der Schatulle, wollen wir das als den Wert Eins verstehen.

Das ist das wohl am weitesten verbreitete Verständnis eines Informationsspeichers: in einem Gedächtnis (einer Art Riesenschatulle) kann Wissen "abgelegt" werden.

Doch es gibt eine interessante Alternative dazu: Nehmen Sie eine Tasse mit Kaffee und rühren Sie den Kaffee rechts herum: Eins. Rühren Sie ihn links herum: Null. Die Rotationsrichtung des Kaffees enthält die Information! Wenn Sie zu lange warten, sorgen Reibungsverluste dafür, dass dem System Energie entzogen wird und sich irgendwann ein undefinierter Zustand ergibt: der Kaffee rotiert nicht mehr, die Information ist vergessen.

Wir haben also zwei Fälle vorliegen:

  • Informationsträger ist Materie und örtlich gebunden (Raum)

  • Informationsträger ist Energie und zeitlich gebunden (Fluß)


In technischen Systemen wird das Rotierenlassen von Energie zur Informationsspeicherung durch Rückkopplung erreicht. Rückkopplung ist die Rückführung von Ausgängen an Eingänge. Ein sehr schönes Beispiel ist das Flipflop, das z.B. aus zwei NOR-Gattern besteht. Der Schaltkreis selbst ist materielle Information und räumlich gebunden. Der in die materiellen Bahnen geleitete Energiefluss (vereinfacht gesagt der Strom) kann in eine stabile "Rotationsrichtung" versetzt werden -- und merkt sich darüber ein Bit: linksdrehend bzw. rechtsdrehend.

Was passiert, wenn wir ein Flipflop im laufenden Betrieb einfrieren und wieder auftauen? Der Vorgang des Einfrierens entspricht dem Entzug von Energie. Lediglich bei Supraleitung, also Nahe des absoluten Temperaturnullpunktes wäre ein Flusserhalt möglich. Unter "normalen" Umständen vergisst das Flipflop alles und nimmt nach dem Auftauen eine zufällige Rotationsrichtung an. Das Flipflop hat seine Vergangenheit schlichtweg vergessen.

Unser Gehirn besteht aus Nervenzellen, Neuronen, die sich untereinander vernetzen -- das materielle "Schaltungsbild" unseres Denkapparats. Auch hier ist Rückkopplung der Schlüssel zu unserem Gedächtnis. Ohne Rückkopplung wären wir im wahrsten Sinne des Wortes zu keiner "reflektierten" Handlung fähig. Der Teil unseres Denkens, der sich nicht in der Vernetzung der Neuronen niedergeschlagen hat, "kreist" auf diesen rückgekoppelten Bahnen. Würden wir unser Gehirn einfrieren, käme es zum Stillstand des Denkens und aller Erinnerungen, die in uns ihre Kreise ziehen. Dumm gelaufen.

Also: Legen Sie lieber ein Bit ins Gefrierfach! Auch dumme Hefe löscht den Durst!

Samstag, Oktober 06, 2007

Get Lively


Yesterday (Friday, Oct 5, 2007), Dan Ingalls announced the Sun Labs Lively Kernel on the squeak-dev mailing list. Squeak is an implementation of the Smalltalk programming language and Dan Ingalls is one of the lead developers of Squeak. So, you might guess what Lively is?! Something that is very close in spirit and conception to Smalltalk. You've never heard of Smalltalk? Never mind, have a look at Lively, it's fascinating and quite cool -- and completely implemented in JavaScript using SVG capabilities of a web browser.

The main goal of the Lively Kernel is to bring the same kind of simplicity, generality and flexibility to web programming that we have known in desktop programming for thirty years, but without the installation and upgrade hassles than conventional desktop applications have.

[...]

The Lively Kernel places a special emphasis on treating web applications as real applications, as opposed to the document-oriented nature of most web applications today. In general, we want to put programming into web development, as opposed to the current weaving of HTML, XML and CSS documents that is also sometimes referred to as programming.

(http://research.sun.com/projects/lively/, 2007-10-06)

If you are interested in Dan Ingalls way of reasoning, read "The Design Principles Behind Smalltalk" -- a document, which is more than 25 years old and still worth reading. Two other members of the Lively Project, Tommi Mikkonen and Antero Taivalsaari, have written another interesting paper, which might help understand, why they developed Lively: "Web Applications - Spaghetti Code for the 21st Century".

By the way, my students and I started analyzing Lively in my course "Modeling Software Architecture". I'm curious on the insights we will gain.

Freitag, September 28, 2007

Ur-Taschenrechner

Mögen Sie einen Blick in die Urzeit des Computerbaus werfen? Bei Spiegel-Online gibt es einen netten Beitrag dazu: "Der erste Taschenrechner wog 1,5 Kilo" (Konrad Lischka, 27. Sep. 2007). Schauen Sie sich mal die Bilder zu den alten Taschenrechnern an! Schaurig schön.

Mittwoch, September 26, 2007

Vom Zählen und vom Sehen

Mein ältester Sohn, bald sechs Jahre alt, hat die vergangenen Tage die "großen Zahlen" für sich entdeckt. Genauer gesagt, er entdeckt das Regelsystem, nach dem Folgen von Zahlen ausgesprochen werden: 3-2-0, dreihundertzwanzig; 1-4-0, einhundertvierzig. Es ist beachtlich, wie hart ein kleines Menschenkind daran üben muss -- einem Computer wäre das in Kürze beigebracht. Ein kurzes Programm würde für immer und ewig "große Zahlen" richtig in Wortfolgen übersetzen. Meinem Sohn müssen wir die Regeln wieder und wieder erklären. Es bewahrt ihn nicht vor Fehlern. Ein mühsamer Prozess, der spielerisch umgesetzt zwar Spaß macht, aber eines schön verdeutlicht: unsere Hirne sind nicht gerade für solche Regeln gemacht.

Auf der anderen Seite habe ich noch keinem meiner Kinder erklären müssen, wie die Regeln fürs Sehen funktionieren. Noch besser, ich kenne sie selber nicht. Innerhalb kürzester Zeit weisen Kinder Fähigkeiten in der Verarbeitung von Bildern auf, die wir bislang weder mit Hochleistungsrechnern noch ausgefuchsten Algorithmen nachbilden können. Die Mühelosigkeit, mit der wir uns in der Welt bewegen und mit unseren Sinnen orientieren können, ist purer Hohn für all die kläglichen Versuche, Computern menschliche Fähigkeiten angedeihen zu lassen. Geht es aber bereits um einfache Regelsysteme, stechen uns die Computer wiederum gnadenlos aus. Auf ihre Weise verstehen es Computer, uns beim Schach den Rang abzulaufen -- da findet ein spannendes Kräftemessen zwischen der Arbeitsweise von Neuronen und der von Computern statt.

Interessanterweise gibt es aber immer wieder Menschen, die ebenfalls mit solchen Regelsystem ausgezeichnet umzugehen wissen: Mathematiker oder Physiker zum Beispiel. Aber auch Musiker. Zum Teil sind es extreme Einzelbegabungen. Faszinierend daran ist, das neuronale Netze auch so etwas beherrschen können. Was ist es nur, was neuronale Netze zu solchen "formalen Leistungen" befähigt? Ich weiß es nicht.

Freitag, September 21, 2007

Computer-basierte Beratung in der Medizin


Die computer-basierte, medizinische Beratung von Patienten wird zunehmend auch in Deutschland als ein hilfreicher Baustein in der Vorsorge und Therapie entdeckt. Auf dem Bild sehen Sie ein solches Beratungssystem im Einsatz. Der Patient interagiert mit dem drucksensitiven Bildschirm des TabletPCs über einen speziellen Stift. Zum Einsatz kommt dieses System gerade in einer Studie, die in Praxen von Hausärzten durchgeführt wird.

Dieses Beratungssystem ist entwickelt worden im Rahmen einer Forschungskooperation der Hochschule Heilbronn und der Philipps-Universität Marburg. Dafür hat sich ein interdisziplinäres Team zusammengefunden aus Medizinern, Psychologen und Software Engineers. Sie dürfen raten, an welchem Teil ich beteiligt bin :-)

Die erste Fassung der Beratungssoftware ist übrigens im vergangenen Sommersemester 2007 an der Hochschule Heilbronn im Rahmen einer Veranstaltung entstanden, dem "Labor für Software Projekte". Mittlerweile ist die Software neu geschrieben und weiter entwickelt worden.

Bei der aktuellen Untersuchung, die die Marburger Mediziner und Psychologen derzeit mit dem Beratungssystem durchführen, geht es um eine Akzeptanzstudie. Untersucht werden chronisch erkrankte Patienten; im konkreten Fall Patienten mit diabetes mellitus (im Volksmund "Zuckerkrankheit") und/oder einer Erkrankung der Herzkranzgefäße. Da körperliche Aktivierung ein wichtiger Bestandteil der Therapie bei diesen Erkrankungen ist, versucht das Beratungssystem den Patienten eine angepasste Beratung zum Thema geben. Welche Bedeutung hat körperliche Aktivität? Wie lässt sich mehr körperliche Aktivität im Alltag einbinden? Bevor das Beratungssystem darauf eingeht, ermittelt es durch Fragen die Motivationsstufe des Patienten bzw. der Patientin (Grundlage ist das Transtheoretische Modell, TTM) und leitet dann über in eine stufenspezifische Beratung.

Wir haben das System diese Woche (Ende September 2007) auf dem 8. Kongress für Gesundheitspsychologie und dem 41. Kongress der Deutschen Gesellschaft für Allgemeinmedizin und Familienmedizin (DEGAM) vorgestellt und positives Feedback erhalten. Eine weitere Vorstellung wird es im November auf der USAB 2007 (Usability & HCI for Medicine and Health Care) geben.

Wenn Sie Interesse an einer Beteiligung, Mitarbeit oder Kooperation als Mediziner, Psychologe oder Informatiker haben, ich würde mich freuen, wenn Sie sich bei mir melden.

Für die Software-Techniker unter Ihnen: Über die software-technische Aspekte werde ich in einem späteren Blogeintrag berichten.

Freitag, Juli 13, 2007

Blogpause

Liebe Blogleser(innen), ich werde mir eine Blogpause gönnen bis Mitte September. Eine Denkpause wird es nicht sein, es gibt interessante Projekte, die ich in dieser Zeit vorantreiben möchte. In dem einen Projekt wird es gehen um formale Grundlagen zur Aspekt-Orientierung -- ein Thema, was mich schon länger beschäftigt. Neu dagegen ist eine Entdeckung, Verhältnisse in Raum und Zeit mit Hilfe einer Prozessalgebra zu beschreiben. Damit kann man z.B. User Interfaces und Maskenwechsel prototypen und formal verifizieren. Im Augenblick kommt eine pragmatische Version davon in einem medizinischen Beratungssystem zum Einsatz.

Dann liegt noch einiges andere an: ein Queue-Konzept, bei dem sich Consumer und Producer gegenseitig über die Queue synchronisieren können. Ein Anfang zu einem Tutorial zu Alloy soll entstehen. Und und und.

Natürlich werde ich bis zum Beginn der Vorlesungen im Wintersemester nicht mit allem durchkommen. Aber sicher werde ich von dem einen oder anderen Ergebnis nach der Blogpause berichten. Bis dahin wünsche ich allen eine gute Zeit.

Montag, Juli 02, 2007

Editing and Persistence



In this post, I want to present a generalization of the ideas, which are behind HTML, CSS and JavaScript. We will end up with a broad understanding of what is meant by editing und persistence in the context of an object model.

Most of you know HTML, the HyperText Markup Language, which is at the heart of web technology. For those who don't know it: The content of a web page is described with HTML. HTML structures the content of a web page hierarchically. Furthermore, the content is annotated by so-called tags. A tag indicates the logical purpose of a piece of content. Is some content supposed to be a header, a paragraph, a highlighted word etc.? For further info see e.g. Wikipedia on HTML or any other of the hundreds of resource about HTML.

HTML is flanked by two other guys. One guy is called CSS, the other JavaScript. When you look at a HTML page in a browser, the graphics engine (the rendering engine) takes the HTML stuff and calculates a visual presentation out of it. There are some predefined rules, which let a header, for instance, appear in big, fat letters. With CSS (Cascading Style Sheets) you can define your own style information. You can do quite some fancy things with CSS in order to change the default behavior of the rendering engine. Have a look at CSS Zen Garden -- the same content is presented in astonishingly different ways, just the CSS is exchanged.

Before we come to the other guy, JavaScript, you have to know that your browser internally converts HTML into an alternative representation, an object model called DOM (Document Object Model). It's a data structure, which represents HTML in form of a tree. The fun part is that the tree has a defined interface (we call it an API, Application Programmer Interface) to inspect the tree, navigate through it, add or delete nodes or node attributes. You couldn't do this in HTML. So once HTML is consumed by the browser, HTML "disappears" and continues to live in the browser in a different form: as a DOM. The object model can be traversed at any time and the HTML form can be reconstructed. An HTML page can be transformed into DOM and vice versa.

JavaScript is a programming language all browsers understand. With JavaScript you can manipulate HTML and CSS via DOM. CSS is also accessible via DOM. This gives you quite some power to dynamically change content and its appearance. It's the miracle behind some fancy visual effects, web designers create on some web pages with JavaScript.

In addition, JavaScript can overwrite all standard reactions on user initiated events. When you click on a link with the mouse, you usually get transferred to a new location in the web and a new web page is opened. With JavaScript you can do something else and generate a new user experience.

As I said at the very beginning: What I am after in this post is to generalize the ideas, which are behind HTML, CSS and JavaScript. So, let's look at the figure above. The object model captures three aspects: form, style and syntax.

We call the logical model of a language (like HTML) its form. The form contains language conceptions and their relations. Together with a syntax definition, a notation, the logical model can be serialized as a stream of characters. It's a both way thing. The character stream can be transformed into a form and vice versa. In case of HTML, it's the HTML syntax, the textual form which is send as messages via HTTP.

To produce a projection, a visual representation of the form, the rendering engine processes the form and a style definition -- something like CSS, for example. That's the way, how something appears on the screen.

Events that are generated by e.g. the user and timers are digested by a processor, something like a JavaScript interpreter. The processor can modify the object model in any way. A modification has an immediate effect on the projection. The projection always presents the current "shape" of the form.

The upper part of our figures makes up what can be called editing, the lower part realizes persistence.

Just some years ago, the traditional form of writing code had a misconception (and it's still widely spread): To edit code one uses a more or less advanced text editor. If you call the structure of a programming language its form and its textual notation its syntax, it's somewhat strange why one wants to work on a serialization format and not on the form directly, benefiting from advanced projections and a powerfull I/O-model. That is where modern IDEs like Eclipse move to. Internally, Eclipse builds up a model of the code, which represents its form -- technically speaking, it is an Abstract Syntax Tree (AST). This give you cool features like automated refactoring, word completion etc. However, the actual syntax of, say, Java or C#, is too restricted and too simple, to be an suitable snapshot of the code's form. And that's a pitty. There are only very few new approaches, like Intentional Programming, which realized the limitations a today's code syntaxes.

To summarize, what we discussed here:

HTML is just a serialization format for the exchange of content that is otherwise represented in form of an object model called DOM. This serialization format is the prerequisite to send content around in HTTP messages. But the HTML format is nothing a browser works internally with. It's the object model instead.

If we apply the editing/persistence-model on programming languages, we have to conclude that programming languages are historically driven by a text-based serialization format, which is -- today -- not appropriate anymore.

Dienstag, Juni 26, 2007

Kann man Programmieren lernen?

Kann man das Programmieren erlernen? Sicher! Aber kann es jeder erlernen?

Ich bin über einen Blog auf einen interessanten Artikel gestossen ("The camel has two humps (working title)" von Saeed Dehnadi und Richard Bornat). Darin berichten die Autoren von den vielen vergeblichen Versuchen, die es gegeben hat, das Programmieren erfolgreich zu unterrichten. Denn zwischen 30 und 60 Prozent der Studierenden an Universitäten und Hochschulen scheitern regelmäßig am ersten Programmierkurs. Bei allen Bemühungen: Die hohen Durchfallquoten scheinen unabänderlich zu sein.

Die Autoren behaupten, die Programmierbegabung mit einem Test ermitteln und damit vorhersagen zu können, ob ein Kandidat bzw. eine Kandidatin das Programmieren erfolgreich erlernen wird. Ich halte die durchgeführte Studie für methodisch kritisch, darum sind die Aussagen und Spekulationen mit großer Vorsicht zu genießen. Dennoch lassen Sie uns einmal anschauen, was Dehnadi und Bornat da untersucht haben.

Die beiden gehen davon aus, dass sich dem Programmierunerfahrenen, dem Novizen, beim Umgang mit imperativen Sprachen drei Hürden stellen -- und zwar in der angegebenen Reihenfolge:

  • Zuweisungen und Zuweisungsfolgen

  • Rekursion und Iteration

  • Nebenläufigkeit


In einem Test stellen Dehnadi und Bornat den Studierenden vor dem ersten Kontakt mit einer Programmiersprache einige Fragen zu Zuweisungen bzw. zu Folgen von Zuweisungen; sie testen also lediglich die erste Hürde. Die Probanden müssen via Multiple Choice erraten, welche Werte nach den Zuweisungen gültig sind.

Nach den Tests unterscheiden Dehnadi und Bornat drei Gruppen. Die Annahme ist, dass sich die Probanden ein mentales Modell von der Arbeitsweise von Zuweisungen machen. Versuchen die Probanden, sich bei der Suche nach Lösungen strikt an Regeln zu halten, seien die Ergebnisse auch noch so unsinnig oder seltsam? Oder versuchen sie, etwas sinnvolles aus jeder einzelnen Aufgabe zu holen und entsprechend zu antworten? Oder verweigern sie die Antwort, da diese Zuweisungen wenig Sinn zu machen scheinen? Eine Gruppe, die Konsistenten, beantwortet die meisten bis alle Fragen mit dem gleichen mentalen Modell; das sind die, die sich einer Maschine gleich an ein Regelwerk halten. Die Inkonsistenten sind die, die bei verschiedenen Fragen verschiedene mentale Modelle anwenden; es sind die, die versuchen, jede Zuweisungsaufgabe für sich genommen sinnhaft zu beantworten. Die Blanken verweigern die Antwort auf die meisten oder alle Fragen; sie mögen nicht rätseln, was diese ganze Kryptik für einen Sinn machen soll.

Obwohl jede der drei Gruppen eine absolut vernünftige Strategie für ihr Handeln verfolgt, die durchaus als intelligent bezeichnet werden kann, kommt lediglich das Vorgehen der Konsistenten der Arbeitsweise eines Rechners gleich. Ein Rechner befolgt Regeln der Ausführung und wendet diese stur an. Ob die Ergebnisse Sinn machen oder nicht, hinterfragt ein Rechner nicht.

Interessant ist nun, wie sich die Probanden im Laufe der Zeit entwickeln. Alle belegten einen Programmierkurs und schlossen den Kurs mit einer Prüfung ab. Dehnadi und Bornat wollen nun festgestellt haben, dass einzig die Konsistenten zu bemerkenswert guten oder mittelmäßigen Programmierern werden. Die Inkonsistenten und Blanken bleiben bemerkenswert programmierschwach. Es will fast so scheinen, als lege der frühe Test als Novize die Zukunft in Ketten: einem Inkonsistenten bzw. Blanken scheint der Eintritt in die Programmierwelt verwehrt. Die Autoren schreiben:


[...] it is extremely difficult to teach programming to the inconsistent and blank groups. It might be possible to teach them, if we concentrated on trying to persuade them to see a programming language as a system of rules ([...]).


Vor diesem Hintergrund scheint es besonders fragwürdig, so die Autoren, Java als erste Programmiersprache zu unterrichten. Java wird nicht über ein einfaches Regelwerk definiert, sondern über einen mehrere Hundert Seiten umfassenden Standard.

Mich machen diese Ergebnisse nachdenklich. Was sind die Konsequenzen daraus? Sollten manche Studierenden lieber die Finger von der Informatik lassen, weil ihre Hirne nicht so regelbasiert wie Computer tickern? Andererseits: Nicht jeder Software Engineer muss ein Programmierstar sein. Oder haben wir schlicht noch nicht das richtige Unterrichtsmodell für Programmiersprachen gefunden? Ich hoffe sehr, dass dieser Untersuchung weitere Studien folgen, die besser und erkenntnisreicher sind.

Montag, Juni 18, 2007

Suchen mit Strategie

In den vergangenen Wochen habe ich mich viel mit XML befasst. Für die Verarbeitung eines XML-Dokuments habe ich mir ein Python-Programm geschrieben, das die XML-Darstellung direkt in einen Objektbaum abbildet -- alle weiteren Bearbeitungsschritte führe ich dann in dem Objektmodell aus. Jedes Objekt in diesem Baum hat einen Vorgänger (parent) und keinen oder mehr Nachfolger (childs). Das ist sehr ähnlich zu DOM.

Bei der Verarbeitung einer solchen Baustruktur tritt ein Problem immer wieder auf: Sie suchen Knoten (= Objekte) in dem Baum, die einem oder mehreren Kriterien genügen. Für diese Aufgabe kann man eine sehr flexible query-Funktion programmieren:

def query(criteria):
assert callable(criteria)
result = []
for element in allElements():
try:
if criteria(element) == True:
result.append(element)
except: pass
return result

Dieser query-Funktion übergibt man ein Kriterium in Form eines Lambda-Ausdrucks (das ist eine anonyme, sprich namenlose Funktion; so etwas gibt es jetzt auch in C# 3.0). Zum Beispiel:

query(lambda e: e.tag == "page")

Dieser Aufruf sucht aus dem Objektmodell alle Objekte raus, die in der XML-Darstellung das Tag "page" tragen.

Ein Nachteil dieser Suchabfrage ist, dass alle Elemente (allElements()) durchgegangen werden. Optimiert werden könnte das durch eine Suchstrategie, die nur relevante Elemente nach einem bestimmten Verfahren der Suche zum Test vorlegen würde. Hier die optimierte Version:

def query(criteria,strategy=yieldElements):
assert callable(criteria) and callable(strategy)
result = []
for element in strategy():
try:
if criteria(element) == True:
result.append(element)
except: pass
return result

Dazu zwei Strategien. Die erste Strategie (yieldElements) generiert wie gehabt alle Elemente. Die zweite Strategie (yieldInnerElements) generiert alle Elemente, die im Sinne einer XML-Darstellung "innerhalb" eines gegebenen Elements liegen. Die Strategie ist also parametrisiert.

def yieldElements():
for klass in elementClasses:
for element in klass.instances:
yield element


def yieldInnerElements(element):
def _yieldInnerElements():
def yieldInnerNodes(node):
for n in node.childs:
yield n
for child in yieldInnerNodes(n):
yield child
return yieldInnerNodes(element)
return _yieldInnerElements

Wieder ein Beispiel für eine Abfrage:

query(lambda e: e.tag == "page",yieldInnerElements(chapterOne))

Jetzt werden lediglich die Objekte mit dem Tag "page" herausgesucht, die als Kinder bzw. Kindskinder etc. innerhalb eines chapterOne-Objekts des Objektmodells zu finden sind.

Eine interessante Einsicht ist, dass jede Strategie auch als Teil eines Kriteriums in criteria verstanden werden kann. Die explizite Formulierung einer Strategie optimiert lediglich die Vorlage von Elementen zum Kriteriumstest und beschleunigt das Suchverfahren. Strukturwissen um die Organisation der Daten kann so effizient ausgenutzt werden. Die Parallelen zum Constraint Programming sind kein Zufall!

Donnerstag, Juni 07, 2007

Maschinelles 3D-Sehen

Bislang hat es viele Versuche gegeben, Computern (bzw. Robotern) das Sehen beizubringen -- mit mäßigem Erfolg. Basis für eine erfolgreiche Orientierung im Raum ist die Fähigkeit, die Welt dreidimensional wahrzunehmen. Wir Menschen bekommen das mit unseren zwei Augen hervorragend hin. Und deshalb hat man versucht, das Erfolgsmodell aus der Natur, das "Stereosehen", zu imitieren.

Allerdings ist man damit nicht weit gekommen. Es ist schon bei einem Bild extrem aufwendig und schwierig, aus den zahllosen Bildpunkten abzuleiten, wo Objektgrenzen entlang verlaufen. Bei zwei Bildern wird es nicht weniger einfach, zumal die zwei Bilder in Bezug gesetzt werden müssen und daraus mehr oder weniger präzise eine Information über die Raumtiefe gewonnen werden muss. Das ist so schwierig, dass man es bis heute nicht wagt, autonome Fahrersysteme am "normalen" Straßenverkehr teilnehmen zu lassen. Es gibt auch keine kleinen staubsaugenden oder rasenmähenden Roboter zu kaufen, die sich sicheren Auges zügig durch Wohnung oder Garten bewegen.

Ein Teil des Problems liegt daran, dass unser Stereosehen nur im Nahbereich sehr gut arbeitet. Unsere Augen liegen nur ein paar Zentimeter auseinander, zu wenig, um sehr genaue Entfernungsinformationen daraus berechnen zu können. Information über die Entfernung von etwas wird zu einem großen Teil von unserem Gehirn aus Erfahrungswissen über Größenverhältnisse, Bewegungsverhalten etc. abgeleitet. Das alles zusammen gibt uns die Illusion einer räumlichen Orientierungsfähigkeit, wie sie faktisch durch unseren reinen Sehapparat nicht gegeben ist.

Es ist also fraglich, ob das Stereosehen als Vorlage für maschinelles 3D-Sehen taugt. Müssen wir uns vielleicht nach gänzlich anderen Techniken umschauen? Es gibt sie, die neue Technik des 3D-Sehens, entwickelt von Prof. Dr. Schwarte aus Siegen. Mit Hilfe der PMD-Technologie (PMD steht für "Photonic Mixer Device") liefert eine PMD-Kamera zu jedem Pixel eine Tiefeninformation -- und das bei nur einem Kameraauge! Die Technik ist faszinierend. Sie wird fraglos unsere Zukunft verändern. Können Sie sich das vorstellen? Ein Blick in die Zukunft: In ein paar Jahren halten Sie Ihre Handykamera auf ein Motiv und Sie bekommen ein Raumbild der Szene! Damit ist es für eine Bildverarbeitung ganz einfach, Objektgrenzen in einer Szene zu ermitteln. Denn es wird gesehen, dass das eine Objekt vor oder hinter dem anderen Objekt liegt.

Ich bin sehr gespannt, was diese Zukunft bringen wird. Es werden neue Algorithmen für diese Technik entwickelt werden müssen. Man wird diese neue Technik zu nutzen lernen müssen. Bei aller Begeisterung, die ich dafür aufbringe, es wird sicher 10 oder 15 Jahre dauern, bis diese Technik unseren Alltag zu durchdringen beginnt.

Nehmen wir einmal an, wir sind 20 Jahre weiter und die Maschinen haben keine Probleme mehr beim 3D-Sehen. Dann gibt es immer noch viel zu tun. Was unterscheidet einen Profi-Tennisspieler von einem normalen Tennisspieler? Weder ist es die Fähigkeit zum 3D-Sehen bei der Ballerkennung, noch Reaktionsschnelligkeit. Wenn ein Roboter in der Profi-Liga mitspielen möchte, so muss er lernen zu sehen, was mit dem Ball wahrscheinlich passieren wird, bevor der Ball den Schläger des Gegners verlässt und die Flugbahn berechnet werden kann.

Ähnliches gilt im Straßenverkehr. Gute Autofahrer ahnen vorher, was passieren könnte und verhalten sich entsprechend. Auch hier ist unser Gehirn in der Einschätzung von Verkehrsituationen technischen Lösungen weit voraus. Wir werden das Problem mit Computern anders lösen müssen, analog zum 3D-Sehen: nicht das Vorbild imitieren, sondern technische Lösungen finden, die qualitativ ähnliches leisten, aber die Stärken der Technik ausnutzen.

Mittwoch, Mai 02, 2007

Zahlenspielerei

In meinem Blogeintrag "Hochstapelei" habe ich Ihnen gezeigt, wie sich rein mit den Mitteln der Objekt-Orientierung ein Stack realisieren lässt. Zur Konstruktion eines solchen Datentyps reicht es vollkommen aus, mit Konstruktoren, Methoden, Attributen und der Möglichkeit des Vergleichs von Objekten zu arbeiten. Keine sonstigen eingebauten Operationen, kein weiterer Datentyp (außer Bool) ist nötig.

Auf die gleiche Weise lassen sich auch die natürlichen Zahlen inklusive Null als Typ einführen. Das Geheimnis liegt wieder in der Nutzung des Konstruktors verborgen; das Beispiel ist in Python umgesetzt. Wir machen uns eine Zahlendarstellung zu nutze, die ihren Ursprung in der Mathematik hat: Ausgehend von der Zahl Null ist jede andere Zahl ein Nachfolger von Null. Eine Rangordnung wird hergestellt durch eine Nachfolgekette. Wir nennen den direkten Nachfolger von Null "Eins", den Nachfolger von Eins "Zwei" usw. Ein Nachfolger einer Zahl wird durch die Methode "inc" (inkrementiere) generiert. Der Vorgänger einer Zahl kann mit der Methode "dec" (dekrementiere) ermittelt werden. Eine Zahl heißt "Null", wenn sie keinen Vorgänger hat.

class Number(object):
def __init__(self,predecessor=None):
assert isinstance(predecessor,type(None)) or \
isinstance(predecessor,type(self))
self.predecessor = predecessor
def is_zero(self):
return isinstance(self.predecessor,type(None))
def inc(self):
return Number(self)
def dec(self):
assert not isinstance(self.predecessor,type(None)),\
"Number is not zero"
return self.predecessor

Eine wichtige Methode, die nicht fehlen sollte, überprüft die Gleichheit von zwei Zahlen. Zwei Zahlen sind dann gleich, wenn Sie die gleiche Anzahl von Vorgängern haben. Das Konzept der "Anzahl" ist jedoch nicht zugreifbar, da wir just dabei sind Zahlen zu definieren. Doch es gibt einen kleinen Kniff, der uns das Problem löst: Rekursion. Wir dekrementieren die zu vergleichenden Zahlen gemeinsam so lange, bis entweder beide Zahlen Null sind oder nur eine Zahl Null ergibt. Im ersten Fall (beide Zahlen sind Null) wissen wir, dass die Zahlen gleich sein müssen; ist nur eine Zahl Null, liegt Ungleichheit vor.

Aus praktischen Gründen überschreiben wir die Gleichheitsmethode "__eq__" von Python, um den Vergleichsoperator "==" einsetzen zu können.

def __eq__(self,number):
assert isinstance(number,type(self))
if self.is_zero() and number.is_zero(): return True
if self.is_zero() or number.is_zero(): return False
return self.dec().__eq__(number.dec())

Einem erfahrenen Python-Programmierer wird im ersten Code-Fragment aufgefallen sein, dass ich "self.predecessor" nicht direkt mit None vergleiche, sondern den vielleicht etwas umständlich anmutenden Umweg über "isinstance" gehe. Grund ist die "__eq__"-Methode. Ich kann keine Number mit None vergleichen, ohne den Aufruf von "__eq__" zu provozieren. Dort will ich aber nur einen Vergleich zweier Zahlen implementieren, nicht den Vergleich mit None.

Eine weitere Methode setzt den plus-Operator um. Die "__repr__"-Methode gibt eine geeignete Repräsentation eines Number-Objekts aus.

def plus(self,number):
assert isinstance(number,type(self))
if number.is_zero(): return self
return self.inc().plus(number.dec())
def __repr__(self):
if self.is_zero(): return "0"
return "1+%s" % self.predecessor

Wenn Sie ein wenig Zahlenspielerei mögen, dann tippern Sie doch auf der Console zum Beispiel Folgendes ein:

>>> zero = Number()
>>> zero
0
>>> one = zero.inc()
>>> one
1+0
>>> two = one.inc()
>>> one == Number(Number())
True
>>> one == Number().inc()
True
>>> three = one.plus(two)
>>> three
1+1+1+0
>>> five = three.plus(Number().inc().inc())
>>> five
1+1+1+1+1+0
>>> five.dec()
1+1+1+1+0

Beschleicht Sie übrigens so ein komisches Gefühl? Sind das nicht komische Zahlen, die sich über die Idee der Nachfolge realisieren? Ist das nicht Kindergarten-Arithmetik, die Addition (plus) auf so eine alberne "Nimm weg, gib woanders dazu"-Art zu definieren?

Lassen Sie sich von der Einfachheit und der Speicherineffizienz nicht täuschen. Die Verwendung von z.B. Binärzahlen ist lediglich eine speichereffiziente Ablage einer Zahl. Auch die binäre Addition (0+0=0, 0+1=1, 1+0=1, 1+1=0 mit einem Übertrag von 1) kann man als optimierten Algorithmus für die binäre Zahlendarstellung verstehen.

Freitag, April 27, 2007

Hochstapelei

Wissen Sie, was ein Stack ist? In der Informatik ist damit eine Datenstruktur gemeint. Auf einem Stack, zu deutsch "Stapel", können Sie Datenelemente ablegen und wieder entfernen. Ein Stack organisiert die Datenablage in einer Form, die man mit "last in, first out" bezeichnet: Das letzte auf einem Stapel abgelegte Element ist auch das erste, das Sie wieder vom Stapel nehmen können.

Für einen Stapel ist eine Handvoll Methoden definiert. Der Konstruktor, der einen Stack erzeugt; eine push-Methode, mit der Sie ein Element auf dem Stack ablegen können; eine top-Methode, die Ihnen verrät, was "oben" auf dem Stack liegt (das Element verbleibt auf dem Stack); eine pop-Methode, die Ihnen das oberste Element vom Stack entfernt; und eine is_empty-Methode, mit der sich feststellen lässt, ob ein Stack leer ist oder nicht.

Wenn Sie einen Stack in einer OO-Sprache umsetzen wollen, dann ist eine typische Vorgehensweise die Folgende: Sie suchen eine Datenstruktur, die Ihre Programmiersprache anbietet und die der Idee und Arbeitsweise eines Stacks so nahe kommt wie möglich. Diese Datenstruktur "verbergen" Sie dann hinter den Methoden.

Zum Beispiel bietet die Liste oder ein Array eine einigermaßen gute Implementierungshilfe. Ihre Umsetung (hier in Python) könnte wie folgt aussehen; ich greife dabei auf die interne Datenstruktur der Liste zurück.

LAST = -1

class Stack1(object):
def __init__(self):
self.elements = []
def push(self,element):
self.elements.append(element)
def top(self):
assert not self.is_empty()
return self.elements[LAST]
def pop(self):
assert not self.is_empty()
self.elements.pop()
def is_empty(self):
return self.elements == []

Wie Sie sehen, ist die Verwendung der Liste wirklich naheliegend. Es gibt Methoden, wie zum Beispiel "pop", die für Listen direkt angeboten werden und den gewünschen Effekt haben. Andere Methoden, hier etwa "append", firmieren für die Liste lediglich unter einem anderen Namen. Der Stack präsentiert sich als eine für einen besonderen Einsatzzweck zurückgeschnittene Liste. Übrigens, die eingestreuten assert-Statements sind als PreConditions zu verstehen. Mehr dazu finden Sie in meinem Beitrag "Design by Contract in Practice".

Geht es auch gänzlich anders? Was, wenn uns keine anderen Datentypen als Annäherung oder Hilfsmittel zur Verfügung stehen? Lässt sich rein mit den Boardmitteln der Objekt-Orientierung ein Stack umsetzen? Reicht der Einsatz von Konstruktoren, Attributen und Methoden aus?

Ja, es geht -- unter einer winzigen Voraussetzung: Sie müssen die Möglichkeit haben, Attributwerte auf ihre Gleichheit hin zu überprüfen. Am Rande: Das belegt, wie fundamental die Idee der Gleichheit in der Informatik ist; eng damit verwandt ist die Idee der Identität.

class Stack2(object):
def __init__(self,top=None,bottom=None):
assert (top,bottom) == (None,None) or \
isinstance(bottom,Stack2)
self.ontop, self.bottom = top, bottom
def push(self,element):
return Stack2(element,self)
def top(self):
assert not self.is_empty()
return self.ontop
def pop(self):
assert not self.is_empty()
return self.bottom
def is_empty(self):
return self.bottom == None

Diese zweite Variante eines Stacks ist nicht eine Zeile länger als die erste. Und doch ist hier vieles anders. Diese Stack-Klasse hat zwei Attribute, "ontop" und "bottom". Das Attribut "ontop" repräsentiert das oberste Element auf dem Stack, "bottom" den "Rest" darunter. Dieser "Rest" kann None oder seinerseits ein Stack sein. Ein Stack mit "bottom" gleich None steht für einen leeren Stack; aus diesem Grund fordert auch das Assert-Statement im Konstruktor ein None für "top" ein. Denn ein leerer Stack, der einen "ontop"-Wert hat, das verwirrt und macht keinen Sinn.

Das ganze Geheimnis der Funktionsweise dieses Stacks liegt in der Verwendung des Konstruktors. Im Konstruktor wird ein "top"-Wert für das oberste Element und ein darunter liegender Stack eingefordert, um die Datenstruktur aufbauen zu können. Die Methoden "top" und "pop" sind nur Abfragen dieser im Konstruktor übergebenen Werte. Konsequenterweise verändert sich damit das Verhalten der "push"-Methode. Sie wird zum Generator neuer Stack-Objekte. Das Ablegen eines Elements auf einem Stack erzeugt einen neuen Stack, mit dem Element als "ontop" und dem vormaligen Stack als "bottom".

Dieses Beispiel zeigt zwei Dinge schön auf:

Zum einen ist es faszinierend zu sehen, wie man im Grunde rein mit Konstruktoren und Attributen alles zur Verfügung hat, um einen Stack zu realisieren. Es wird im Hintergrund keine Liste mehr benötigt, wie noch in der ersten Variante. Objekt-Orientierung ist, wenn Sie so wollen, in sich selbst abgeschlossen. Sie können sich eine Datenwelt erschaffen, ohne auf andere Datentypen zurückgreifen zu müssen. Mit einer kleinen Ausnahme: Sie müssen Objekte miteinander vergleichen können. Wenn Sie sich schon einmal mit ADTs (Abstrakten DatenTypen) befasst haben, werden Sie entdecken, dass es sich um die objekt-orientierte Fassung eines Stack-ADTs handelt.

Zum anderen: Es ist unmöglich, Design-Änderungen immer so durchzuführen, dass die Interfaces (die zugreifbaren Methoden) davon unberührt bleiben. Sie können machen, was Sie wollen, Sie bekommen das Interface von Variante 1 und von Vairante 2 nicht irgendwie vereinheitlicht. Die Rückgabewerte sind unterschiedlich. Die beiden Varianten dokumentieren fundamental alternative Design-Ansätze für den Stack. Es ist eine Illusion zu glauben, man könne einmal getroffene Interface-Entscheidungen für alle Zeit beibehalten und einzig und allein gegen Interfaces programmieren. Fundamental unterschiedliche Design-Alternativen ziehen nicht selten Änderungen an den Interfaces nach sich, die weit reichende Konsequenzen haben können. Wer Interfaces fixieren möchte, der schränkt die Suche nach Design-Alternativen erheblich ein.

Das ist eine interessante Lehre für das Software Engineering: So gut und wichtig Interfaces im Softwarebau sind, sie sind kein Wundermittel. Wer Systeme weiterentwickeln möchte, wer sie verbessern möchte, der muss auch bereit sein, Interfaces zu ändern -- mit allen damit verbundenen Konsequenzen.

Freitag, April 13, 2007

Breakpoint mit Farbrausch

Haben Sie auch schon von "Breakpoint 2007" gehört? Vorgestern machte mich Herr Arz auf die Meldung bei golem aufmerksam ("Breakpoint 2007 - Gewinner der Demo-Party stehen fest", 11. April 2007). Das Team "Farbrausch" hat im Bereich "PC-Demo" den Titel geholt. Aus einer gerade mal 180 KByte großen ausführbaren Datei entzaubert "Farbrausch" einen 7minütigen Film -- mir verschlägt sowas den Atem. Ich habe mir das Video auf YouTube angeschaut. Es wirkt fast wie Hexerei!

Machen wir einmal sehr ungünstige Annahmen, was die Bildqualität betrifft: 320 x 200 Bildpunkten mit 8 Bit für die Farbkodierung und 15 Frames pro Sekunde (fps). Das macht für einen etwa 7minütigen Beitrag (7 x 60 Sekunden = 420 Sekunden) eine Datenmenge von 3.225.600.000 Bits aus, sprich 403.200.000 Bytes, also ungefähr 400 MB. Das File kommt jedoch nur mit ca. 180 KB daher! Dem entspricht eine Kompressionsrate um den Faktor 2000 (400/0,18). Ein Kompressionsstandard wie MPEG-2 komprimiert um den Faktor 10-20. Es liegen Welten zwischen 2000 und 20!

Diese Zahlen sollen Ihnen nur ein Gefühl dafür geben, dass hier wahrhafte Künstler ("Hacker" im guten Sinne des Wortes) am Werk sind. Ich habe absichtlich schlechte Annahmen gemacht, der Film von "Farbrausch" ist qualitativ wesentlich hochwertiger. In den 180 KB steckt nicht nur eine Graphik-Engine, auch die "Filmwelt" muss sehr spärlich kodiert sein, die zum Teil mit recht aufwendigen Vorberechnungen erst einmal erstellt werden muss, bevor ein Video ablaufen kann. Sie werden vermutlich einiges an Rechenpower benötigen, damit die 180 KB vernünftig laufen. Und die Audio-Spur habe ich gänzlich vernachlässigt.

Was Sie daraus noch lernen können, und das ist vielleicht als Software-Engineer gar nicht so uninteressant: Ein normaler Kompressionsalgorithmus wie MPEG-2 ist zwar bereits ein Algorithmus für eine besondere Art von Datenmaterial, er arbeitet aber mit recht generellen Techniken zur Kompression von Bildflächen. Was die Hacker da treiben, ist nur zu erreichen mit einer domänenspezifischen Kodierung einer "Filmwelt" -- einer Sprache, wenn Sie so wollen. Mit dieser Spezialsprache ist eine Kompaktheit zu erreichen, die ansonsten undenkbar ist. Domänenspezifische Sprachen haben in der Tat ihren Platz und ihren Sinn. Mit ihnen sind solche Hexereien zu bewerkstelligen.

Dienstag, April 10, 2007

Design by Contract in Practice

Design by Contract (DbC) is a very valuable specification technique -- I already posted about it in German (Netze spannen mit Design by Contract). However, you should be aware that DbC also tends to complicate matters if state is involved. In this case, we need a complementing approach.

To give you a simple example, have a look at a thing called "Account". The "Account" is purely specified via pre- and post-conditions (require and ensure); "context" enables you to capture a context required for a subsequent post-condition. The code is written in a syntax close to Python. A contract precedes the method signature.

class Account(object):
ensure: self.balance == 0
def __init__(self)

require: 0 < amount <= self.balance
context: balance = self.balance
ensure: self.balance == balance - amount
def withdraw(self,amount)

require: amount > 0
context: balance = self.balance
ensure: self.balance == balance + amount
def deposit(self,amount)

context: balance = self.balance
ensure: res == balance
def query(self)

The very first "ensure" specifies that an implementation provides a state preserving instance variable called “self.balance” and that its value is set to 0. The way to specify changes in state (here "self.balance") is shown in "withdraw" and "deposit". If there are no changes in state, "query" gives an example of that.

Now let us add an implementation fulfilling the contracts. It's quite straight forward.

class Account(object):
ensure: self.balance == 0
def __init__(self):
self.balance = 0

require: 0 < amount <= self.balance
context: balance = self.balance
ensure: self.balance == balance - amount
def withdraw(self,amount):
self.balance -= amount

require: amount > 0
context: balance = self.balance
ensure: self.balance == balance + amount
def deposit(self,amount):
self.balance += amount

context: balance = self.balance
ensure: res == balance
def query(self):
return self.balance

Something is weird here: The implementation (4 lines) looks just like a reformulation of the “context” and “ensure” blocks (7 lines). In addition, the implementation is much more easier to grasp and to understand. No doubt, the contracts are way too heavy compared to the implementation. We could easily condense our specification if the implementation is regarded as part of the specification.

class Account(object):
def __init__(self):
self.balance = 0

require: 0 < amount <= self.balance
def withdraw(self,amount):
self.balance -= amount

require: amount > 0
def deposit(self,amount):
self.balance += amount

def query(self):
return self.balance

That's easy and lightweight, isn't it?

Things have become much more simpler, the code is definitely easier to read and to grasp. But is this still a specification? Yes, but the viewpoint has changed. Design by Contract is a technique, which tells you, whether an implementation fulfills the contracts or not. DbC cannot generate answers for you, it can just verify if your answer (an implementation) is valid or not. This is somewhat impractical if a state space needs to be maintained for DbC to verify an implementation; in some sense you’re doing double work. In a purist approach you would maintain independent state spaces: one for specification purposes and another for the implementation. An alternative style is to create an executable specification, which lets you experience the right answers by trying it out. It’s a way to show, what withdrawal, deposition etc. actually do, so that you can understand their behavior. In our example, we mixed both styles, taking advantage of each style, where it fits best.

If you write your code this way, you are coding a specification, which is executable. And that’s quite some fun. The risk is that you start to mix in implementation issues with an eye on performance, optimizations etc. You shouldn’t. You are writing a specification using your favorite programming language. That's it! No more, no less.

Donnerstag, April 05, 2007

Von Beruf Software Engineer

Na, was glauben Sie, wie Ihr Beruf als Software Engineer in 10, 20 Jahren aussehen wird? Zu Beginn des Wintersemesters 2006 habe ich meine Studierenden im Hauptstudium befragt, wie sie die Zukunft des Software Engineering in 10 Jahren sehen. Folgende Liste kam dabei heraus:

  • mehr Konzeption von Software: Anforderungen, Modellierung

  • Software aus Komponenten “zusammenstecken”, Code-Generierung

  • mehr Planung und Organisation von Software-Projekten

  • viel Planung und Kommunikation mit Kunden

  • Hohe Qualitätssicherung bei Outsourcing der Programmierung

  • Teamarbeit: internationale, verteilte Arbeit und Kommunikation

  • Pflege, Weiterentwicklung, Optimierung von Altsystemen

  • sicherer Arbeitsplatz: es entsteht immer mehr Software => Wartung

  • neue Technologien, da HW immer leistungsfähiger wird

  • Entwicklung mit leistungsfähigen CASE-Werkzeugen und IDEs

  • Fortschritte in HMI, Webtechnologie, KI, Virtual Reality, …

  • Notwendigkeit ständiger Weiterbildung

  • es wird eine neue Programmiersprache geben => weniger Fehler

  • Agile Softwareentwicklung als Standard


Eine interessante Liste, nicht wahr? Andere interessante Gedanken hat sich Hans Beck in Telepolis gemacht. Er geht davon aus, dass Software-Entwickler es lernen müssen, sich in abstrakten (Denk-)Welten zu bewegen ("Von der Notwendigkeit, sich in abstrakten Welten bewegen zu können", 28. März 2007). Ein, wie ich glaube, lesenswerter Artikel.


--
P.S.: Da nicht jeder mit den Abkürzungen oben vertraut ist: HW (Hardware), CASE (Computer Aided Software Engineering), IDE (Integrated Development Environment), HMI (Human Machine Interface), KI (Künstliche Intelligenz)

Mittwoch, März 28, 2007

Was ist Software-Architektur?



Was ist Software-Architektur? Wenn Sie nach einer Definition im Internet recherchieren, werden Sie auf eine Unmenge von Vorschlägen stoßen. Wenngleich kein vollkommener Konsens besteht, so findet die Definition von Bass et al. (Software Architecture in Practice, 2nd Ed., Addison-Wesley, 2003) offenbar den meisten Anklag. In der deutschsprachigen Literatur zum Thema wird sie auch gerne herangezogen.

The software architecture of a program or computing system is the structure or structures of the system, which comprises software elements, the externally visible properties of those elements, and the relationships among them.

Ich halte diese Definition für zu kurz gegriffen -- Sie stimmt nicht mit meinen Erfahrungen aus der Praxis überein. Architektur hat nach meinem Verständnis sehr viel mit Ökonomie zu tun.

Die Architektur ist die ökonomischste Form der Beschreibung "innerer" Anforderungen, die nicht mit der Implementierung des Systems identisch ist.

Unter den "inneren" Anforderungen verstehe ich alle Maßgaben an eine Implementierung, der sich eine Organisation unterwirft (siehe auch das Bild). Das beschränkt sich nicht einzig auf Blaupausen zur Software-Organisation und arbeitsteiligen Entwicklung (dem Design), sondern bezieht auch Qualitätsmerkmale mit ein. Ob ein Softwaresystem fehlertolerant, wartbar etc. sein soll, interessiert den Kunden herzlich wenig. In der Realität ist diese Sicht etwas zu schwarz/weiß, aber sie soll klar machen, dass es Gesichtspunkte bei der Architektur gibt, die sich eine Organisation auferlegt, z.B. um ihr Software-Produkt am Markt für ein, zwei Jahrzehnte(!) am Markt positionieren und halten zu können. Es gibt Dinge, die müssen weit über den Horizont eines Kunden entschieden und bei der Software-Entwicklung durchgesetzt werden.

Am Dienstag, 27. März 2007, habe ich meine Sicht der Dinge zusammen mit weiteren Ausführungen im Workshop "Software-Architektur und Migration" im Rahmen der Konferenz "Software Engineering 2007" zur Diskussion gestellt. Ich schloss meinen Vortrag (Titel: "Was ist Software-Architektur? Ein Abgleich mit der Praxis") mit folgendem Fazit:

  • Architektur ist Ausdruck der "internen" Anforderungen

  • Architektur unterliegt ökonomischen Antriebskräften

  • Komponenten-Orientierung und Sichtkonzepte greifen als Modellierungsparadigmen für Architekturen zu kurz

  • Modellierungsansätze müssen Domänen-Modelle integrieren

  • Es fehlt eine Methodik zur Architekturmodellierung


Zu meiner eigenen Überraschung erhielt ich in vielen Punkten Zustimmung; es entstand eine lebhafte Diskussion. Möglicherweise (die Diskussionen dazu waren zu kurz) habe ich den Nerv eines Problems getroffen. Auf alle Fälle gibt es zum Thema "Software-Architektur" noch einiges zu forschen und zu bewältigen. Wir sind noch lange nicht am Ende eines umfassenden Verständnisses von Software-Architektur angekommen.

Montag, März 26, 2007

"Open, reusable object models" in Python

It's roughly three or four weeks ago that I read an interview with Alan Kay ("Alan Kay: The PC Must Be Revamped—Now", CIO Insight, Feb 14, 2007). I found it quite inspiring, began surfing the Internet for more material and finally stumbled across Ian Piumarta's paper "Open, reusable object models" (2007/2/7) (see here also). I was fascinated by all the claims stated in the paper and started to have a closer look. Finally, in order to really understand what he did, I started coding his concept world in Python (my favourite programming language). The code is shown below. It's very close to the pseudo code used in the paper on page 5.

Before you have a look at the Python code, some remarks.

After the third rework of my code, I started renaming concepts. For my taste, e.g. "vtable" is not so intuitive. You will see that I introduce a "Object" class, a "ObjectBehavior" class and a "BehaviorBehavior" class in the code. Furthermore, I changed the names for the methods. They are now called "addClosure", "lookupClosure", "createObject", and "createBehavior". I think, the intentions of the object model get much clearer with the names changed.

When it comes to bootstrapping, I think that the code in Fig. 15 does not precisely re-construct the object model as shown in Fig. 5. When you look at the Python code, you'll see that the hard coded approximation and the bootstrapped model match quite nicely. This was also a main motivation to change names, as mentioned above. I have the feeling that it's now somewhat easier to see what is done in the paper and how the object model is "born".


lookupClosure = "lookupClosure"
addClosure = "addClosure"
createObject = "createObject"
createBehavior = "createBehavior"

class Closure(object):
def __init__(self,method,data=None):
assert callable(method)
self.method = method
self.data = data

def eval(self,obj,*args,**kwds):
assert isinstance(obj,Object)
return self.method(self,obj,*args,**kwds)

class Object(object):
def __init__(self,behavior,data=None):
assert isinstance(behavior,ObjectBehavior)
self.behavior = behavior
self.data = data

class ObjectBehavior(Object): # formerly 'VTable'
def __init__(self,behavior,delegate=None):
assert isinstance(behavior,BehaviorBehavior)
assert delegate == None or isinstance(delegate,ObjectBehavior)
Object.__init__(self,behavior,{})
self.delegate = delegate

class BehaviorBehavior(ObjectBehavior): # formerly 'VTableVTable'
def __init__(self):
ObjectBehavior.__init__(self,self)

def _addClosure(context,obj,key,closure): # see 'addMethod' (Fig. 10)
obj.data[key] = closure

def _lookupClosure(context,obj,key): # see 'lookup' (Fig. 11)
if key in obj.data:
return obj.data[key]
if obj.delegate != None:
return send(obj.delegate,lookupClosure,key)
return None

def _createObject(context,obj,data=None): # see 'allocate' (Fig. 12)
return Object(obj,data)

def _createBehavior(context,obj,delegate=None): # see 'delegated' (Fig. 13)
return ObjectBehavior(obj,delegate)

addClosureClosure = Closure(_addClosure)
lookupClosureClosure = Closure(_lookupClosure)
createObjectClosure = Closure(_createObject)
createBehaviorClosure = Closure(_createBehavior)

def send(obj,messageName,*args,**kwds): # see 'function send()' p.5
assert isinstance(obj,Object)
closure = bind(obj,messageName)
return closure.eval(obj,*args,**kwds)

def bind(obj,messageName): # see 'function bind()' p.5
assert isinstance(obj,Object)
if obj.behavior == obj:
closure = lookupClosureClosure.eval(obj,messageName)
else:
closure = send(obj.behavior,lookupClosure,messageName)
return closure

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Bootstrap the object universe (Fig. 15)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

_bb_ = BehaviorBehavior()
addClosureClosure.eval(_bb_,addClosure,addClosureClosure)
send(_bb_,addClosure,lookupClosure,lookupClosureClosure)
send(_bb_,addClosure,createObject,createObjectClosure)
send(_bb_,addClosure,createBehavior,createBehaviorClosure)

_b_ = send(_bb_,createBehavior,delegate=_bb_) # just an example
_o_ = send(_b_,createObject) # just an example


Any comments are welcome.

Mittwoch, März 21, 2007

Factor: In der Kürze liegt die Würze

Es gibt eine Sprache, die mich immer wieder und zunehmend irritiert: Factor von Slava Pestov. Factor steht in der Tradition von Forth und ist eine rein stack-basierte Sprache. Die angepriesenen Features auf der Factor-Webseite klingen erstaunlich genug, um einen genaueren Blick auf die Sprache zu werfen:

Factor is a general purpose, dynamically typed, stack-based programming language.

Factor has an optimizing native compiler, automatic memory management with a generational garbage collector, a powerful collections library, and various advanced language features such as higher-order programming, continuations, and extensible syntax.

Factor development is done in an interactive environment with a graphical user interface. There is a single-stepping debugger which can travel backwards in time, and extensive documentation. An easy to use C library interface allows one to call C libraries without writing any glue code in C. Bindings for OpenGL, FreeType, X11, Cocoa, and Windows APIs are provided.

Ein faszinierendes Spektrum an Eigenschaften, nicht wahr?

Ich verfolge seit einiger Zeit den Blog von Pestov zu Factor. Was mich erstaunt, ist die Kürze der Programme. Ein paar Beispiele: Das Framework zum Unit-Testing ist kaum eine DIN A4-Seite lang. Pretty Printing sieht von der Codemenge her ebenfalls kurz aus. So manch ein Programm, hier Topological Sort oder ein Sudoko-Solver, präsentiert sich in aufreizender Kürze.

Zum ersten Mal wurde ich auf die Kompaktheit von Factor-Programmen aufmerksam durch doctest, ein Modul, das es auch für Python gibt und dessen Code ich mir irgendwann einmal angeschaut habe. Es sieht nicht so aus, dass das doctest-Modul für Factor mit der selben Power daher kommt. Aber selbst wenn es sich bei Factor nur um eine Realisierung eines Proof-of-Concepts hielte, es schlägt an Kürze alles, was ich von Python oder einer anderen Sprache her kenne. Das hat natürlich unter anderem mit der syntaktischen Einfachheit von Factor zu tun.

Was ist der Grund, dass Factor es erlaubt, so kurze, knackige Programme zu schreiben? Ich habe mich noch nicht ausreichend mit der Sprache beschäftigt, als dass ich wirklich verstanden hätte, mit welchen "Gewürzen" Factor diese Kürze erreicht.

Donnerstag, März 15, 2007

Rechnen mit Quanten, Quanten rechnen

Interessieren Sie sich für Quantenmechanik? Vielleicht wird es einmal Computer geben, die mit so genannten Qubits (Quantenbits) arbeiten. Ganz absurd ist der Gedanke heute nicht mehr, aber die Realisierung solcher Maschinen erweist sich bislang als gar nicht so einfach. Die Technologie dazu steckt in den Kinderschuhen, man ist weit entfernt von einem PC-Ersatz. Doch wer weiß, in 20 Jahren gehören Qubits womöglich zu den "Grundlagen der Informatik". Ich würde mich darüber freuen, weil das völlig interessantes Zeugs ist.

Wenn Sie zu dem Thema "Quantenrechner" herumsurfen, werden Sie interessantes Material finden. Hin und wieder geistern ja auch Meldungen dazu über die Nachrichtenticker. Worüber ich die Tage stolperte, war der Blog-Eintrag "Independence, entanglement and decoherence with the quantum monad". Hier geht es weniger um Quantenrechner als um das Rechnen mit Quanten, was im wesentlichen Wahrscheinlichkeitsrechnung ist. Das Faszinierende daran ist für mich, wie man sich Quantenmechanik programmierbar machen kann. Der Autor verwendet dazu Haskell und ein besonderes Konstrukt, die Monade. Haskell ist eine rein funktionale Programmiersprache; funktionale Sprachen sind vollkommen zustandsfrei. Monaden sind gewissermaßen ein Kunstgriff, Zustände durch die Funktionen zu pipen, ohne dabei das funktionale Paradigma zu verletzen.

Was mich aber endgültig an dem Blog-Eintrag in den Bann zog, war Folgendes: Der Autor betrachtet ein System, das sich zusammensetzt aus Umgebung (environment) und Subsystem. So lange beide unabhängig sind, sind beide isoliert voneinander studierbar. Er sagt, dass wir mit der Vorstellung vertraut sind, dass der Zufluss von etwas in das System, das Ganze (die isolierte Betrachtung) über den Haufen werfen kann. Er zeigt aber auch, dass der Abfluss von etwas aus dem System es ebenfalls "vermasseln" kann -- und das entspricht nicht mehr unbedingt unserer Intuition.

Ich finde diese Gedanken sehr interessant, auch wenn ich die Quantenrechnerei dahinter nicht wirklich verstehe. Können wir das übertragen auf den Umgang mit komplexen Softwaresystemen? Gibt es da Analogien? Vielleicht weiß ich das in 20 Jahren ;-)

Wie auch immer. Wen das Rechnen mit Quantenphänomenen weniger interessiert und wer loslegen möchte, ein Quanten-Linux zu programmieren, nur zu: hier eine Simulation ("A lambda calculus for quantum computation") von André van Tonder dazu.