<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5556918437810598389</id><updated>2011-12-21T13:58:10.754+01:00</updated><category term='Team'/><category term='Idee'/><category term='Software Engineering'/><category term='SpiderMonkey'/><category term='MSP'/><category term='clojure'/><category term='3d'/><category term='Patching'/><category term='C'/><category term='Walid Taha'/><category term='medina'/><category term='type inference'/><category term='Parser Combinator'/><category term='reguläre Ausdrücke'/><category term='Parsing'/><category term='Prolog'/><category term='weihnachten'/><category term='chrome'/><category term='Master Thesis'/><category term='Chomsky-Hierarchie'/><category term='Testing'/><category term='DOM'/><category term='buch'/><category term='DSL'/><category term='Typen'/><category term='Stipendium'/><category term='Fehler'/><category term='Parser'/><category term='philosophie'/><category term='ActionMonkey'/><category term='POJO'/><category term='Qubit'/><category term='float'/><category term='Threading'/><category term='Service'/><category term='System'/><category term='CSS'/><category term='Projekt'/><category term='macros'/><category term='UML'/><category term='Teamarbeit'/><category term='Haskell'/><category term='finite state machine'/><category term='Interfaces'/><category term='interview'/><category term='Firefox'/><category term='Forth'/><category term='HTML'/><category term='TeX'/><category term='Cat'/><category term='JavaScript'/><category term='Verschlüsselung'/><category term='google'/><category term='Python'/><category term='Systemtheorie'/><category term='informatik'/><category term='PS3'/><category term='Prozess'/><category term='Semantik'/><category term='Alan Kay'/><category term='wissenschaftliche Abschlussarbeit'/><category term='scripting language'/><category term='ECMAScript'/><category term='Diplomarbeit'/><category term='bootstrapping'/><category term='Lisp'/><category term='Factor'/><category term='bücher'/><category term='Quantum'/><category term='Ajax'/><category term='types'/><category term='Tamarin'/><category term='Softwarearchitektur'/><category term='Hochschule Heilbronn'/><category term='EBNF'/><category term='addons'/><category term='bafa'/><category term='Joy'/><category term='funktionale Programmierung'/><category term='Lidl'/><category term='concatenative programming'/><category term='Studienarbeit'/><category term='Spring'/><category term='Lambda Calculus'/><category term='rewriting'/><category term='addon'/><category term='Scheme'/><category term='Luhmann'/><category term='waitzkin'/><category term='Design by Contract'/><category term='umweltprämie'/><category term='Zustandsmaschine'/><category term='extensions'/><category term='Parser-Kombinator'/><category term='Multi-Stage Programming'/><category term='Internet'/><category term='formale Sprachen'/><category term='schreibbar'/><category term='Grammatik'/><category term='wii'/><category term='RegEx'/><category term='FSM'/><category term='cell'/><category term='Code-Generierung'/><category term='stack'/><category term='Syntax'/><category term='n95'/><category term='RegExp'/><category term='MetaOCaml'/><category term='Ruby'/><category term='twitter'/><category term='Projektmanagement'/><category term='Object Model'/><category term='abwrackprämie'/><category term='Bachelor Thesis'/><category term='Komponente'/><category term='LaTeX'/><title type='text'>denkspuren</title><subtitle type='html'>gedanken, ideen, anregungen und links rund um informatik-themen</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default?start-index=101&amp;max-results=100'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>126</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-8821754959660668975</id><published>2011-12-21T13:58:00.000+01:00</published><updated>2011-12-21T13:58:10.761+01:00</updated><title type='text'>How to Avoid Plagiarism?</title><content type='html'>&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;The purpose of any scientific activity is to gain insight, to understand something, to advance knowledge in a field, to make some theory applicable etc. In any case, your are standing on someone else shoulders – a statement attributed to Isaac Newton (1642-1726), who revolutionized physics. Even a genius like Newton rarely creates something from scratch. There is always a basis, a foundation, work done by other people, we built our research upon.&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;The issue is: &lt;b&gt;Give credit where credit is due!&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;In science, you do so by referencing the work (books, papers, articles and – in rare cases – web sites) of others your scientific outcome (books, papers, articles and – in rare cases – web sites) relies and is built on. It is a way to say “Thank you for letting me stand on your shoulders that helped me do my work.” This might include referencing private communication. Here, I don't mean any sort of assistance you received while you were stuck, but personal contacts, which decisively influenced your research by having research-related conversations, orally, by email etc. Give credit where credit is due!&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;The other issue is: &lt;b&gt;Be honest about your contribution, no matter how tiny it is.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;Most scientific work does not create a sort of Big Bang of insights, understandings etc. Mostly, science advances in very small, more baby-like steps. That's ok and there is nothing wrong with this. Do not feel bad about your tiny contribution to science. The point is: Make absolutely clear what the state-of-the-art in your field regarding your topic is and what your contribution is no one else did before. It is about making a difference, literally speaking.&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;You do so by summarizing and referencing the work of others relevant to your field. For that you need to carefully revise and inspect the current state-of-the-art. Sometimes that's not easy and requires you to do a lot of work, usually systematically searching databases covering the vast knowledge of your field and reading a lot of papers. Nonetheless, it is important work. To make a difference you need to show the difference no matter how small the difference is.&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;b&gt;Not giving credit and letting your contribution appear more impressive than it actually is is regarded as an academic fraud. It is called plagiarism. &lt;/b&gt; &lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;I hope you got the point: This one-pager is not about the technicalities to reference and quote other peoples work correctly. On this topic, there are tons of resources available elsewhere. “How to avoid plagiarism?” is about creating a mindset. It is a mindset of showing respect to others and being honest about your contribution. Make a difference – but without plagiarism.&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;Having immersed the mindset, you might understand why academia reacts quite drastic to uncovered cases of plagiarism. Students might get exmatriculated, researchers might loose academic titles and their jobs or positions. Plagiarism is not so much about a code of ethics but putting the scientific method at risk:&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div align="JUSTIFY" style="margin-bottom: 0cm;"&gt;&lt;b&gt;&lt;span style="font-family: inherit;"&gt;We cannot advance science by cheating on each other.&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-8821754959660668975?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/8821754959660668975/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=8821754959660668975' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/8821754959660668975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/8821754959660668975'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2011/12/how-to-avoid-plagiarism.html' title='How to Avoid Plagiarism?'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-4845331004360410648</id><published>2011-11-17T20:56:00.000+01:00</published><updated>2011-11-17T20:56:41.894+01:00</updated><title type='text'>Das Kanban-Board des Steve Jobs</title><content type='html'>War Steve Jobs ein Anhänger der Kanban-Methode? Ja, ich glaube schon. Er hat Kanban gewissermaßen praktiziert. Anders zwar, auf seine Weise, aber es hat ihm einen Überblick über den aktuellen Arbeitsstand bei Apple samt einem Blick in die Zukunft ermöglicht.&lt;br /&gt;&lt;br /&gt;Doch zunächst: Was ist Kanban?&lt;br /&gt;&lt;br /&gt;Kanban ist eine der jüngsten agilen Methoden der Software-Entwicklung. Eine zentrale Stellung nimmt dabei das sogenannte „Kanban-Board“ ein. Als Kanban-Board dient z.B. eine (magnetische) Tafel oder eine Pin-Wand. Darauf finden sich Karten angeheftet. Die Karten repräsentieren Arbeitspakete; sie weisen einen Titel für das Arbeitspaket aus, den Namen der Person, die mit dem Arbeitspaket befasst ist, das Datum der Deadline etc. Das Kanban-Board ist in Bereiche unterteilt, die ein Spiegelbild des Entwicklungsprozesses sind. So gibt es Bereiche die beispielsweise "Inkubation", "Analyse", "Entwicklung", "Test" und "Abnahme" heißen. Die Verteilung der Karten in den Bereichen gibt die aktuelle Situation der Arbeitspakete in den einzelnen Arbeitsschritten wider. Das Kanban-Board ist nicht nur eine Dokumentation des Status quo, sondern dient auch als Steuerinstrument, um sicher und ohne Überlastung den Entwicklungsprozess zu durchlaufen -- und fordert dabei die stete Auseinandersetzung mit der Frage heraus "Was können wir besser machen?".&lt;br /&gt;&lt;br /&gt;Kanban-Boards verfehlen leicht ihren Sinn und Zweck, wenn sie ein virtuelles Leben führen. Den Kanban-Vertreter(inne)n ist ein physisches Board sehr wichtig. Da soll was an der Wand hängen und für alle Beteiligten unübersehbar sein. Jeder soll über den aktuelle Arbeitsstand im Bilde sein. Das Kanban-Board soll auch Treffpunkt sein für kurze Treffen zur Abstimmung über die zu erledigende Arbeit, für den Austausch über Probleme, Rückstände oder Fortschritte.&lt;br /&gt;&lt;br /&gt;Das Kanban-Board des Steve Jobs lag in einem Gebäudeteil auf dem Apple-Campus, im Design-Studio von Jonathan ("Jony") Ive, dem Chefdesigner von Apple. Es war weniger ein Board, als denn eine Reihe von langen Stahltischen, die in einem großen Raum aufgestellt waren. Auf den Tischen lagen echt aussehende Design-Modelle der laufenden Arbeiten. -- Das ist nachzulesen in Kapitel 25 der nach dem Tode von Jobs erschienenen Biographie "Steve Jobs" von Walter Isaacson, auf Deutsch veröffentlicht im C. Bertelsmann-Verlag. Die nachfolgenden Seitenangabe beziehen sich auf diese Ausgabe.&lt;br /&gt;&lt;br /&gt;Jobs kam praktisch täglich in das Design-Studio von Ive und hatte dabei seine "Kanban-Tische" direkt im Blick. Er sah dort alle in Planung befindlichen Produkte und "konnte direkt erspüren, ob und wie sie in die Strategie von Apple hineinpassten. Er konnte mit seinen Fingern das in Entwicklung befindliche Design befühlen und begreifen." (S.405) Oder, um Ive sprechen zu lassen: "Dieser große Raum ist der einzige Ort in der ganzen Firma, wo man sich einfach nur umzuschauen braucht und alles sieht, was wir gerade in Arbeit haben." (S. 406)&lt;br /&gt;&lt;br /&gt;Genau das ist die Funktion eines Kanban-Boards! Steve Jobs hatte von Software-Entwicklung und Hardware-Bau kaum Ahnung -- ganz im Gegensatz zu Bill Gates. Bei ihm war das Design, das Aussehen, die Formgebung seiner Produkte derart zentral, dass er alles dem Design unterwarf und das alles mit dem Design verwoben war. Mit dem Design began und endete alles. Insofern ist es nur konsequent, "Kanban-Tische" im Fall von Jobs zu haben. Für einen Außenstehenden standen dort "nur" Design-Modelle. Für ihn manifestierte sich in den Design-Modelle der gesamte Entwicklungsstand seiner Produkte. Auf einen Blick! Was für ein großartiges Management-Tool!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-4845331004360410648?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/4845331004360410648/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=4845331004360410648' title='3 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/4845331004360410648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/4845331004360410648'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2011/11/das-kanban-board-des-steve-jobs.html' title='Das Kanban-Board des Steve Jobs'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-375153922987614573</id><published>2011-11-09T22:55:00.000+01:00</published><updated>2011-11-09T22:55:39.236+01:00</updated><title type='text'>Über den Wolken muss die Freiheit wohl grenzenlos sein ...</title><content type='html'>In einer Wolke kann man sich der schönen Illusion hingeben, man habe so etwas wie Privatsphäre. Ein paar Meter weit kann man sehen, gerade genug, um sich selbst nicht aus dem Auge zu verlieren. Einem Außenstehenden versperrt der Dunst den Blick.&lt;br /&gt;&lt;br /&gt;Welch wunderbare Illusion!&lt;br /&gt;&lt;br /&gt;Ich nutze z.B. Google Docs. Ein paar Texte und Tabellen sind unter meinem Account abgelegt -- irgendwo in der Datenwolke, der Cloud von Google. Gerne gebe ich mich dem Glauben hin, meine Daten seien dort "privat" und "sicher". Vielleicht liegen Ihre Daten gleich nebenan, nur ein kleines winziges Bisschen entfernt auf der Festplatte im Google-Rechenzentrum. Wir sehen einander nur nicht, im Nebel der Cloud.&lt;br /&gt;&lt;br /&gt;Machen wir uns nichts vor: natürlich ist der Nebel eine Illusion. Google sieht alles. Man analysiert dort fleißig alle nur verfügbaren Daten. Meine Daten ebenso wie Ihre Daten. Für Google gibt es keinen Nebel. Google sieht alle Daten in der Wolke, die Spannendes an Informationen herzugeben weiß. Und sollte irgendwo, irgendwann eine Panne passieren, so lichtet sich möglicherweise der Nebelschleier für einen Moment -- und Ihre und meine Daten bieten sich der Welt feil, und wir müssen uns der Peinlichkeit der Offenbarung des Privaten stellen.&lt;br /&gt;&lt;br /&gt;Wissen Sie, was ich gerne möchte? Über den Wolken fliegen. Auch wenn es in diesen luftigen Höhen eiskalt ist, der Blick auf sonnengeflutete Wolkenlandschaften entschädigt alles. Durch eine Wolke fliegen ist uninteressant. Aber über den Wolken, da ist die Freiheit grenzenlos ...&lt;br /&gt;&lt;br /&gt;Grenzlose Freiheit ist, wenn jeder in der Cloud prinzipiell meine Daten sehen könnte -- aber nichts davon hätte, weil alles verschlüsselt ist. Grenzenlose Freiheit ist, wenn Google (oder welcher Clouddienst auch immer) meine Daten nicht zu interpretieren wüsste. Verschlüsselt eben. Auf dem Client, im Browser, in der App, dort würde ent- und verschlüsselt werden. Niemals jedoch würde auch nur ein einziges privates Bit meine Rechner oder mein Smartphone verlassen, ohne vor den neugierigen Blicken Dritter wirklich geschützt zu sein. &lt;br /&gt;&lt;br /&gt;Warum sollte uns irgendjemand diese Freiheit schenken? Wohl kaum einer! Die Freiheit über den Wolken, die Freiheit über der Cloud ist wirtschaftlich uninteressant. Grenzenlose Freiheit hat nur der, der in der Cloud keine Privatsphäre kennt oder will. Grenzenlos frei ist auch der, der unter der Wolke lebt -- und ohne den Datenrummel in der Cloud auskommt.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-375153922987614573?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/375153922987614573/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=375153922987614573' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/375153922987614573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/375153922987614573'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2011/11/uber-den-wolken-muss-die-freiheit-wohl.html' title='Über den Wolken muss die Freiheit wohl grenzenlos sein ...'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-7559039406524168507</id><published>2011-11-02T13:02:00.000+01:00</published><updated>2011-11-02T13:02:25.814+01:00</updated><title type='text'>Von der Leichtigkeit, ein Startup zu gründen</title><content type='html'>Am vergangenen Wochenende fand der &lt;a href="http://www.entrepreneurship.de/summit" target="_blank"&gt;Entrepreneuship Summit&lt;/a&gt; in Berlin statt. Etwa 1200 Teilnehmer füllten den &lt;a href="http://www.fu-berlin.de/sites/hfb/index.html" target="_blank"&gt;Henry-Ford-Bau&lt;/a&gt; der Freien Universität Berlin. Vorträge wechselten sich ab mit Impulsgruppen. Ging es am Samstag noch etwas zaghaft zu, kam am Sonntag mehr Bewegung und Stimmung auf. Man hatte sich am Vortag zaghaft beschnuppert, orientiert und allmählich in ein Gefühl gemeinschaftlicher Absichten eingefunden. So "störte" eine kleine Gruppe den Programmablauf am Sonntagmorgen und rief zum "Funky Business" auf; man wolle sich in Berlin-Tempelhof zusammentun und ein kleines Silicon Valley aufbauen -- nur besser. Sowas, so mein spontaner Gedanke, ist eben nur in einer Großstadt möglich. Und vielleicht sind die Berliner sogar experimentierfreudiger als andere Großstädter; vielleicht eben auch williger, das Scheitern mit in Kauf zu nehmen.&lt;br /&gt;&lt;br /&gt;Veranstaltet hat den Summit die &lt;a href="http://www.entrepreneurship.de/" target="_blank"&gt;Stiftung Entrepreneurship&lt;/a&gt;. Dahinter steht als treibende Kraft &lt;a href="http://de.wikipedia.org/wiki/G%C3%BCnter_Faltin" target="_blank"&gt;Prof. Dr. Günter Faltin&lt;/a&gt;. Er hat mit seinen Studierenden das Unternehmertum real in der freien Wildbahn des Marktes ausprobiert. Herausgekommen ist dabei die sogenannte &lt;a href="http://www.teekampagne.de/" target="_blank"&gt;Teekampagne&lt;/a&gt;, die sich rühmen darf, den Teemarkt neu aufgemischt zu haben. Günter Faltin hat das und seine Gedanken zum Unternehmertum festgehalten in dem Buch "Kopf schlägt Kapital". Ein absolut lesenswertes Buch! Seine Art des "Entrepreneurship Design" prägte die Veranstaltung durch und durch. Es ist die neue "Leichtigkeit des Unternehmertums", mit der man von einer Idee zu einer Unternehmensgründung kommt. Heute lässt sich eine Vielzahl von Komponenten "einkaufen". Es ist nicht mehr nötig ein Büro zu haben, die Buchhaltung zu führen, selbst Produktionsanlagen zu betreiben, Bestellung und Versand in die Hand zu nehmen. Es genügt, sich aus diesen Komponenten das eigene Unternehmen masszuschneidern. Man muss nicht mehr Alleskönner sein. Man kann sich ganz auf das konzentrieren, was den Kern eines Unternehmens ausmacht: Die Geschäftsidee, die Konzeption der Idee und ihre Ausrichtung am Markt.&lt;br /&gt;&lt;br /&gt;Den einen oder anderen mag das erinnern an die "4-Hour Workweek" ("Die 4-Stunden Arbeitswoche") von &lt;a href="http://en.wikipedia.org/wiki/Timothy_Ferriss" target="_blank"&gt;Tim Ferriss&lt;/a&gt;. Er vertritt eine ähnlich autonome, komponentenbasierte Unternehmensarchitektur, in Teilen sogar radikaler als Prof. Faltin. So war es denn kein Zufalls, dass ein Vortrag eine Videoeinspielung war, in der Prof. Faltin Tim Ferriss interviewte. Bedauerlicherweise war die noch am Samstagmorgen angekündigte Video-Liveschaltung mit Ferriss nicht zustande gekommen.&lt;br /&gt;&lt;br /&gt;Ich kann nicht aus eigener Erfahrung mitreden. Aber es hat in der Tat den Anschein, als sei es nie zuvor so leicht und risikoarm gewesen, ein Unternehmen zu gründen. Manch junger Unternehmer setzt sein Unternehmenskonzept so konsequent auf, dass Kosten erst entstehen, wenn Kunden das Produkt bestellen oder die Dienstleistung nutzen. Das ist ein faszinierendes Extrem. Der Gründer der &lt;a href="http://laktasekampagne.de/" target="_blank"&gt;Laktasekampagne&lt;/a&gt; (der Name deutet es an, die Teekampagne war das Vorbild) Martin Lipsdorf sagte, er habe sein Unternehmen mit 700€ an den Start gebracht. Hui! Das hat was, oder?&lt;br /&gt;&lt;br /&gt;&lt;a href="http://saschalobo.com/" target="_blank"&gt;Sascha Lobo&lt;/a&gt; -- wer ihn nicht kennt: eine auffallend unauffällige Erscheinung, wäre da nicht die rote Irokesen-Frisur -- berichtete als selbsternannter "Scheiterexperte" vom Scheitern. Auch das war also Thema. So leicht es heutzutage sein mag, ein Startup zu gründen, so leicht ist auch das Scheitern geworden. Es ist ja nicht gleichzeitig leichter geworden, sich auf dem Markt zu behaupten und in einer Nische einzunisten. "Fail often and adapt", das könnte man als Botschaft da raushören. (Ein Buchtipp am Rande: "Adapt: Why Success Always Starts with Failure" von Tim Harford.) Die Lernzyklen sind kürzer geworden. Man kann sich allmählich "warmgründen", bis es klappt! Und man sollte sich ohnehin darauf einstellen, die Geschäftsidee immer wieder anzupassen und zu tunen. Das berichteten einige Gründer in einer Impulsgruppe.&lt;br /&gt;&lt;br /&gt;Wer sich Mut holen möchte zum Gründen: Ich bin sicher, im Oktober 2012 findet wieder ein Entrepreneurship Summit in Berlin statt. Einfach hinfahren und Erfahrungen austauschen. Ich habe 75€ Teilnahmegebühr bezahlt, der Betrag sollte für künftige Entrepreneure erschwinglich sein.&lt;br /&gt;&lt;br /&gt;P.S.: An meine Zunft der Softwareschrauber: Die "&lt;a href="http://www.hpi.uni-potsdam.de/d_school" target="_blank"&gt;School of Design Thinking&lt;/a&gt;" des Hasso Plattner Instituts (HPI) aus Potsdam war mit einem Vortrag zu "Enabling Innovation with Design Thinking" vertreten. Da geht es zwar nicht nur um Innovationen mit Software. Aber wenn Software eine Rolle spielt, dann macht es kaum einen Unterschied. Da werden "Prototypen" mit Stift und Papier, Knete, Playmobil und Lego realisiert. Anders lässt sich die prototypische Entwicklung eines Produkts an einem Tag gar nicht durchziehen. Dahinter steckt Methode. Kurze Zyklen, das Scheitern inbegriffen, sollen eine Innovation zu einem nützlichen, marktfähigen Produkt reifen lassen. Das Ganze hat mich sehr neugierig gemacht. Eine "School of Design Thinking" an der Hochschule Heilbronn, das wäre mal was ... fehlt uns doch nur ein kapitalkräftiger Förderer! Das "Design Thinking" ist sehr personalintensiv in der Betreuung der studentischen Gruppen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-7559039406524168507?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/7559039406524168507/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=7559039406524168507' title='3 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/7559039406524168507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/7559039406524168507'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2011/11/von-der-leichtigkeit-ein-startup-zu.html' title='Von der Leichtigkeit, ein Startup zu gründen'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-1358681573596892743</id><published>2011-10-30T00:21:00.000+02:00</published><updated>2011-10-30T00:21:32.301+02:00</updated><title type='text'>Ein Blick in die Zukunft</title><content type='html'>Was hat einem ein Zukunftsforscher zu erzählen? Am Dienstag, den 25. Oktober, hielt Lars Thomsen an der Hochschule Heilbronn einen Vortrag über die Zukunft. 520 Wochen, sprich 10 Jahre, ließ er uns in die Zukunft schauen. Thomsen hatte aufmerksame Zuhörer. Die Aula war voll. Etwas mehr als eine Stunde hörten alle gebannt einem Vortrag zu, der ohne eine einzige Folie auskam. Ohne Zweifel ist Thomsen ein geübter Redner, der sein Thema ausgezeichnet zu vermitteln und zu verpacken weiß!&lt;br /&gt;&lt;br /&gt;Worüber er sprach? Sie hätten dabei sein sollen. Ich versuche eine grobe Zusammenfassung von vier "Megatrends", wie Thomsen sie nennt:&lt;br /&gt;&lt;br /&gt;Die Rechenleistung von Computern wird sich weiterhin jährlich verdoppeln. In 10 Jahren sind die Desktops, Laptops, Netbooks, Tabs und Smartphones 1000x leistungsfähiger als die heutigen Geräte. Es wird das "Ende der Dummheit" einläuten. Computer werden uns ganz neue Helferlein sein, da sie beginnen, uns zu verstehen. Sie werden EMails mitlesen, eingehende Nachrichten geeignet sortieren, Anfragen teils selbstständig beantworten. Das brauchen wir dringend. Jedes Jahr steigt der Mailverkehr um 18%. Wir Menschen sind schon jetzt mit der Datenflut überfordert. Es wird mehr und mehr Programme geben, die ein primitives Verständnis haben von dem, was wir tun, was unsere Gewohnheiten und Wünsche sind. Und die werden dieses Verständnis nutzen, uns zu helfen.&lt;br /&gt;&lt;br /&gt;Unser Umgang mit Energie wird sich vollkommen verändern -- schon aus reiner Notwendigkeit. Die fossilen Rohstoffe sind begrenzt. Schon immer hat es auf unserem Planeten ein Einlagern und Freigeben von Kohlenstoff gegeben. Das, was der Mensch jedoch an CO2 in kürzester Zeit auf dem Planeten freigesetzt hat, ist wohl einmalig in der Geschichte der Erde. Klimatische Grenzen werden sich verschieben, neue Vegetationsgebiete kommen auf. Der Umstieg auf alternative Formen der Energiegewinnung und -speicherung ist unausweichlich. In China werden Solarmodule produziert, die Preise für Photovoltaik sind dadurch allein in der Zeit von Januar bis September um 22% gefallen -- ein sich fortsetzender Trend. Gut möglich: Künftig mögen die Solarzellen billiger sein als Dachziegel. Die Speicherung von Energie wird in Form eines Smartgrids gelöst werden. Die intelligente, dezentrale Organisation von Energiezu- und abflüssen im Energienetz wird die zentrale Energieversorgung ablösen.&lt;br /&gt;&lt;br /&gt;2016 wird ein Elektroauto so viel kosten wie ein Benziner. Elektroautos sind dem Treibstoffwagen in vielerlei Hinsicht überlegen. Ein Blick unter die Motorhaube offenbart eine Boardelektronik, die kaum mehr als drei Coladosen einnimmt. Die Bodenplatte wird mit Akkus aufgefüllt, was zudem den Schwerpunkt extrem tief legt und exzellente Fahreigenschaften garantiert. Schon jetzt sieht ein Porsche alt aus im Sprint gegen moderne Elektroautos. Das derzeit kostentreibende Element im Elektroauto sind die Akkus. Doch hier macht sich ein Preisverfall von 12% pro Jahr bemerkbar. Noch in diesem Jahrzehnt wird das Auto mit Verbrennungsmotor nur noch etwas für Enthusiasten sein. Wer das Röhren in seinen Ohren höhren will, wer das Zittern eines aufdrehendes Motors spüren möchte, der muss sich als Nostalgiker einen teuren Benziner oder Diesel leisten -- vermutlich als Zweit- oder Drittwagen.&lt;br /&gt;&lt;br /&gt;Die Medizin hat längst nicht ihr Potenzial ausgereizt. Sie lässt sich reduzieren auf das "Schneiden und Zusammenflicken" und den Einsatz von Chemie. Es kommen derzeit im Wesentlichen 37 Grundsubstanzen in Medikamenten zum Einsatz. Der Rest ist Hoffnung. Die "Medizin 2.0" baut auf den Selbstheilungskräften des Genoms auf. Die Menschen haben es gelernt, die 770MB Erbinformation, die jede Zelle mit sich herumträgt, auszulesen. Nun geht es darum, die darüber kodierten Eigenschaften und Aubläufe gezielt zu nutzen. Ein Beispiel: Eine Firma schenkt schwerhörigen Menschen ihr Gehör zurück. Nicht durch ein Hörgerät! Die feinen Häarchen im Ohr, die für das Hören gebraucht werden, werden wieder zum Wachstum stimuliert. Dazu wird ein Stopp-Gen, das unbegrenztes Haarwachstum verhindert, gezielt ausgeschalter und später wieder eingeschaltet. Mit den nachgewachsenen Harchen hört es sich prima. Viele von uns durfen auf solche medizinischen Fortschritte hoffen. Die Lebenserwartung unter den lebenden Menschen (nicht also erst in einer späteren Generation), steigt pro Jahr um 3-4 Monaten. Wer künftig steinalt wird, wird sich gerne von der Medizin "frisch" halten lassen.&lt;br /&gt;&lt;br /&gt;Spannend, nicht wahr?! Thomsen hat noch eine Menge mehr erzählt. Er sprach vom Versagen des Geldes, aber auch von dem, was uns Menschen auszeichnet: Wir sind soziale Wesen, das wird sich nicht ändern. Vermutlich werden wir neue Wirtschafts- und Arbeitsformen ausprobieren. Und was Studenten gerne hören mögen: Man wird sich später auf dem Berufsmarkt um sie reißen. Es wird einen Mangel an (aus)gebildeten Menschen geben. Selbst Länder wie China werden aggressiv Fachkräfte aus dem Ausland anheuern, um ihren Hunger nach wirtschaftlichen Wachstum zu stillen.&lt;br /&gt;&lt;br /&gt;Ich habe keine Ahnung, ob sich die Zukunft so entwickeln wird. Vieles, was Thomsen erzählt, wirkt erschreckend plausibel. Wenn Sie diesen Blogbeitrag in 10 Jahren, also im Jahr 2021 lesen, dann werden Sie wissen, ob Thomsen nicht nur ein hervorragender Redner, sondern auch ein wirklich guter Zukunftsforscher ist.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-1358681573596892743?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/1358681573596892743/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=1358681573596892743' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1358681573596892743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1358681573596892743'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2011/10/ein-blick-in-die-zukunft.html' title='Ein Blick in die Zukunft'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-5622223282376893882</id><published>2011-04-19T22:13:00.000+02:00</published><updated>2011-04-19T22:13:16.216+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='clojure'/><title type='text'>Clojure per Kommandozeile in Windows: CLASSPATH-Setting</title><content type='html'>Möchte man die Clojure-REPL interaktiv unter Windows nutzen, helfen gut gesetzte Umgebungsvariablen und ein einzeiliges Batch-File ungemein. Schmerzfrei wird der Dialog mit Clojure aber erst dann, wenn der &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;CLASSPATH&lt;/span&gt; der JVM auf die nötigen jar-Files gesetzt ist. Ist auch das Verzeichnis der interaktiven Konsolen-Session dabei, funktioniert auch z.B. ein load-Aufruf aus Clojure heraus, um die dort befindlichen clj-Dateien zu laden.&lt;br /&gt;&lt;br /&gt;Der folgende Einzeiler ruft die Clojure-REPL auf. Die Umgebungsvariable &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;PATH&lt;/span&gt; muss das Verzeichnis mit java.exe beinhalten, die Umgebungsvariable &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;CLOJURE&lt;/span&gt; sei auf das aktuelle Clojure-Verzeichnis gesetzt:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;java -cp %CLOJURE%\*;*; clojure.main %1 %2 %3 %4 %5 %6 %7 %8&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Zur Erläuterung: Das Wildcardzeichen "&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;*&lt;/span&gt;" sorgt dafür, dass alle jar-Files im &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;CLOJURE&lt;/span&gt;-Verzeichnis in den &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;CLASSPATH&lt;/span&gt; aufgenommen werden, ebenso wie mit dem zweiten Wildcard "&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;*&lt;/span&gt;" alle jar-Files im aktuellen Verzeichnis. Hinweis: Ohne das Semikolon als abschließendes Trennzeichen funktioniert das Wildcard-Zeichen nicht.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-5622223282376893882?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/5622223282376893882/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=5622223282376893882' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5622223282376893882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5622223282376893882'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2011/04/clojure-per-kommandozeile-in-windows.html' title='Clojure per Kommandozeile in Windows: CLASSPATH-Setting'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-9202604171239048085</id><published>2010-10-07T11:24:00.000+02:00</published><updated>2010-10-07T11:24:54.641+02:00</updated><title type='text'>Complexity, Size and Focus</title><content type='html'>&lt;div style="margin-bottom: 0cm;"&gt;&lt;span style="font-style: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Why is it so hard to understand software?&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; Or to put it more to the point: &lt;/span&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;What makes it so hard to write understandable software?&lt;/span&gt;&lt;/i&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; This question is the driving theme of this article: the quest to uncover techniques of complexitiy management that go beyond established principles of software engineering such as information hiding and modularization and which are unbound to specific paradigms like object-orientation or functional programming.&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;For that reason I studied two kinds of software systems in depth: telecommunication systems, modeling and programming languages. I did so for two reasons: First, telecommunication systems are among the oldest, largest and most successful systems. They are highly reliable, roboust and scalable. What are their key design principles that make them stand such demanding requirements? Second, each modeling and programming language is its creators attempt to provide a set of language conceptions to address and manage complexity. A language – be it a programming or modeling language – is, so to speak, the destillate of another persons opinion, experience and expert knowledge about how to write „better“ programs or how to design „better“ software.&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;My observation and claim is that two factors are most responsible for what I capture under the term „complexity“: &lt;/span&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;size&lt;/span&gt;&lt;/i&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt; and &lt;/span&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;focus&lt;/span&gt;&lt;/i&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;. Size refers to number of lines of code and number of features, focus refers to intellectual comprehensibility.&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;The code basis of todays operating systems goes into million lines of code. Recently, Linux was reported to reach 10 million lines of code. Windows 7 is estimated to be of the same size. These numbers do not include application software typically shipped with these operating systems. Applications such as OpenOffice also count some ten million lines of code. The latest release of the Eclipse IDE (Integrated Development Environment), version 3.6, counts 33 million lines of codes. Since there is a relation between code size and the number of faults to be expected per 1000 lines of code (numbers vary from 25 to about 1 error per 1000 lines of code), such huge-sized software is highly interspersed with faults.&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Another dimension of size is number of features: Todays software is extremely feature-rich. A whole industry of education and consulting is build around teaching and configuring the use of software, which is too feature-rich to use out of the box. Office applications and SAP R5 come into mind. This observation also refers to programming languages used to build these systems. The most spreaded languages are C, C++, C# and Java. Java, for instance, is such feature-rich that it requires a programmer to learn and understand a language specification of almost 700 pages of text. It is no exaggeration that most Java programmers only master a personalized subset of these 700 pages.&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;The sheer size of code of todays software makes it impossible for a software developer to understand software systems in its entirety. The sheer volume of code is overwhelming und impossible to master. It is a valid question whether this size complexitiy is inherent to the problem domain or a symptom of a certain design philosophy that has become main stream and is manifested in lanaguages like C(++), C# and Java. Alternative approaches indicate the latter: TeX, a typesetting system designed in the 1980s by Donald E. Knuth, is still top-class in its typesetting quality and widely spread in academia and among textbook authors; many publishers prefer manuscripts produced in TeX. TeX is based on a language kernel with primitives for typesetting and it can be easily extended via a powerful macro system. Besides bug fixes, the TeX kernel has been kept stable for almost 30 years now. Nonetheless, the system adapted constantly via its macro system with grwoing demands and new technologies coming up. Another example is Postscript.&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;There are also alternatives to feature-rich languages like C(++), C# and Java. Kernel-based languages like Lisp/Scheme, Prolog, Forth and Smalltalk are easy to understand. Their implementations fit on some few pages of code. They easily incorporated new paradigms and trends (e.g. object-orientation and aspect-orientation) due to their extensibility.  &lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Another aspect of complexitiy management is focus. From a cognitive viewpoint, complexity is a human beings incapability to intellectually manage information which is (a) too much and (b) spread in time and space. It is a combination of information overload and a lack of recognizing temporal and/or spacial patterns. Two techniques address these issues: one is condensation, the other is localization. Condensation comes in two forms: abstraction building and modeling. Abstraction building can be reversed by refinement without loss of information; modeling condenses at the price of loosing information thereby simplifying things. A simplification introduces faults and errors; an oversimplification overstresses the acceptance of incorrectness. Localization is a technique to bring together (to bring in focus), what was spread and distributed before and thus appeared to be unrelated and unconnected. To concentrate on a problem (domain) means to put it in focus, to dissolve and localize relevant parts and highlight their relations, which might be spatial (i.e. structural) and/or temporal (behavioral). The act of localization establishes a new context, a new perspective or point of view, a new universe of discourse, a new domain.  &lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;In software engineering, several techniques have been developed for abstraction and localization. Among many other ideas we just would like to mention abstract data types, object-orientation and meta-object protocols, aspect-orientation, meta-programming and macro systems. All these approaches have one thing in common: they try to rearrange parts in a software description, they try to bring in focus, they localize. We call the flexibility of a language to adapt to different localization needs its &lt;/span&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;expressiveness&lt;/span&gt;&lt;/i&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Interestingly, the other aspect of condensation, modeling, is rarely used in a systematic manner in software engineering with a clear understanding of the degree of incorrection and impreciseness introduced with a model. This understanding of modeling differs significantly from the common interpretation of the term. Typically, modeling is more meant to be a form of visual programming or a means to visually create code templates.&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt; &lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;The assumption is that small size systems are a natural consequence of systems designed with extremely expressive languages. Empirical data point into this direction: Systems developed in expressive languages like Lisp/Scheme, Prolog, Python or Ruby argue with code size reduction compared to languages like C, C++, C# and Java. These languages (Lisp etc.) are quite expressive, whereas C and others strictly separate the language from the problem domain. If a certain localization need is not covered by language features, frameworks need to be designed and implemented to simulate expressiveness.&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;I think that software engineering has yet underestimated the use and the value of highly expressive languages and highly extensible kernel-based systems.&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0cm;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-9202604171239048085?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/9202604171239048085/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=9202604171239048085' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/9202604171239048085'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/9202604171239048085'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2010/10/complexity-size-and-focus.html' title='Complexity, Size and Focus'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-610700147894321767</id><published>2010-05-14T07:39:00.002+02:00</published><updated>2010-08-18T10:23:26.763+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Softwarearchitektur'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Superhacker</title><content type='html'>Es gibt dieses wunderbare Bild der Hacker! Ich meine die Geeks, nicht die Kriminellen. Hacker leben mit dem Computer, sie scheinen eins mit ihm zu sein. Computer und Hacker gehen eine Symbiose ein. Hacken ist Leben, Leben ist Hacken. Menschen und soziale Kontakte sind eine wunderbare Sache -- sofern man mit ihnen im Chat oder in anderen virtuellen Welten kommuniziert und sie dort trifft. Hacker sind mindestens 10x produktiver als normal sterbliche Programmierer. Und Hacker sind nicht nur produktiver, ihr Code scheint nicht von dieser Welt zu sein. Kein Mensch versteht die Kryptik und die Gedankengänge im Code eines Hackers.&lt;br /&gt;&lt;br /&gt;Kurzum, wir bewundern die Hacker. Ein bissel hätten wir gerne von ihnen "vererbt" bekommen, wir, denen das Programmieren nicht ganz so locker von der Hand geht.&lt;br /&gt;&lt;br /&gt;Gibt es die Hacker überhaupt? Oder sind sie ein Mythos? Ja und nein.&lt;br /&gt;&lt;br /&gt;Es gibt Menschen, die das Bedienen ihrer Maschinen gründlich erlernt haben. Die 1000 Tastenkürzel kennen, mit Emacs arbeiten, alle Unix-Befehle kennen und im 10 Finger-System schreiben. Die Arbeit geht rasend von statten, wenn man diesen Tastaturakrobaten zuschaut. Fenster wechseln so schnell, das man glauben könnte, der Monitor habe einen Wackelkontakt. Das so ziemlich überflüssigste Interface für sie ist die Maus.&lt;br /&gt;&lt;br /&gt;Dann gibt es welche, die mit den vielen kleinen Helferlein und Tools umzugehen wissen. Da wird Windows rasch gescripted, ein Makro programmiert, ein Makefile konfiguriert, im Hintergrund laufen inkrementelle Backups. Das sind die Automatisierer. Denn wozu von Hand machen, was eine Maschine besser, alleine und vor allem viel schneller erledigen kann. Für sie ist Linux die Idealwelt. Aber sie ziehen auch eine Freude daraus, dass sie dieselbe Magie auch mit Windows hinkriegen. Und mache von ihnen haben sich auf die Zauberkunst mit Excel spezialisiert.&lt;br /&gt;&lt;br /&gt;Und es gibt die, die das Programmieren als Handwerk gelernt und verinnerlicht haben. Design Patterns sind für diese Menschen ein Klacks. Standardalgorithmen und -probleme können auf Zuruf während eines Telefonats runtergezimmert werden. Die Handwerker kennen ihre Bibliotheken und APIs in- und auswendig. Für sie ist Eclipse eine mächtige Schaltzentrale und die vielen offenen Fenster sind auf mindestens zwei Riesenmonitore verteilt. Sie haben mindestens genauso viel im Blick wie Börsenmarkler.&lt;br /&gt;&lt;br /&gt;Kennen Sie die Sammler? Sie sammeln Programmiersprachen und konzentrieren sich natürlich auf die exotischen Exemplare. Java und C# hat schließlich jeder. Sie Sammler sind oft auch liebenswerte Spinner. Sie können einem stundenlang begeisterte Vorträge über ihre neueste Entdeckung halten. Die neueste Sprache ist immer eine Steigerung zu dem, was letzten Monat noch aktuell war. Sie schreiben immerzu kleine Programme, manchmal auch etwas größere, und zwar in Sprachen, die keiner versteht. Aber sie kennen sich aus. Im Grunde gibt es für sie keine Probleme, sondern nur falsche Programmiersprachen.&lt;br /&gt;&lt;br /&gt;Tastaturakrobaten, Automatisierer, Programmierhandwerker, Sammler -- sie alle können etwas, was der Otto Normal-Programmierer nicht kann. Es sind Künstler, Handwerker, Besessene. Sie sind zweifelsohne jeweils auf ihre Art produktiver. Sie lösen Probleme geschickter, schneller und überzeugender als Andere. Manchmal nennen wir sie Hacker, besonders dann, wenn sie mehrere dieser Fähigkeiten vereinen. Aber sind das wirklich &lt;i&gt;die&lt;/i&gt; Hacker?&lt;br /&gt;&lt;br /&gt;Ich habe ein ganz anderes Bild vom Hacker; ich will sie mal "Superhacker" nennen. Manche von ihnen sind Tastaturakrobaten, manche Automatisierer, alle beherrschen das Programmierhandwerk eher besser als schlecht, und einige sammeln Programmiersprachen. Aber keines dieser Talente ist entscheidend. Superhacker denken! Das ist ihr eigentliches Talent, ihre eigentliche Stärke. Superhacker durchleuchten Probleme von verschiedenen Perspektiven. Sie skizzieren mögliche Lösungen. Diskutieren Ansätze und Vorgehensweisen. Sie brauchen dafür ihre Zeit. Manchmal findet sich eine elegante Problemlösung in einer exotischen Sprache begründet. Aber von Sprachen sind diese Menschen im Prinzip unabhängig. Sie kombinieren für eine Lösung Altbekanntes und Neues.&lt;br /&gt;&lt;br /&gt;Und das Ergebnis: Brillant kurzer Code. Code, der verständlich ist. Code, der verblüfft ob seiner Offensichtlichkeit. Code, dessen Genialität seine Einfachkeit ist. Code, der wartbar ist und andere Designer und Software-Entwickler inspiriert. Code, der Zukunft hat und klare Entscheidungen für ein Design trifft.&lt;br /&gt;&lt;br /&gt;Die Superhacker sind in der Regel nicht mehr produktiv in ihrem Tagesoutput als andere Software-Entwickler auch -- auch wenn es solche Wunder-Hacker geben mag. Das Geheimnis ihrer Produktivität schlägt sich nieder im Einfluss, den sie auf andere Entwickler ausüben. Das Geheimnis ihrer Produktivität zeigt sich in der überdurchschnittlichen Qualitätssteigerung der durch sie beeinflussten Produkte. Sie sichern Märkte. Sie sichern Zukunft.&lt;br /&gt;&lt;br /&gt;Die Superhacker, die Denker, sind Menschen, deren Produktivität deshalb hochgradig skaliert. Über den Umweg des Einflusses auf andere steigern sie die Produktivität in einem Unternehmen vielleicht um ein, zwei, drei oder vielleicht sogar einmal fünf Prozentpunkte, im Glücksfall um 10 Prozent. Ähnliches mag für die Qualitätssicherung gelten. Darüber tragen Sie zum Umsatz und Gewinn eines Unternehmens in einem Ausmaß bei, der keinen Vergleich findet zum Einfluss eines "Normalprogrammierers". Die normalen Hacker steigern ihre Produktivität -- nicht die der anderen!&lt;br /&gt;&lt;br /&gt;Übrigens gibt es eine etwas seriösere Bezeichnung für Superhacker: Man nennt sie auch &lt;a href="http://denkspuren.blogspot.com/2007/03/was-ist-software-architektur.html"&gt;Softwarearchitekten&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-610700147894321767?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/610700147894321767/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=610700147894321767' title='8 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/610700147894321767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/610700147894321767'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2010/05/superhacker.html' title='Superhacker'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-1481414814763101135</id><published>2010-01-28T13:28:00.013+01:00</published><updated>2010-01-29T09:55:54.364+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='concatenative programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Hochschule Heilbronn'/><category scheme='http://www.blogger.com/atom/ns#' term='Factor'/><title type='text'>Factor @ Heilbronn University</title><content type='html'>It was an experiment -- and it went much better than I had imagined: I used &lt;a href="http://factorcode.org"&gt;Factor&lt;/a&gt; (a &lt;a href="http://concatenative.org"&gt;concatenative programming&lt;/a&gt; language) as the subject of study in a project week at &lt;a href="http://www.hs-heilbronn.de"&gt;Heilbronn University&lt;/a&gt; in a course called "Software Engineering of Complex Systems" (SECS). Maybe we are the first university in the world, where concatenative languages in general and Factor in specific are used and studied. Factor is the most mature concatenative programming language around. Its creator, Slava Pestov, and some few developers have done an excellent job.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Why concatenative programming? Why Factor?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Over the years I experimented with a lot of different languages and approaches. I ran experiments using Python, Scheme and also Prolog in my course. It turned out that I found myself mainly teaching &lt;i&gt;how&lt;/i&gt; to program in Python, Scheme or Prolog (which still is something valuable for the students) instead of covering my main issue of concern: mastering complexity. In another approach I used XML as a tool for lightweight modeling to explore and study some techniques. The approach is innovative and still worth to be developed further but I wasn't satisfied.&lt;br /&gt;&lt;br /&gt;My goal in the course "Software Engineering of Complex Systems" is to present and discuss practical techniques to conquer complexity in software systems. I did and still do a lot of research in this area. To make a long story short, I have come to the conclusion that Language-Driven Software Engineering (LDSE) is a very powerful and promising approach to conquer complexity. It's more than creating and using Domain Specific Languages (DSLs). It's consistently designing and creating languages throughout all levels and layers of a software implementation.&lt;br /&gt;&lt;br /&gt;During my research I stumbled across Joy and Factor and learned about the concatenative paradigm. A series of excellent articles written by Manfred von Thun, creator of Joy, taught me the theory and fundamentals of concatenative languages. Factor, Slava Pestov's implementation of a practical concatenative language, turned out to be the best showcase I could think of: Factor is almost self-contained and extends itself by creating vocabularies of words using other vocabularies of words. Programs in Factor are written the very same style. Factor is seeing LDSE in action. I realized that it's the concatenative paradigm which enforces you to design software from a language-driven point of view.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;How did the course go?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;First I discussed the issue of complexity in software systems. Before I used Factor in the project week, I introduced the concatenative paradigm in the course. I presented it's mathematical foundation and used a pattern-driven approach to define the semantics of concatenative words as syntactic transformations. Finally, we defined a simplified grammar of Factor which we extended to cover pattern matching and template instantiation. All this served the purpose to smoothly prepare the ground for Factor. We also reflected and discussed a lot about what complexity is about and how it can be managed.&lt;br /&gt;&lt;br /&gt;During the project week, my students (about 30 persons) worked with Factor four out of five days almost 8 hours per day. For my students it was full contact combat with an almost unknown programming paradigm and an exotic language. But they did really well. On day 1, the students worked through the introductory material supplied with Factor. On day 2, we studied types and object-orientation in Factor. On day 3, parsing and macros were studied in Factor. For these two days, the students worked with tutorials and worked their way through a number of exercise, which required them to write tiny programs in Factor to pass unit tests. On day 4, we worked on a topic unrelated to Factor. On day 5, two students thoroughly presented their project work, a real-world application in Factor, they had done in another course in the previous semester. We concluded the week with discussing and reflecting Factor's capabilities and the power of the concatenative paradigm in general.&lt;br /&gt;&lt;br /&gt;Before I forget to mentioned it: Tim, research assistant in the software engineering department and PhD student, created the tutorials and the exercises and helped out a lot in class. Without him, the course wouldn't have been possible!&lt;br /&gt;&lt;br /&gt;The students enjoyed the week very much. The evaluation of the course shows that they liked getting a new and different viewpoint on software development, object-orientation, parsing etc. They definitely realized and experienced that Factor helps them becoming better software engineers although Java is their main language.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Isn't Facor, aren't concatenative languages too esoteric to be useful?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Yes and no. There is no question that Factor is a niche language no one in industry shows interest for (&lt;a href="http://www.youtube.com/watch?v=f_0QlhYlS8g"&gt;besides Google&lt;/a&gt;, so far ;-). There might be some companies out there which use Forth and might be open for "concatenative thinking". However, even though the concatenative paradigm is almost unknown, concatenative languages are functional languages and functional languages are gaining in popularity. There's little doubt that learning functional programming broadens your scope and complements a student's skill set.&lt;br /&gt;&lt;br /&gt;The fun part is that the concatenative approach to functional programming is much more simpler than the lambda calculus, which is traditionally taught. The math is simple and no intellectual barrier and formal transformations are easy to understand since there are no variable bindings and nesting scopes. Key concepts are stripped to their bare minimum. Did you ever try to explain the idea of continuations in Scheme? You might spend a good amount of time explaining continuations and running exercises. It's not unlikely that some students still don't get it. Continuations seem to be an extremely complex thing and appear to be somewhat mystical. In Factor, and in concatenative languages in general, continuations are a triviality! In principle, it's a snapshot of the data and the call stack. No big deal, since you juggle around with both stacks all the time. Are generic functions a specialty of CLOS. They come out naturally in a pattern-based approach to define concatenative words.&lt;br /&gt;&lt;br /&gt;But my point goes beyond that. The way you create abstractions and refactor your programs in a concatenative language enforces you to continuously reflect about your design decisions. You have an enormous freedom of how you shape and constrain the design space of options at hand. It lets you think about words and vocabularies of words. It is thinking about creating and using languages. It combines software engineering and software programming in a way I haven't experienced in any other paradigm. That's why I introduced Factor in my course: You will start to engineer software, you'll explore new ways of creating abstractions and design frameworks.&lt;br /&gt;&lt;br /&gt;Factor itself is an excellent case study for this approach. Factor starts from a relatively small kernel (which I -- admittedly -- haven't cleanly dissected, yet) and then consequently adds feature by feature with using Factor to extend Factor. A neat concatenative kernel turns itself into a powerful piece of software using a language-driven approach right from the start. Slava Pestov proves that this approach does result in a fast, interactive and highly reflective language. For me, Factor is a masterpiece of software engineering! It's definitely worth studying it!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;What I experienced over the last two semesters is that some students become deeply attracted by Factor. Even if not, almost all students sense that there is a new world worth entering that takes them to a new level of understanding. It broadens their scope and skill set. Eventually, they'll leave the concatenative path for doing their Java/C# assignments in other courses or when they do some programming for a living. Still, I'm convinced that concatenative programming has an impact that lasts.&lt;br /&gt;&lt;br /&gt;Do I sound too enthusiastic? Possibly, but I prefer to teach things I'm enthusiastic about! I'm still a student regarding the concatenative paradigm myself, I'm learning a lot each and every day about this paradigm. And one is for sure: I will continue to use Factor in the next semesters.&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;&lt;small&gt;&lt;b&gt;Update (2010-01-29)&lt;/b&gt; I received quite some requests to publish the Factor material we produced for the project week. The material is in German. Comments, ideas, corrections and improvements are welcome!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Day 1 - Intro:&lt;/b&gt; &lt;a href="http://docs.factorcode.org/"&gt;Getting started (Factor docu)&lt;/a&gt;, &lt;a href="http://mitarbeiter.hs-heilbronn.de/~herzberg/Publications/SEKS.WS2009/SEKS.WS2009.Aufgaben.BlockTag1.pdf"&gt;Q&amp;As&lt;/a&gt;&lt;br/&gt;&lt;br /&gt;&lt;b&gt;Day 2 - Object-Orientation:&lt;/b&gt; &lt;a href="http://mitarbeiter.hs-heilbronn.de/~herzberg/Publications/SEKS.WS2009/SEKS.WS2009.TypenUndOO.Intro.pdf"&gt;Intro&lt;/a&gt;, &lt;a href="http://mitarbeiter.hs-heilbronn.de/~herzberg/Publications/SEKS.WS2009/SEKS.WS2009.TypenUndOO.pdf"&gt;Tutorial&lt;/a&gt;, &lt;a href="http://mitarbeiter.hs-heilbronn.de/~herzberg/Publications/SEKS.WS2009/SEKS.WS2009.TypenUndOO.Aufgaben.txt"&gt;Q&amp;As&lt;/a&gt;&lt;br/&gt;&lt;br /&gt;&lt;b&gt;Day 3 - Parsing and Macros:&lt;/b&gt; &lt;a href="http://mitarbeiter.hs-heilbronn.de/~herzberg/Publications/SEKS.WS2009/SEKS.WS2009.Q&amp;As.Parsing.pdf"&gt;Intro&lt;/a&gt;, &lt;a href="http://mitarbeiter.hs-heilbronn.de/~herzberg/Publications/SEKS.WS2009/SEKS.WS2009.ParseworteUndMakros.pdf"&gt;Tutorial&lt;/a&gt;, &lt;a href="http://mitarbeiter.hs-heilbronn.de/~herzberg/Publications/SEKS.WS2009/SEKS.WS2009.ParseworteUndMakros.Aufgaben.txt"&gt;Q&amp;As&lt;/a&gt;&lt;br/&gt;&lt;br /&gt;&lt;b&gt;Day 4 - Unrelated Topic:&lt;/b&gt;&lt;br/&gt;&lt;br /&gt;&lt;b&gt;Day 5 - Real-World Application in Factor:&lt;/b&gt; &lt;a href="http://mitarbeiter.hs-heilbronn.de/~herzberg/Publications/SEKS.WS2009/Factor.MaierSteinle.Slides.pdf"&gt;Presentation&lt;/a&gt;, &lt;a href="http://www.technetbloggers.de/downloads/Documentation_Factor__Stackprogrammierung.pdf"&gt;Report&lt;/a&gt;, &lt;a href="http://mitarbeiter.hs-heilbronn.de/~herzberg/Publications/SEKS.WS2009/Sokoban.MaierSteinle.zip"&gt;Sources&lt;/a&gt; (thanks to &lt;a href="http://www.technetbloggers.de/"&gt;Andreas Maier&lt;/a&gt; and Marcel Steinle)&lt;br /&gt;&lt;br /&gt;By the way, &lt;a href="http://www.mail-archive.com/factor-talk@lists.sourceforge.net/msg04211.html"&gt;Daniel Ehrenberg indicated&lt;/a&gt; that Heilbronn University is not the first using Factor in a course. That's great to hear. Factor starts spreading!&lt;br /&gt;&lt;br /&gt;In case you are interested in our research on concatenative languages, there is a paper available: "&lt;a href="http://mitarbeiter.hs-heilbronn.de/~herzberg/Publications/ICSOFT.2009.pdf"&gt;Concatenative Programming: An Overlooked Paradigm in Functional Programming&lt;/a&gt;".&lt;br /&gt;&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-1481414814763101135?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/1481414814763101135/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=1481414814763101135' title='17 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1481414814763101135'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1481414814763101135'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2010/01/factor-heilbronn-university.html' title='Factor @ Heilbronn University'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-8454923644547383710</id><published>2010-01-21T18:48:00.002+01:00</published><updated>2010-01-21T18:53:28.223+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scripting language'/><category scheme='http://www.blogger.com/atom/ns#' term='Forth'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Factor'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Scripting Languages</title><content type='html'>Recently, I had an interesting discussion about "What's the distinguishing feature of so-called scripting languages?" We easily agreed on calling Python, Ruby, Groovy, Tcl, Perl etc. as scripting languages. But then the trouble started: What distinguishes Python, Ruby etc. from Java, C#, C++ and similar languages? Is it dynamic typing? Are they more introspective? Isn't it so that meta-programming is no difficulty at all with scripting languages?&lt;br /&gt;&lt;br /&gt;Some whisper that a Python or Ruby programmer is as much as 2-5 times more productive than a Java/C# programmer. As a matter of fact, programs written in so-called scripting languages tend to be significantly shorter than their "unscripted" counterparts. Such a discussion typically moves over into an almost religious debate about static and dynamic typing. Programs in Python and Ruby might be shorter but they are unsafe because of dynamic typing. Static typing is the way to go for large programs being developed with many developers -- say the Java and C# advocates. And they have a point. Write unit tests, say the Pythoneers and Rubyists, which you are supposed to write anyhow. As a side-effect, your unit tests easily uncover all typing related bugs. You're not better off with a statically typed language, they say.&lt;br /&gt;&lt;br /&gt;While such discussions are interesting our main question remains unanswered. What's the distinguishing feature of scripting languages? Most scripting languages are dynamically typed. But C# for example is catching up here. Are scripting languages interpreted languages? Python compiles to byte code internally, so does Java. Do they have unique reflective and introspective capabilities? To some extend, yes, but Java and C# are also quite powerful in this respect. Is programm size the only criteria? Regarding size, Haskell is a serious competitor. Haskell is statically typed (it requires a minimum of explicit type declarations) and quite dense in expressivity.&lt;br /&gt;&lt;br /&gt;I think that the name "scripting language" is not very helpful these days anymore. It's historically motivated. In the early days of computing, users had to interact with their machines by typing in commands in a command line. Soon, the command line was embedded in a so-called shell. Famous shells under Unix are the bourne shell (bsh), csh, tcsh; another specialized automation tool for software developers is "make". The shell provided means to automate -- script -- repetitive tasks. This kind of "programming" inspired languages like Perl. These languages weren't regarded as "serious" languages like e.g. C/C++. They were typically interpreted and relatively slow in execution. However, these languages matured over time and inspired other designers to create "glue" languages like Python or Tcl/Tk. Because of their interpretative nature it was easy to add introspective features and meta-programming facilities. The idea of being a scripting or "glue" language vanished over time. They became full-fledged implementation languages on their own right and kept the philosophy of being flexible and easy to use to solve problems. I think it is not appropriate anymore to call them "scripting languages".&lt;br /&gt;&lt;br /&gt;However, some of these "scripting languages" introduced a feature none of the compile-execute languages offered: The "programmable command line" languages introduced &lt;b&gt;interactivity&lt;/b&gt;!&lt;br /&gt;&lt;br /&gt;And that is the key point, it's the distinguishing feature: Interactivity requires to design a language in a certain way. To be interactive, relatively small chunks of text must represent syntactically valid program fragments in order to query or incrementally modify the run-time environment.&lt;br /&gt;&lt;br /&gt;The way to interact with the run-tim environment in non-interactive compile-execute languages is via the debugger. A tool that is rarely taught in combination with a non-interactive programming language. It's quite much a different experience to work with a debugger or interactively via an interactive command-line. A debugger is built around a representation of the run-time model and usually establishes a bridge towards the language the original program is written in. Interactive languages connect your programming experience with the run-time model in a consistent language-related way but still might shield some implementation details from the programmer a debugger shamelessly unveils.&lt;br /&gt;&lt;br /&gt;So the point is that interactive languages have a severe impact (a) on the syntactic language design and (b) they establish a certain way of how you perceive and experience the run-time environment of your language. This explains the shortness of interactive programs, it also explains the agility in the development process and its perceived prouctivity: quickly testing a program at the console results in immediate feedback to the programmer. This helps learning a language a lot and helps get a better run-time understanding. It's just fun and feels cool. There are only two languages I know of which have taken the implications of interactivity (small chunks of text represent valid syntactic programs and an incremental run-time experience) to an extreme: Forth and &lt;a href="http://factorcode.org/"&gt;Factor&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;This does not mean, that non-interactive languages are not useful and important! They just feel a bit different. Due to their lack of interactivity they feel less "handy", so to speak.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-8454923644547383710?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/8454923644547383710/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=8454923644547383710' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/8454923644547383710'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/8454923644547383710'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2010/01/scripting-languages.html' title='Scripting Languages'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-3725377847904759804</id><published>2009-12-23T12:02:00.003+01:00</published><updated>2009-12-23T12:23:22.926+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='twitter'/><title type='text'>Die Denkspuren auf Twitter</title><content type='html'>Einige meiner Leser(innen) scheinen es noch nicht zu wissen: Die Denkspuren gibt es seit einiger Zeit auch auf Twitter (&lt;a href="http://twitter.com/denkspuren"&gt;twitter.com/denkspuren&lt;/a&gt;). Ich war anfangs skeptisch, ob ich mit Twitter etwas anfangen könne, aber ich wollte das Experiment wagen. Mittlerweile habe ich mich eingezwitschert ...&lt;br /&gt;&lt;br /&gt;Auf diesem Blog ist es ruhiger geworden. Dabei habe ich 2009 vielleicht so viel geschrieben wie nie zuvor -- allerdings nicht auf diesem Blog. Ich hatte ursprünglich erwartet, dass mir mein &lt;a href="http://denkspuren.blogspot.com/2009/03/konkatenative-programmiersprachen.html"&gt;Forschungssemester&lt;/a&gt; (März-August 2009) mehr Zeit für den Denkspuren-Blog schenken würde. Interessanterweise trat das Gegenteil ein. Die Forschung zu den konkatenativen Sprachen hat sich derart interessant und aufregend entwickelt (wie man es vielleicht aus den &lt;a href="http://denkspuren.blogspot.com/2009_09_01_archive.html"&gt;September-Beiträgen&lt;/a&gt; erahnen mag), dass ich jede freie Minute in die Entwicklung und Ausarbeitung von Ideen investiere. Dabei kommt dieser Blog momentan zu kurz. Ich bin gespannt, wie sich das 2010 entwickeln wird.&lt;br /&gt;&lt;br /&gt;All meinen Leser(innen) ein schönes Weihnachtsfest und ein gutes neues Jahr 2010.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-3725377847904759804?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/3725377847904759804/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=3725377847904759804' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3725377847904759804'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3725377847904759804'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2009/12/die-denkspuren-auf-twitter.html' title='Die Denkspuren auf Twitter'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-5852323906708309589</id><published>2009-09-17T11:09:00.003+02:00</published><updated>2009-09-17T11:33:42.410+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='concatenative programming'/><category scheme='http://www.blogger.com/atom/ns#' term='rewriting'/><category scheme='http://www.blogger.com/atom/ns#' term='Scheme'/><category scheme='http://www.blogger.com/atom/ns#' term='macros'/><title type='text'>Concatenative Programming via Rewriting in Scheme</title><content type='html'>The kernel of a concatenative programming language can be easily implemented using a rewriting system. As a proof-of-concept the presented implementation fully relies on Scheme's rewriting system at macro expand time! All one needs is define-syntax and -- in order to provide access to Scheme's built-in procedures -- a single defmacro.&lt;br /&gt;&lt;br /&gt;(Apologies, if the formatting makes the code below hard to read. If you like to get the Scheme code, just drop me an email.)&lt;br /&gt;&lt;br /&gt;Rewriting rules concerning the data stack (ds) are written as follows:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(rule swap   : (@d ... snd fst) ==&gt; (@d ... fst snd)) &lt;br /&gt;      ^^^^     ^^^^^^^^^^^^^^^^     ^^^^^^^^^^^^^^^^^&lt;br /&gt;      word     datastack before      datastack after&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that the topmost element of the data stack is the rightmost element in the notation above.&lt;br /&gt;&lt;br /&gt;Rewriting rules concerning the data _and_ the program stack (ps) are written as&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(rule call   : (@d ... (@q ...)) (@p ...) ==&gt; (@d ...) (@q ... @p ...))&lt;br /&gt;      ^^^^     ^^^^^^^^^^^^^^^^^ ^^^^^^^^     ^^^^^^^^ ^^^^^^^^^^^^^^^&lt;br /&gt;      word          ds before    ps before    ds after    ps after&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that the topmost element of the program stack is the leftmost(!) element. Letting the data stack and the program stack "touch" their heads, makes it easier to describe the process when a word or quotation moves from the top of the program stack to the top of the data stack. The item just appears to move over to the other side.&lt;br /&gt;&lt;br /&gt;Quotations are written as lists. The notation for patterns is according to the conventions for syntax-rules in Scheme. The use of a "@" in patterns has no special syntactic meaning, it's just a personal preference.&lt;br /&gt;&lt;br /&gt;To run a concatenative program type&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt; (run () (2 3 plus))&lt;br /&gt;       ^^ ^^^^^^^^^^&lt;br /&gt;       ds     ps    &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you type this in at the console, the result just shows the resulting data stack since the program stack is empty.&lt;br /&gt;&lt;br /&gt;Here are some examples and their results (indicated by "--&gt;"):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt; (run (1 2) (3 4)) --&gt; (1 2 3 4)&lt;br /&gt;&gt; (run () (2 1 swap dup 1 plus)) --&gt; (1 2 3)&lt;br /&gt;&gt; (run (1 2) ((plus dup) call)) --&gt; (3 3)&lt;br /&gt;&gt; (run () (4 5 1 2 eq (plus) (minus) ifte)) --&gt; (-1)&lt;br /&gt;&gt; (run () (4 5 1 2 eq neg (plus) (minus) ifte)) --&gt; (9)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This is the way, I implemented the rewriting system with Scheme macros only. I use &lt;a href="http://www.plt-scheme.org"&gt;PLT Scheme&lt;/a&gt;, choose language "Pretty Big".&lt;br /&gt;&lt;br /&gt;First, we need to import "defmacro". In addition, we need a nice macro hack from Oleg Kiselyov, see "&lt;a href="http://okmij.org/ftp/Scheme/macros.html#macro-symbol-p"&gt;How to write symbol? with syntax-rules&lt;/a&gt;". We use it in the definition of 'run'.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(require mzlib/defmacro)&lt;br /&gt;&lt;br /&gt;(define-syntax symbol??&lt;br /&gt;  (syntax-rules ()&lt;br /&gt;    ((symbol?? (x . y) kt kf) kf)  ; It's a pair, not a symbol&lt;br /&gt;    ((symbol?? #(x ...) kt kf) kf) ; It's a vector, not a symbol&lt;br /&gt;    ((symbol?? maybe-symbol kt kf)&lt;br /&gt;      (let-syntax&lt;br /&gt; ((test&lt;br /&gt;    (syntax-rules ()&lt;br /&gt;      ((test maybe-symbol t f) t)&lt;br /&gt;      ((test x t f) f))))&lt;br /&gt; (test abracadabra kt kf)))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The rule macro transforms rewrite rules into new macros. For example, the rule for 'swap'&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(rule swap   : (@d ... snd fst) ==&gt; (@d ... fst snd))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;creates the following new macro&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;((swap (@d ... snd fst) ps) (run (@d ... fst snd) ps))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That means, whenever an s-expression with 'swap' being leftmost is encountered, such like '(swap (1 2 3) (4 5))', the macro is applied. In the example, the result is '(run (1 3 2) (4 5))'.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define-syntax rule&lt;br /&gt;  (syntax-rules (: ==&gt;)&lt;br /&gt;    ((_ word : (@d1 ...) ==&gt; (@d2 ...))&lt;br /&gt;     (define-syntax word&lt;br /&gt;       (syntax-rules ()&lt;br /&gt;         ((_ (@d1 ...) ps) (run (@d2 ...) ps)))))&lt;br /&gt;    ((_ word : (@d1 ...) ==&gt; (@d2 ...)&lt;br /&gt;               (@d3 ...) ==&gt; (@d4 ...))&lt;br /&gt;     (define-syntax word&lt;br /&gt;       (syntax-rules ()&lt;br /&gt;         ((_ (@d1 ...) ps) (run (@d2 ...) ps))&lt;br /&gt;         ((_ (@d3 ...) ps) (run (@d4 ...) ps)))))&lt;br /&gt;    ((_ word : (@d1 ...) (@p1 ...) ==&gt; (@d2 ...) (@p2 ...))&lt;br /&gt;     (define-syntax word&lt;br /&gt;       (syntax-rules ()&lt;br /&gt;         ((_ (@d1 ...) (@p1 ...)) (run (@d2 ...) (@p2 ...))))))&lt;br /&gt;    ((_ word : (@d1 ...) (@p1 ...) ==&gt; (@d2 ...) (@p2 ...)&lt;br /&gt;               (@d3 ...) (@p3 ...) ==&gt; (@d4 ...) (@p4 ...))&lt;br /&gt;     (define-syntax word&lt;br /&gt;       (syntax-rules ()&lt;br /&gt;         ((_ (@d1 ...) (@p1 ...)) (run (@d2 ...) (@p2 ...)))&lt;br /&gt;         ((_ (@d3 ...) (@p3 ...)) (run (@d4 ...) (@p4 ...))))))&lt;br /&gt;    ))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The run macro keeps the rewriting process running until the program stack is empty. The assumption is that there is a rewriting rule defined for symbols used on the program stack.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(define-syntax run&lt;br /&gt;  (syntax-rules ()&lt;br /&gt;    ((run (@d ...) ()) ; we are done&lt;br /&gt;     '(@d ...))&lt;br /&gt;    ((run (@d ...) (wrd @p ...)) ; inspect next wrd on program stack&lt;br /&gt;     (symbol?? wrd&lt;br /&gt;               (wrd (@d ...) (@p ...)) ; activate macro associated with wrd&lt;br /&gt;               (run (@d ... wrd) (@p ...)))))) ; move wrd on top of data stack&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In order to have access to Scheme's built in procedures, we introduce a rewriting rule for a word called 'alien'. In Scheme, a procedure such as '+' can also be called using apply:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt; (+ 2 3)&lt;br /&gt;5&lt;br /&gt;&gt; (apply + '(2 3))&lt;br /&gt;5&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Thus, 'alien' expects the arguments and a symbol on top of the data stack, each wrapped in a quotation/list. To interact with Scheme, we need to use defmacro _alien.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defmacro _alien (op q ds ps)&lt;br /&gt;  `(run (,@ds ,(apply (eval op) q)) ,ps))&lt;br /&gt; &lt;br /&gt;(define-syntax alien&lt;br /&gt;  (syntax-rules ()&lt;br /&gt;    ((_ (@d ... (@q ...) (op)) (@p ...))&lt;br /&gt;     (_alien op (@q ...) (@d ...) (@p ...)))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now let us define some rewriting rules:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(rule swap   : (@d ... snd fst) ==&gt; (@d ... fst snd))&lt;br /&gt;(rule dup    : (@d ... fst) ==&gt; (@d ... fst fst))&lt;br /&gt;(rule quote1 : (@d ... fst) ==&gt; (@d ... (fst)))&lt;br /&gt;(rule quote2 : (@d ... snd fst) ==&gt; (@d ...(snd fst)))&lt;br /&gt;(rule quote3 : (@d ... trd snd fst) ==&gt; (@d ... (trd snd fst)))&lt;br /&gt;(rule call   : (@d ... (@q ...)) (@p ...) ==&gt; (@d ...) (@q ... @p ...))&lt;br /&gt;(rule ifte   : (@d ... #f  (@t ...) (@e ...)) (@p ...) ==&gt; (@d ...) (@e ... @p ...)&lt;br /&gt;               (@d ... obj (@t ...) (@e ...)) (@p ...) ==&gt; (@d ...) (@t ... @p ...))&lt;br /&gt;(rule plus   : (@d ...) (@p ...) ==&gt; (@d ...) (quote2 (+) alien @p ...))&lt;br /&gt;(rule minus  : (@d ...) (@p ...) ==&gt; (@d ...) (quote2 (-) alien @p ...))&lt;br /&gt;(rule mult   : (@d ...) (@p ...) ==&gt; (@d ...) (quote2 (*) alien @p ...))&lt;br /&gt;(rule div    : (@d ...) (@p ...) ==&gt; (@d ...) (quote2 (/) alien @p ...))&lt;br /&gt;(rule eq     : (@d ...) (@p ...) ==&gt; (@d ...) (quote2 (eq?) alien @p ...))&lt;br /&gt;(rule neg    : (@d ... #f) ==&gt; (@d ... #t)&lt;br /&gt;               (@d ... obj) ==&gt; (@d ... #f))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And we are done ;-)&lt;br /&gt;&lt;br /&gt;For information about concatenative languages, see &lt;a href="http://concatenative.org"&gt;concatenative.org&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-5852323906708309589?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/5852323906708309589/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=5852323906708309589' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5852323906708309589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5852323906708309589'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2009/09/concatenative-programming-via-rewriting.html' title='Concatenative Programming via Rewriting in Scheme'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-6588129258638815114</id><published>2009-09-14T16:24:00.003+02:00</published><updated>2009-09-14T16:33:19.191+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='concatenative programming'/><category scheme='http://www.blogger.com/atom/ns#' term='types'/><category scheme='http://www.blogger.com/atom/ns#' term='Typen'/><category scheme='http://www.blogger.com/atom/ns#' term='Factor'/><category scheme='http://www.blogger.com/atom/ns#' term='Cat'/><category scheme='http://www.blogger.com/atom/ns#' term='type inference'/><title type='text'>Type Inference for "call" in Concatenative Languages</title><content type='html'>I think I solved the problem of type inference for "call" in concatenative languages. In a private mail, Slava Pestov (the creator of &lt;a href="http://factorcode.org"&gt;Factor&lt;/a&gt;) challenged me with the problem of inferring types for the bi and bi@ combinator. In essence, the problem boils down to "call". The solution, Christopher Diggins proposes in his &lt;a href="http://www.cat-language.com/paper.html"&gt;papers on Cat&lt;/a&gt; is not without complications.&lt;br /&gt;&lt;br /&gt;First let me introduce a notation for describing the effect of a word via substitutions. I use pattern matching. $X matches a single word, #X matches a single word _or_ quotation, and @X matches any number of words/quotations. To refer to a quotation, I use squared brackets. For example, "[ $X ]" matches a quotation with a single word inside like "[ 7 ]". Furthermore, I explicitly distinguish the data stack and the program stack and separate them with a bar "|". Here are some example substitutions:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@D #X | dup @P ==&gt; @D #X #X | @P&lt;br /&gt;@D #X #Y | swap @P ==&gt; @D #Y #X | @P&lt;br /&gt;@D $X&lt;int&gt; $Y&lt;int&gt; | + @P ==&gt; @D $Z&lt;int&gt; | @P&lt;br /&gt;@D [ @X ] [ @Y ] | append @P ==&gt; @D [ @X @Y ] | @P&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you can see, @D and @P explicitly catch the "rest" of the data stack and the program stack, respectively. The rules are precise specifications on the effects a word has on the data _and_ the program stack. Attachments like &lt;int&gt; are type annotations.&lt;br /&gt;&lt;br /&gt;The combination of a data and program stack represents a "continuation". A substitution rule substitutes a matching continuation by another continuation. &lt;br /&gt;&lt;br /&gt;Since concatenative programs are written in continuation passing style, so to speak, we can decompose the substitution of a continuation @DS | @PS into ( @DS | @P ) | @S with @PS = @P @S, meaning that @P and @S stand for any decomposition of @PS. For example, the program "dup *" can be decomposed into "dup" and "*". Instead of evaluating ( @DS | dup * @R ) with some instance of a data stack @DS, we can also first evaluate ( @DS | dup ), which must result in an empty program stack and a data stack @DS', and then evaluate ( @DS' | * @R ). For this process, we also write ( @DS | dup ) | * @R.&lt;br /&gt;&lt;br /&gt;Now we have everything in place to define the substitution rule for call:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@D [ @Q ] | call @P ==&gt; ( @D | @Q ) | @P&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The right hand side of the rule uses a continuation so that that further substitution rules for whatever is on @P can be applied and don't hinder stack effect inference.&lt;br /&gt;&lt;br /&gt;Let's take the program "call +" as an example. To avoid naming conflicts in the following, we repeat the rules for "call" and "+" and rename some pattern variables.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(1) @D1 [ @Q ] | call @P1  ==&gt; ( @D1 | @Q ) | @P1&lt;br /&gt;(2) @D2 $X&lt;int&gt; $Y&lt;int&gt; | + @P2 ==&gt; @D2 $Z&lt;int&gt; | @P2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The question to answer is: &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(?) @D | call + @P ==&gt; @D' | @P&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Rule (1) applies:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@D | call + @P ==&gt; ( @D1 | @Q ) | @P1&lt;br /&gt;with @D = @D1 [ @Q ] and @P1 = + @P&lt;br /&gt;               ==&gt; ( @D1 | @Q ) | + @P&lt;br /&gt;with @D = @D1 [ @Q ]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Rules (2) applies:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;               ==&gt; @D2 $Z&lt;int&gt; | @P2&lt;br /&gt;with @D = @D1 [ @Q ]&lt;br /&gt;and @D2 $X&lt;int&gt; $Y&lt;int&gt; = ( @D1 | @Q )&lt;br /&gt;and @P = @P2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We can conclude that&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@D1 [ @Q ] | call + @P ==&gt; @D2 $Z&lt;int&gt; | @P&lt;br /&gt;with&lt;br /&gt;( @D1 | @Q ) ==&gt; @D2 $X&lt;int&gt; $Y&lt;int&gt; | &lt;empty&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We are done! The result says that "quote +" expects a quotation [ @Q ] at the very top of the data stack with @D1 underneath. The result will be a data stack with elements @D2 and an integer $Z&lt;int&gt; on top. But there is a constraint which demands that the continuation ( @D1 | @Q ) returns a data stack with two integers on top and @D2 underneath.&lt;br /&gt;&lt;br /&gt;I don't find a way to express this any shorter. This is just the way it is. The example shows that type inference of "call +" is possible. Problems just occur if stack effect declarations (at least for the purpose of type inference) are limited to the data stack only. Consider Factor's stack effect declaration for call&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;call ( callable -- )&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;which does not capture the effect the created continuation has on the data stack.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-6588129258638815114?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/6588129258638815114/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=6588129258638815114' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6588129258638815114'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6588129258638815114'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2009/09/type-inference-for-call-in.html' title='Type Inference for &quot;call&quot; in Concatenative Languages'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-7862106532528518387</id><published>2009-07-07T00:48:00.002+02:00</published><updated>2009-07-07T00:58:37.842+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Patching'/><category scheme='http://www.blogger.com/atom/ns#' term='Code-Generierung'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Code-Generierung und Patching</title><content type='html'>Code-Generierung hat einen Vorteil, der oft übersehen wird: Man kann den generierten Code &lt;a href="http://de.wikipedia.org/wiki/Patch_%28Software%29"&gt;patchen&lt;/a&gt;, sprich Fehler darin beheben, ohne die Generator-Software anzufassen.&lt;br /&gt;&lt;br /&gt;Ich arbeite derzeit an einem Projekt, in dem aus XML-Dateien HTML-Dateien samt zugehörigem JavaScript generiert werden. Die XML-Dateien spezifizieren ein Dialogsystem, die per JavaScript gesteuerten HTML-Seiten führen das Dialogsystem aus.&lt;br /&gt;&lt;br /&gt;Nun ist es so, dass ich die Generatorsoftware nicht geschrieben habe. Zwar habe ich Zugriff auf den Quellcode, doch möchte ich am Code vorerst nichts ändern. Die Generatorsoftware hat sich in einem vorangegangenen Projekt bewährt, arbeitet zuverlässig und nimmt an den XML-Spezifikationen zahllose Konsistenzüberprüfungen vor -- und das ist Gold wert. Hier heißt es Finger weg, solange es geht, getreu der Devise: Never touch a running/working system.&lt;br /&gt;&lt;br /&gt;Im jetzigen Projekt wird jedoch anhand neuer XML-Spezifikationen deutlich, dass der Generator HTML-Code erzeugt, der Missverständnisse in den Anforderungen an das System offenbart. Der Generator erzeugt also Code, der nicht "passt". Und das, obwohl das System funktional sehr gut spezifiziert ist. That's life.&lt;br /&gt;&lt;br /&gt;Es ist nicht ohne Risiken, die Generatorsoftware direkt anzupassen: Ich baue mir möglicherweise neue Fehler ein, breche bestehende Funktionalitäten und riskiere Inkompatibilitäten zum generierten Code aus der ersten Projektphase.&lt;br /&gt;&lt;br /&gt;Eine Alternative ist, sich Programme zu schreiben, die die Probleme im generierten Code beheben (patchen). Diese Strategie lässt die Generatorsoftware unangetastet und intakt. Stattdessen beschränkt und fokussiert sich alle Aufmerksamkeit auf das Endprodukt, auf den durch die Patch-Programme modifizierten generierten Code. Genau darauf sollen sich auch die Testing-Energien konzentrieren, nicht auf die Generator-Software. Da die Komplexität der Patch-Programme -- im Vergleich zur Generatorsoftware -- gering und überschaubar ist, ist auch mit weniger Programmierfehlern zu rechnen. Zuguterletzt sind die Patch-Programme hervorragende Spezifikationen für die Änderungen, die in einem späteren Schritt an der Generatorsoftware vorgenommen werden können.&lt;br /&gt;&lt;br /&gt;Patching ist nicht nur eine simple Technik der Fehlerkorrektur, sondern es kann eine sehr gezielte Engineering-Aktivität sein, die hilft, bessere Software zu entwickeln.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-7862106532528518387?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/7862106532528518387/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=7862106532528518387' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/7862106532528518387'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/7862106532528518387'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2009/07/code-generierung-und-patching.html' title='Code-Generierung und Patching'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-3411207057632646252</id><published>2009-05-07T21:19:00.004+02:00</published><updated>2009-05-07T21:38:22.098+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='concatenative programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Parser Combinator'/><category scheme='http://www.blogger.com/atom/ns#' term='Factor'/><category scheme='http://www.blogger.com/atom/ns#' term='Cat'/><category scheme='http://www.blogger.com/atom/ns#' term='stack'/><category scheme='http://www.blogger.com/atom/ns#' term='Parser-Kombinator'/><category scheme='http://www.blogger.com/atom/ns#' term='Joy'/><title type='text'>RewriteParser &amp; RewriteParser-Kombinatoren</title><content type='html'>In der Vergangenheit habe ich über "&lt;a href="http://denkspuren.blogspot.com/2008/09/objekt-orientierte-parser-kombinatoren.html"&gt;Objekt-orientierte Parser-Kombinatoren in Python&lt;/a&gt;" geschrieben -- ein Thema, das mich immer noch fasziniert. Es ist so unglaublich einfach, einen Parser mit Parser-Kombinatoren zu entwickeln. Das ist gepaart mit einer Flexibilität, die traditionelle Parser-Ansätze a la lex &amp; yacc nicht bieten.&lt;br /&gt;&lt;br /&gt;In diesem Beitrag geht es (i) um die Verallgemeinerung eines Text-Parsers zum Parsen beliebiger Objektfolgen mit Hilfe zweier Stacks und (ii) um Parser, die ich RewriteParser nenne, und deren Kombination mit einem ganz speziellen RewriteParser-Kombinator, RPC*. Ich habe auf eine konkrete Programmiersprache verzichtet, damit das Prinzip klarer zutage tritt.&lt;br /&gt;&lt;br /&gt;Um die Idee der Parser-Kombinatoren nicht auf das Parsen von Zeichenketten zu beschränken, verallgemeinern wir die Idee, parsen beliebige Objekte von einem Stack und legen die Ergebnisse auf einem anderen Stack ab. Ein Parser (und somit auch ein Parser-Kombinator) nimmt zwei Stacks entgegen, ich nenne sie inStack und outStack, und liefert neben einem Flag für erfolgreiches Parsen zwei Stacks zurück, inStack' und outStack'. Zur Info: meine Stacks sind funktional, sprich immutabel.&lt;br /&gt;&lt;br /&gt;Was macht ein Parser generell? (1) Er prüft, ob ein bestimmtes Muster auf dem inStack zu finden ist -- dafür gibt es eine Funktion Crit(erion):Stack-&gt;Bool. (2) Er konsumiert kein oder mehr Elemente vom inStack -- die konsumierende Funktion heiße Consume:Stack-&gt;Stack. (3) Er produziert kein oder mehr Elemente für den Ausgabe-Stack -- der produzierte Stackanteil werde über Produce:Stack-&gt;Stack erzeugt.&lt;br /&gt;&lt;br /&gt;Wir können das etwas formaler beschreiben mit P(arser), Consume und Produce als Funktionen und SUCCESS = True, FAILURE = False. Der '+'-Operator produziert einen neuen Stack aus dem Aneinanderhängen zweier gegebener Stacks.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;P(Crit,Consume,Produce)(inStack,outStack) --&gt; success,inStack',outStack'&lt;br /&gt;if !Crit(inStack): return FAILURE, inStack, outStack&lt;br /&gt;return SUCCESS, inStack', outStack'&lt;br /&gt;with inStack' + Consume(inStack) == inStack&lt;br /&gt;and outStack' == outStack + Produce(inStack)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Die "with"-Schreibweise ist vielleicht etwas ungewöhnlich, aber sie besagt nur, dass der inStack' ein um Consume(inStack) reduzierter inStack ist. Und dass der outStack immer nur um Produce(inStack) anwachsen kann zu outStack'. Ich nutze für die Stackreduktion weiter unten kurzfristig auch das "-":&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;inStack' == inStack - Consume(inStack)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Ein Parser-Kombinator, der ein oder mehr Parser in irgendeiner Weise verknüft (bisweilen ist die Verknüpfung konfigurierbar), muss sich an dieselben Spielregeln halten: er ist auch wieder ein Parser, der möglicherweise Teile vom inStack oder den ganzen inStack konsumiert und möglicherweise etwas zum outStack beiträgt. Beachten Sie nochmal, dass Konsum und Produktion ausschließlich eine Funktion vom inStack sind! Der outStack kann z.B. als Gedächtnis nicht genutzt werden!&lt;br /&gt;&lt;br /&gt;Nachfolgend beschreibe ich einen Parser-Kombinator der zwei Parser komponiert: PC kombiniert zwei Parser &lt;code&gt;P1 = P(Crit1,Consume1,Produce1)&lt;/code&gt; und &lt;code&gt;P2 = P(Crit2,Consume2,Produce2)&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;PC(P1,P2)(inStack, outStack) --&gt; success, _inStack, _outStack&lt;br /&gt;success', inStack', outStack' = P1(inStack, outStack)&lt;br /&gt;if !success': return FAILURE, inStack, outStack&lt;br /&gt;success'', inStack'', outStack'' = P2(inStack', outStack')&lt;br /&gt;if !success'': return FAILURE, inStack, outStack&lt;br /&gt;return SUCCESS, inStack'', outStack''&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Man könnte auch für den Erfolgsfall zusammenfassen:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;inStack'' == inStack' - Consume2(inStack') &lt;==&gt;&lt;br /&gt;inStack'' == inStack - Consume1(inStack) - Consume2(inStack - Consume1(inStack))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;und&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;outStack'' == outStack + Produce1(inStack) + Produce2(inStack)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Die Komposition zweier Parser tut genau das, was man erwartet: erst konsumiert der erste Parser etwas vom inStack und legt sein Ergebnis auf dem outStack ab, dann folgt der zweite Parser, der weiteres vom inStack konsumiert und zusätzlich etwas auf dem outStack ablegt.&lt;br /&gt;&lt;br /&gt;Nachfolgende möchte ich eine Parser-Klasse vorstellen, die ich RewriteParser nenne. Sie verallgemeinern das Parser-Prinzip; sie sind aus meinen Spielereien und der Suche nach immer wieder neuen, verbesserten, generischeren Parser-Kombinatoren hervorgegangen. Allerdings hat es eine Weile gedauert, bis ich ihre neue Eigenschaft destilliert hatte.&lt;br /&gt;&lt;br /&gt;Der Unterschied zum Parser ist: Der Rewrite-Parser (RP) kann den inStack modifizieren! Der outStack kann nachwievor nicht gelesen, sondern nur produzierend (d.h. mit der Ablage neuer Elemente) bedient werden. &lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;RP(Crit,Rewrite,Produce)(inStack,outStack) --&gt; success,inStack',outStack'&lt;br /&gt;if !Crit(inStack): return FAILURE, inStack, outStack&lt;br /&gt;return SUCCESS, inStack', outStack'&lt;br /&gt;with inStack' == Rewrite(inStack)&lt;br /&gt;and outStack' == outStack + Produce(inStack)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Die Modifikation ist gering. Rewrite ist ebenso wie Consume eine Funktion, &lt;code&gt;Rewrite:stack-&gt;stack&lt;/code&gt;. Sie konsumiert jedoch nicht nur einen Teil des inStack, sondern kann ihn vollständig umschreiben und beispielsweise neue Elemente auf dem inStack ablegen (z.B. als Gedächtnis etwa in Form von Annotationen). Der nachfolgende RewriteParser arbeitet dann mit diesem modifizierten inStack.&lt;br /&gt;&lt;br /&gt;Schauen wir uns jetzt einmal einen RewriteParser-Kombinator an, der zwei Parser in eine Kompositionsbeziehung miteinander bringt. Wir berücksichtigen nun wieder den outStack. Es gilt &lt;code&gt;RP1 = RP(Crit1,Rewrite1,Produce1)&lt;/code&gt;, &lt;code&gt;RP2 = RP(Crit2,Rewrite2,Produce2)&lt;/code&gt;.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;RPC(RP1,RP2)(inStack,outStack) --&gt; success, _inStack, _outStack&lt;br /&gt;success', inStack', outStack' = RP1(inStack,outStack)&lt;br /&gt;if !success': return FAILURE, inStack, outStack&lt;br /&gt;success'', inStack'', outStack'' = RP2(inStack',outStack')&lt;br /&gt;if !success'': return FAILURE, inStack, outStack&lt;br /&gt;return SUCCESS, inStack'', outStack''&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Um das Kompositionsverhalten im Erfolgsfall verstehbar zu machen, auch hier wieder die Auflösung:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;inStack'' == Rewrite2(inStack') &lt;==&gt; (mit inStack' == Rewrite1(inStack))&lt;br /&gt;inStack'' == Rewrite2(Rewrite1(inStack))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Voila! Die Komposition zweier RewriteParser ist die Komposition ihrer Rewrite-Funktionen angewendet auf den inStack!&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;outStack'' == outStack' + Produce2(inStack')&lt;br /&gt;outStack' == outStack  + Produce1(inStack)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;mit&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;inStack' == Rewrite1(inStack)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;ergibt sich&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;outStack'' == outStack + Produce1(inStack) + Produce2(Rewrite1(inStack))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Das Ergebnis für den OutStack überrascht nicht. Hier legen RP1 und RP2 ihre Ergebnise der Verarbeitung von inStack bzw. inStack' ab&lt;br /&gt;&lt;br /&gt;Wir können schon einmal festhalten: Die Kombination von RewriteParsern entspricht der Funktionskomposition plus Seiteneffekte!&lt;br /&gt;&lt;br /&gt;Es gibt einen kleinen Kniff, der die Sache nun vollends interessant macht. Berücksichtigen wir bei der Komposition doch den Output von RP1, outStack', beim Input von RP2. Damit ist es nicht mehr nötig, RP2 als Ausgabe-Stack outStack' zu geben, da er den prinzipiell bei Produce berücksichtigen kann, sondern outStack. Ebenso benötigt RP1 nun nur einen EMPTYSTACK.&lt;br /&gt;&lt;br /&gt;Diesen modifizierten RPC bezeichne ich RPC*.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;RPC*(RP1,RP2)(inStack,outStack) --&gt; success, _inStack, _outStack&lt;br /&gt;success', inStack', outStack' = RP1(inStack,EMPTYSTACK)&lt;br /&gt;if !success': return FAILURE, inStack, outStack&lt;br /&gt;success'', inStack'', outStack'' = RP2(inStack'+outStack',outStack)&lt;br /&gt;if !success'': return FAILURE, inStack, outStack&lt;br /&gt;return SUCCESS, inStack'', outStack''&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Es ergibt sich nun für inStack'':&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;inStack'' == Rewrite2(inStack'+outStack')&lt;br /&gt;inStack'  == Rewrite1(inStack)&lt;br /&gt;outStack' == EMPTYSTACK + Produce1(inStack)&lt;br /&gt;---&lt;br /&gt;inStack'' == Rewrite2(Rewrite1(inStack)+Produce1(inStack))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Und für outStack'' ergibt sich:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;outStack'' == outStack + Produce2(inStack'+outStack')&lt;br /&gt;outStack'' == outStack + Produce2(Rewrite1(inStack)+Produce1(inStack))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Das Ergebnis hat zwei bemerkenswerte Eigenschaften. Zum einen: Darin ist vollständig der Parser-Kombinator RPC nachbildbar über geeignete Rewrite- und Produce-Funktionen. RPC* ist also erheblich mächtiger. Zum anderen: Es kommt wunderbar aus, dass das Argument zu Rewrite2 in inStack'' und zu Produce2 in outStack'' das gleiche ist! Das Ergebnis inStack'' kann entweder auf "normale" Funktionskomposition reduziert werden &lt;i&gt;oder&lt;/i&gt; es bekommt ein Ergebnis einer Vorverarbeitung durch Produce1(inStack) dazu! Mit diesem Input arbeitet auch Produce2 und kann das Gedächtnis beim Hinzufügen eines Ergebnisses zu outStack berücksichtigen.&lt;br /&gt;&lt;br /&gt;Für diejenigen, die sich mit &lt;a href="http://denkspuren.blogspot.com/2009/03/konkatenative-programmiersprachen.html"&gt;konkatenativer Programmierung&lt;/a&gt; schon einmal befasst haben (siehe z.B. &lt;a href="http://factorcode.org/"&gt;Factor&lt;/a&gt;, &lt;a href="http://www.latrobe.edu.au/philosophy/phimvt/joy.html"&gt;Joy&lt;/a&gt; oder &lt;a href="http://www.cat-language.com/"&gt;Cat&lt;/a&gt;), sei verraten, dass sich das konkatenative Paradigma mit RewriteParsern und RPC* vollständig umsetzen lässt. Oder anders herum: Konkatenative Programmierung kann man verstehen als die Programmierung mit RewriteParsern, die durch PRC* komponiert werden.&lt;br /&gt;&lt;br /&gt;Ich weiß, das war viel. Aber vielleicht werden Sie den Nutzen der RewriteParser erkennen, wenn Sie selber einmal mit Parser-Kombinatoren arbeiten und programmieren.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-3411207057632646252?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/3411207057632646252/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=3411207057632646252' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3411207057632646252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3411207057632646252'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2009/05/rewriteparser-rewriteparser.html' title='RewriteParser &amp; RewriteParser-Kombinatoren'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-4191621002484402250</id><published>2009-03-30T10:56:00.010+02:00</published><updated>2009-03-31T14:34:50.532+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='abwrackprämie'/><category scheme='http://www.blogger.com/atom/ns#' term='umweltprämie'/><category scheme='http://www.blogger.com/atom/ns#' term='bafa'/><title type='text'>Abwrackprämie am Limit</title><content type='html'>(Update 31. März 2009: Der Geschäftsführer der Babiel GmbH, Herr Dr. Rainer Babiel, hat mich gebeten noch einmal ausdrücklich darauf hinzuweisen, dass seine Firma &lt;i&gt;nicht&lt;/i&gt; für das BAFA-Webformular rund um die Abwrackprämie verantwortlich ist. Das betrifft auch das Hosting. Dies geht auch aus den Nachträgen zu diesem Blogbeitrag hervor.)&lt;br /&gt;&lt;br /&gt;Ich gehöre auch zu denen, die sich heute morgen mit einer Funkuhr bewaffnet vor den Rechner setzten, um am Wettrennen um die Reservierung der "Abwrackprämie" teilzunehmen. Der Wettstreit wurde um 8 Uhr vom &lt;a href="http://www.bafa.de"&gt;Bundesamt für Wirtschaft und Ausfuhrkontrolle&lt;/a&gt; eröffnet unter &lt;a href="http://www.ump.bafa.de/"&gt;www.ump.bafa.de&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Bereits vor einer Woche habe ich mich schon zusammen mit einem Freund über den vorherzusehenden Zusammenbruch aufgeregt. Denn was die Sache so heikel macht: Jeder über die Webseite gestellte Antrag wird mit einer Zeitmarke versehen. Wer zuerst auf dem Webserver der BAFA registriert wird, der wird vorrangig bei der Gewährung der Umweltprämie für Altfahrzeuge behandelt. Bekanntlich ist der Geldtopf für die Prämie limitiert.&lt;br /&gt;&lt;br /&gt;Um 8 Uhr lief rein gar nichts. Nicht einmal ein "ping" ging an den Webserver durch. Um 8:14 Uhr bekam ich einen ersten "Sneak Preview" auf das Formular. Ein nettes Gimmick hat man sich da ausgedacht: Mit der Auswahl des Fahrzeugherstellers beginnt die Webseite irgendetwas nachzuladen, ich vermute den Fahrzeugtyp -- und kriegt natürlich keinen Kontakt mehr zum Server, da der überlastet ist.&lt;br /&gt;&lt;br /&gt;Ich rufe bei der BAFA an und melde meinen Protest an. Natürlich sitzt dort eine ebenso überlastete Dame im CallCenter. Über 90% der Anrufe seien Beschwerden zum Thema, sagt sie. Über das &lt;a href="http://www.bafa.de/bafa/de/imprint/index.html"&gt;Impressum der BAFA&lt;/a&gt; finde ich heraus, wer für den Internet-Auftritt verantwortlich und technischer Provider ist. Ich rufe dort um 10:05 Uhr an. Die Dame der &lt;a href="http://www.babiel.com/"&gt;Babiel GmbH&lt;/a&gt; kann mir lediglich verraten, dass man um das Problem des überlasteten Webauftritts wisse und man an seiner Behebung arbeite. Eine alternative IP-Adresse habe sie nicht. Und wann man den Server wieder im Griff habe, könne sie auch nicht sagen.&lt;br /&gt;&lt;br /&gt;Tja. Ich bin fassungslos -- und verärgert. Wie kann man so naiv sein? Nach diesem medialen und politischen Getöse um die Abwrackprämie ist ja wohl nicht schwer vorherzusehen gewesen, dass heute morgen Autohäuser, Privatmenschen und viele Journalisten für unzählige HTTP-Requests auf www.ump.bafa.de sorgen würden. 2.500 Euro sind ein mächtiger Anreiz für den Besuch der Webseite. Und wie kann man ein Formular entwerfen, das die Serverlast mit Nachladerei noch erhöht und den Frust aller Reservierungswilligen nur steigert?&lt;br /&gt;&lt;br /&gt;Die BAFA stellt Regelungen auf, deren technische Umsetzung die von ihr beauftragte Firma nicht zu beherrschen scheint. Damit ist die Reservierung der Umweltprämie kein faires Verfahren mehr. Es ist keine Sache der Schnelligkeit mehr sondern ein Glücksspiel, wer hier wann zuerst seinen Antrag elektronisch einreichen kann. Das wird eine Welle des Protests erzeugen. Die BAFA kann als Lösung eigentlich nur noch die Reihenfolge der heutigen Reservierungen per Losentscheid erstellen. Fraglich bleibt, ob man seinen Antrag heute überhaupt noch per Webformular stellen kann. Mittlerweile ist es fast 11 Uhr. Über drei Stunden hat niemand das Problem lösen können.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&lt;br /&gt;&lt;b&gt;Nachtrag 0:39 Uhr, 31. März:&lt;/b&gt; Unfassbar! Ein letzter Versuch vor dem Weg ins Bett beschert mir unverhofft ein Erfolgserlebnis: Der Antrag ist durch! Nach etwas mehr als 16 Stunden! Die zugeteilte Vorgangsnummer liegt über einer Million. Was mir das sagen soll, weiß ich nicht. Hoffentlich nichts Ungutes.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Nachtrag 22:52 Uhr:&lt;/b&gt; Die Webseite zur Reservierung der Umweltprämie scheint gänzlich vom Netz zu sein. In einer &lt;a href="http://www.bafa.de/bafa/de/pressemitteilungen/2009/10_umweltpraemie.html"&gt;Pressemitteilung&lt;/a&gt; bedauert das BAFA "technische Schwierigkeiten" und verkündet "externer Dienstleister arbeitet an Lösung". Wir dürfen gespannt sein, was es mit den in der Pressemitteilung erwähnten Denial-of-Service-Attacken auf sich haben soll -- das BAFA will morgen um 10 Uhr weitere Hinweise auf seinen Webseiten veröffentlichen. Ich bin gespannt, ob sich der BAFA-Datenschutzbeauftragte Ulrich Schydlo (siehe &lt;a href="http://www.bafa.de/bafa/de/imprint/index.html"&gt;BAFA-Impressum&lt;/a&gt;) morgen aufgeweckt zeigt. Allein die unverschlüsselten Formulareingaben hätte er wohl kaum tolerieren dürfen. Sollten die heise-Meldungen stimmen, dann hätte er allen Grund vehement einzuschreiten.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Nachtrag 18:58 Uhr:&lt;/b&gt; Auf heise.de ist vor einer halben Stunde von massiven Pannen in Sachen Datenschutz berichtet worden: "&lt;a href="http://www.heise.de/newsticker/Auto-Abwrackpraemie-Daten-schutz-pannen-bei-Online-Reservierung--/meldung/135460"&gt;Auto-Abwrackprämie: Daten(schutz)pannen bei Online-Reservierung&lt;/a&gt;". Die Bestätigungsmails werden angeblich nicht immer an die richtigen Antragsteller(innen) geschickt. Ich bin nicht einen Schritt weiter gekommen. Im Moment sieht es nicht besser als kurz nach 8 Uhr heute morgen aus.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Nachtrag 17:04 Uhr:&lt;/b&gt; Die Reaktionszeiten des Portals haben sich spürbar verbessert. Nun kann ich wiederholt meine Daten angeben, um dann dabei unterbrochen zu werden mit dem Hinweis:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Willkommen auf dem Antragsportal für die Umweltprämie!&lt;br /&gt;&lt;br /&gt;Leider ist das Antragsportal zur Zeit überlastet. Bitte versuchen Sie es in einigen Minuten erneut. Vielen Dank für Ihr Verständnis.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Auf mein Verständnis sollte man nach einem Tag nicht mehr hoffen!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Nachtrag 15:05 Uhr:&lt;/b&gt; Immerhin, ich bin bis zur Gotcha-Seite vorgedrungen. Ich klicke auf weiter und komme zur einer Seite mit dem wörtlichen Hinweis:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Aktuell laden sehr viele Antragsteller einen Kaufvertrag hoch.&lt;br /&gt;&lt;br /&gt;Die Anzahl paralleler Uploads ist aber begrenzt. Diese Seite aktualisiert sich automatisch, bis Sie Ihren Upload starten können.&lt;br /&gt;Verzichten Sie bitte daher auf die Funktion 'Neu laden'&lt;br /&gt;&lt;br /&gt;Die Wartezeit sollte 60 Sekunden nich überschreiten.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Ja, da steht "nich überschreiten". Übrigens muss man als Vollendung dieser Unprofessionalität den Versand der eigenen Daten über eine unsichere Verbindung hinnehmen! Das ist schon fast ein regelrechter Datenskandal!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Nachtrag 12:58 Uhr:&lt;/b&gt; Im Impressum der BAFA ist mittlerweile ein Hinweis erschienen, dass die Formularseite für die Reservierung der Umweltprämie &lt;i&gt;nicht&lt;/i&gt; von der Babiel GmbH gehostet wird. Als ich dort gegen 10 Uhr anrief, wusste die Firma selbst das noch nicht ...&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Nachtrag 11:53 Uhr:&lt;/b&gt; Die folgende Meldung findet sich auf der Homepage der BAFA -- auch das hat Stunden gedauert:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Aufgrund von technischen Problemen kommt es derzeit zu Schwierigkeiten beim Aufruf und beim Ausfüllen des Reservierungsantrags, die nicht im Einflussbereich des BAFA liegen. Das BAFA unternimmt alles in seiner Macht stehende, damit dieses Problem schnellstmöglich behoben wird. Bis dahin bitten wir um Ihr Verständnis.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Die Meldung an sich ist bereits amüsant. Die technischen Probleme liegen nicht im Einflussbereich der BAFA. Dennoch will man Mächte aktivieren, die Einfluss auf den Einflussbereich nehmen. Spannend!&lt;br /&gt;&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-4191621002484402250?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/4191621002484402250/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=4191621002484402250' title='4 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/4191621002484402250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/4191621002484402250'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2009/03/abwrackpramie-am-limit.html' title='Abwrackprämie am Limit'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-9080331890403775920</id><published>2009-03-01T22:14:00.002+01:00</published><updated>2009-03-01T22:23:32.164+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='funktionale Programmierung'/><category scheme='http://www.blogger.com/atom/ns#' term='Factor'/><category scheme='http://www.blogger.com/atom/ns#' term='Cat'/><category scheme='http://www.blogger.com/atom/ns#' term='Joy'/><title type='text'>Konkatenative Programmiersprachen</title><content type='html'>Mit dem heutigen Tag beginnt offiziell mein Forschungssemester. Mein Thema: "A Model of Computation in Space and Time" -- darüber werde ich vielleicht ein anderes Mal was schreiben.&lt;br /&gt;&lt;br /&gt;Was sich in den letzten Wochen mehr und mehr aufdrängt, ist, das ein Schlüssel zu meinem Thema in den konkatenativen Sprachen liegt. Ich weiß es noch nicht sicher, aber mit jedem Tag finde ich mehr und mehr Gründe, mich mit dieser Klasse von Sprachen auseinander zu setzen.&lt;br /&gt;&lt;br /&gt;Was, Sie haben noch nie etwas von &lt;em&gt;&lt;a href="http://concatenative.org"&gt;concatenative languages&lt;/a&gt;&lt;/em&gt; gehört?&lt;br /&gt;&lt;br /&gt;Verwunderlich ist das nicht. Konkatenative Sprachen führen zu unrecht ein vollkommenes Schattendasein. Wenn Sie sich für Ruby, Python, Groovy, Scheme, Lisp, Clojure, Haskell, F#, Prolog begeistern können, dann sollten konkatenative Sprachen wie Joy, Cat und Factor ein gefundenes Fressen für Sie sein. Diese drei Sprachen führen Sie in eine ganz neue Programmierwelt ein.&lt;br /&gt;&lt;br /&gt;Konkatenative Sprachen gehören zu den funktionalen Sprachen. Manfred von Thun hat auf seiner Webseite zu &lt;a href="http://www.latrobe.edu.au/philosophy/phimvt/joy.html"&gt;Joy&lt;/a&gt; einen wunderbaren Satz an Beiträgen zusammengestellt, die behutsam in diese rein funktionale Welt konkatenativer Programmierung mit Joy einführen. Auch die Sprache &lt;a href="http://www.cat-language.com/"&gt;Cat&lt;/a&gt; von Christopher Diggins ist interessant. Cat ist in C# implementiert und ein Studium wert.&lt;br /&gt;&lt;br /&gt;Während Joy und Cat mehr Experimentalcharakter haben, ist &lt;a href="http://factorcode.org/"&gt;Factor&lt;/a&gt; eine ernstzunehmende Programmiersprache, die der Pragmatik zuliebe auf ein striktes funktionales Paradigma verzichtet. Für mich ist Factor die spannendste Sprache, die am Programmierhorizont zu sichten ist. Ich habe Factor schon ein Weilchen auf dem Radar und schrieb vor einem Jahr "&lt;a href="http://denkspuren.blogspot.com/2007/03/factor-in-der-krze-liegt-die-wrze.html"&gt;Factor: In der Kürze liegt die Würze&lt;/a&gt;". Ihr Schöpfer, &lt;a href="http://en.wikipedia.org/wiki/Slava_Pestov"&gt;Slava Pestov&lt;/a&gt; (übrigens hat er auch &lt;a href="http://jedit.org/"&gt;jEdit&lt;/a&gt; entwickelt), wird übermorgen, am 3. März 2009, 25 Jahre alt! Vielleicht mag das insbesondere die Informatik-Studierenden unter meinen Lesern motivieren. Andererseits: Slava Pestovs &lt;a href="http://factorcode.org/slava/"&gt;Biographie&lt;/a&gt; liest sich fast wie die eines Wunderkindes, der früh einen Draht zur Mathematik und Informatik fand. Seine Sprache Factor ist so voll gefüllt mit modernen Programmierkonzepten und so intelligent aufgebaut -- ich finde es mehr als beachtlich, wie man so jung derart smart und zielstrebig eine so qualitativ hochwertige Programmiersprache auf die Beine stellen kann, die einen Guido van Rossum (Schöpfer von Python) oder einen Matz (Yukihiro Matsumoto, Schöpfer von Ruby) alt aussehen lassen. &lt;br /&gt;&lt;br /&gt;Vielleicht habe ich Sie jetzt ja neugierig gemacht ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-9080331890403775920?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/9080331890403775920/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=9080331890403775920' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/9080331890403775920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/9080331890403775920'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2009/03/konkatenative-programmiersprachen.html' title='Konkatenative Programmiersprachen'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-4921400502755039406</id><published>2009-02-28T11:51:00.007+01:00</published><updated>2009-03-10T21:07:26.623+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fehler'/><category scheme='http://www.blogger.com/atom/ns#' term='Lidl'/><title type='text'>Ist der Kassen-Bug von Lidl ein Bug?</title><content type='html'>Mein Posting "&lt;a href="http://denkspuren.blogspot.com/2008/04/lidl-und-der-kassen-bug.html"&gt;Lidl und der Kassen-Bug&lt;/a&gt;" ist seit seinem Erscheinen immer noch der am meisten gelesene Beitrag in meinen Denkspuren. Nie hätte ich daran geglaubt, dass er diese Popularität genießen würde, denn er ist einer von den Beiträgen, die mir selber weniger bedeuten. "&lt;a href="http://denkspuren.blogspot.com/2008/04/lidl-und-der-kassen-bug.html"&gt;Lidl und der Kassen-Bug&lt;/a&gt;" erschien am 15. April 2008. Ich hatte den Tipp von einem meiner Studierenden bekommen. Allerdings wollte ich mit eigenen Augen sehen, ob der Tipp wirklich das versprochene Ereignis auslöst, bevor ich darüber blogge.&lt;br /&gt;&lt;br /&gt;Als ich über den Kassen-Bug berichte, gibt es einen kleinen, fast schon aufregenden Peak in den Visits (ich nutze Google Analytics). Die seinerzeit noch üblichen 20, 30, 40 oder auch mal 50 Visits an einem Tag schrauben sich am 15. April auf ungekannte 97 Visits hoch. Am Folgetag gibt es 190 Visits zu verzeichnen, dann 124, dann 100, ... und dann ist schon wieder alles beim alten. Ein paar Tage später, mit Beginn der neuen Woche beginnt es zu rumpeln. Genau eine Woche später, am 22. April scheint der Beitrag auf das Radar von Lesern zu kommen, die sonst die Denkspuren nicht besuchen. Am 4. Mai verzeichne ich den absoluten Besuchsrekord: 5.362 Visits an einem Tag! Es ist ein Peak, aber in der Folgezeit habe ich immer noch ungewohnt hohe und teils stark schwankende Besuchszahlen. Allein in der Zeit vom 22. April bis zum 21. Mai 2008 zählt Google Analytics 25.150 Visits und 34.586 Pageviews. Anfang Juni ist der "Spuk" vorbei. Die Besuchszahlen pendeln sich allmählich wieder auf die Ausgangsdimensionen ein. Ich darf seitdem lediglich im Mittel eine etwas höhere Besuchszahl verzeichnen, meist in der Spannbreite von 35 bis 70 Visits/Tag. In den letzten 30 Tagen (29. Januar - 27. Februar) gab es 1.608 Visits und 1.987 Pageviews.&lt;br /&gt;&lt;br /&gt;Das Ganze war für mich eine absolut interessante Lehrstunde in Sachen Dynamik, die das Web entwickeln kann! Beliebte Seiten, wie golem.de, hatten über "Lidl und der Kassen-Bug" berichtet und einen Teil des Ansturms ausgelöst. Ich hätte diese Entwicklung niemals für diesen Beitrag vorauszusagen gewagt. Never ever!&lt;br /&gt;&lt;br /&gt;In den Kommentaren zu dem Posting (in meinem Blog und anderswo) spekulieren einige meiner Leser(innen) sehr phantasiereich über die Umstände der möglichen Entstehung des Kassen-Bugs. Einige haben sogar konkrete Codezeilen vor Augen. Nur eine sehr kleine Fraktion hält das von mir als Bug deklarierte Ereignis gar nicht für einen Fehler. Kann es sein, dass der Kassen-Bug bei Lidl gar kein Bug, sondern ein Feature ist?&lt;br /&gt;&lt;br /&gt;Gut möglich. Dafür spricht, dass die Kasse bei dem Null-Betrag weder abstürzt noch abraucht (das wäre ein Spaß, was?! ;-), sondern ein definiertes Verhalten zeigt. Dagegen spricht, dass die Kassierer und Kassiererinnen auf dieses Kassenverhalten gar nicht vorbereitet sind. Sie reagieren ratlos, weil sie den Fehler nicht kennen, oder lösen das Problem mit einem Workaround ("Ich zieh das hier wieder ab, dann geht die Kasse wieder und sie zahlen das hier dann gesondert, ok?"). Was für ein Interesse sollte ein Discounter daran haben, bei einer Nullsumme die Kasse zu blockieren, wenn der Workaround so simpel ist?&lt;br /&gt;&lt;br /&gt;Ist der Kassen-Bug nun ein Bug oder ein Feature?&lt;br /&gt;&lt;br /&gt;Ich plädiere zwar auf Bug, glaube die Argumente auf meiner Seite, aber das will nichts heißen. Meinen kann man im Web viel. Letztlich ist die Frage nicht zu beantworten. Es sei denn, wir verlassen die Komfortzone des Browserfensters, begeben uns in die Welt da draußen und klären das Phänomen des Kassen-Bugs auf.&lt;br /&gt;&lt;br /&gt;Wollen Sie wissen, ob der Kassen-Bug ein Bug ist? Wollen Sie mir das Gegenteil beweisen?&lt;br /&gt;&lt;br /&gt;Finden Sie's raus! Besuchen Sie den nächsten Lidl und fragen Sie bei der Filialleitung nach. Vielleicht kommen Sie da weiter. Oder greifen Sie zum Telefon, rufen bei Lidl an und bitten um Kontakt mit dem "Kassen-Verantwortlichen"; man könnte es bei der Lidl-eigenen IT-Abteilung versuchen. Wer ist der Hersteller der Kassen? Kann man Ihnen dort in der Entwicklungsabteilung einen Hinweis geben oder das Problem aufklären? Irgendwo da draußen in der Realwelt gibt es jemanden, der uns die Frage "Bug oder Feature?" beantworten kann.&lt;br /&gt;&lt;br /&gt;Der Erste bzw. die Erste, der/die mir bis zum 31. März 2009 eine EMail schickt mit einer nachvollziehbaren Antwort unter Quellenangaben wie z.B. Gesprächspartner samt Telefonnummer (ich möchte Ihre Angaben überprüfen können), dem verspreche ich ein kleines Buchgeschenk. Da wir das Darwin-Jahr haben, habe ich für Sie das Buch von Joachim Bauer "Das kooperative Gen" ausgesucht. Sie dürfen sich bei akzeptierter Antwort aber auch gerne ein anderes Buch bis 20 Euro wünschen.&lt;br /&gt;&lt;br /&gt;Viel Erfolg!&lt;br /&gt;&lt;br /&gt;[Nachtrag vom 10. März: Meinen herzlichen Glückwunsch an Marius Heisler. Dank seiner Recherchen weiß ich nun, dass der Kassen-Bug bei Lidl definitiv kein Feature ist. Heute hat mir die Pressestelle von Lidl das bestätigt. Die Pressesprecherin spricht selber von einer Kasse, "die sich aufgehängt hat". Sie bittet jedoch um Verständnis, "dass wir darüber hinaus keine detaillierten Angaben zur Softwarethematik machen möchten". Schade eigentlich.]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-4921400502755039406?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/4921400502755039406/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=4921400502755039406' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/4921400502755039406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/4921400502755039406'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2009/02/ist-der-kassen-bug-von-lidl-ein-bug.html' title='Ist der Kassen-Bug von Lidl ein Bug?'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-5070920527181686075</id><published>2009-01-19T19:44:00.006+01:00</published><updated>2009-01-19T22:14:18.926+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='FSM'/><category scheme='http://www.blogger.com/atom/ns#' term='finite state machine'/><category scheme='http://www.blogger.com/atom/ns#' term='Zustandsmaschine'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Was sind das für Zustände?</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_XJMaba79IKU/SXTGvLghv6I/AAAAAAAAAHk/waGJyG1yVyg/s1600-h/ZustandsmaschineRoboterarm.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://4.bp.blogspot.com/_XJMaba79IKU/SXTGvLghv6I/AAAAAAAAAHk/waGJyG1yVyg/s400/ZustandsmaschineRoboterarm.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5293073975912546210" /&gt;&lt;/a&gt;&lt;br /&gt;Zustandsmaschinen dienen in der Informatik zur Modellierung von Verhalten. Sie werden besonders gerne zur Spezifikation technischer Systeme eingesetzt. Oben im Bild sehen Sie ein einfaches Zustandsdiagramm. Zustandsdiagramme sind eine verbreitete Notation zur Darstellung von Zustandsmaschinen. Die Notation ist in der Unified Modeling Language (UML) standardisiert.&lt;br /&gt;&lt;br /&gt;In dem Beispiel geht es um einen Roboterarm. Der Roboterarm ist entweder in dem Zustand "idle", "moving up/down" bzw. "welding" (schweißen); Zustände werden durch Rechtecke mit runden Ecken abgebildet. Der Start- und der Endzustand sind durch besondere Symbole hervorgehoben: durch einen Kreis (Start) bzw. einen Punkt im Kreis (Ende).&lt;br /&gt;&lt;br /&gt;Die Pfeile beschreiben Übergänge (Transitionen) von einem Zustand in einen anderen und zwar abhängig von einem Ereignis. Die Ereignisse sind hier durch Buchstaben abgekürzt und stehen immer links vom Schrägstrich "/". Es sind Ereignisse, die der Roboter über seine Sensoren wahrnimmt. Die meisten der Ereignisse werden durch Steuerungssensoren wahrgenommen. Wenn ein Anwender den "down"-Knopf drückt, dann löst er damit das "d"-Ereignis aus. Ein "up" führt zu einem "u"-Ereignis, ein "s" zu "stop" und ein "o" ist die Folge eines "on"- bzw. "off"-Signals. Einzig das "c"-Ereignis wird durch einen Kontakt-Sensor ("contact") im Roboterarm ausgelöst. Dann "fühlt" der Roboterarm einen Widerstand.&lt;br /&gt;&lt;br /&gt;Zu jedem Ereignis ist rechts vom Schrägstrich angegeben, was der Roboterarm für eine Aktion folgen lässt. Grundsätzlich möglich sind die Aktionen "move down", "move up", "stop moving", "weld" (schweiße), "initialize" und "shut down".&lt;br /&gt;&lt;br /&gt;Befindet sich der Roboterarm im Zustand "idle" und tritt das Ereignis "d" auf (sprich, der Anwender hat den "down"-Knopf gedrückt"), dann bewegt sich der Roboterarm nach unten. Der Zustand wechselt von "idle" auf "moving down". Weitere "d"-Ereignisse bleiben ohne Folge, da sich der Roboterarm bereits in der Abwärtsbewegung befindet. Im Zustand "moving down" bewegt ein "u" den Arm wieder nach oben, ein "c" stößt die Schweiß-Aktivität an. Beim "u"-Ereignis wechselt der Zustand zu "moving up", beim "c"-Ereignis zu "welding".&lt;br /&gt;&lt;br /&gt;Eine solche Zustandsmaschine kann man systematisch in Code übertragen. Der Vorgang ist derart schematisch, dass man ihn leicht automatisieren kann. Dafür übertragen wir in einem ersten Schritt das Diagramm in ein maschinenlesbares Format. Ich habe mich für XML entschieden. (Hinweis: Für die nachstehenden Code-Auszüge verwende ich den &lt;a href="http://code.google.com/p/syntaxhighlighter/"&gt;syntaxhighlighter&lt;/a&gt;. Möglicherweise gibt es Darstellungsprobleme, wenn Sie z.B. einen RSS-Reader nutzen. Dann besuchen Sie einfach direkt die &lt;a href="http://denkspuren.blogspot.com/2009/01/was-sind-das-fr-zustnde.html"&gt;Blogseite zum Posting&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;&lt;textarea name="code" class="xml"&gt;&lt;br /&gt;&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;br /&gt;&lt;fsm name="Robot" version="1.0" … &gt;&lt;br /&gt;    &lt;states&gt;&lt;br /&gt;      &lt;state name="start" type="init"/&gt;&lt;br /&gt;      &lt;state name="end"   type="final"/&gt;&lt;br /&gt;      &lt;state name="idle"/&gt;&lt;br /&gt;      &lt;state name="moving up"/&gt;&lt;br /&gt;      &lt;state name="moving down"/&gt;&lt;br /&gt;      &lt;state name="welding"/&gt;&lt;br /&gt;    &lt;/states&gt;&lt;br /&gt;    &lt;transitions&gt;&lt;br /&gt;      &lt;transition fromState="start" toState="idle" event="o"&gt;&lt;br /&gt;        printf("&gt;&gt;&gt; initialize\n");&lt;br /&gt;      &lt;/transition&gt;&lt;br /&gt;      &lt;transition fromState="idle" toState="end" event="o"&gt;&lt;br /&gt;        printf("&gt;&gt;&gt; shut down\n");&lt;br /&gt;      &lt;/transition&gt;&lt;br /&gt;      &lt;transition fromState="idle" toState="moving down" event="d"&gt;&lt;br /&gt;        printf("&gt;&gt;&gt; move down\n");&lt;br /&gt;      &lt;/transition&gt;&lt;br /&gt;      &lt;transition fromState="moving down" toState="moving down" event="d"&gt;&lt;br /&gt;        /* don't do anything */&lt;br /&gt;      &lt;/transition&gt;&lt;br /&gt;      &lt;transition fromState="moving down" toState="idle" event="s"&gt;&lt;br /&gt;        printf("&gt;&gt;&gt; stop moving\n");&lt;br /&gt;      &lt;/transition&gt;&lt;br /&gt;      &lt;transition fromState="moving down" toState="moving up" event="u"&gt;&lt;br /&gt;        printf("&gt;&gt;&gt; move up\n");&lt;br /&gt;      &lt;/transition&gt;&lt;br /&gt;      &lt;transition fromState="moving down" toState="welding" event="c"&gt;&lt;br /&gt;        printf("&gt;&gt;&gt; weld\n");&lt;br /&gt;      &lt;/transition&gt;&lt;br /&gt;      &lt;transition fromState="welding" toState="moving up" event="u"&gt;&lt;br /&gt;        printf("&gt;&gt;&gt; move up\n");&lt;br /&gt;      &lt;/transition&gt;&lt;br /&gt;      &lt;transition fromState="moving up" toState="idle" event="s"&gt;&lt;br /&gt;        printf("&gt;&gt;&gt; stop moving\n");&lt;br /&gt;      &lt;/transition&gt;&lt;br /&gt;      &lt;transition fromState="moving up" toState="moving down" event="d"&gt;&lt;br /&gt;        printf("&gt;&gt;&gt; move down\n");&lt;br /&gt;      &lt;/transition&gt;&lt;br /&gt;    &lt;/transitions&gt;&lt;br /&gt;&lt;/fsm&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Das Eingangstag &amp;lt;fsm&amp;gt; steht für &lt;em&gt;finite state maschine&lt;/em&gt;. Es folgt die Liste der (endlich vielen) Zustände, wobei der Start- und der Endzustand beliebig benannt werden können, sie dafür aber mit Hilfe des type-Attributes auszuweisen sind. Die Liste der Transitionen ist nahezu selbsterklärend. Die Aktionen geben wir als Programmcode in der Sprache C an. Das ist in dem Beispiel die Sprache, in der wir den Roboterarm programmieren, was nicht untypisch für Steuergeräte oder eingebettete Systeme ist. Zu Demonstrationszwecken ersetzen einfache printf-Statements "echte" Aktionen.&lt;br /&gt;&lt;br /&gt;Das Interface des zu generierenden Codes -- Funktionsprototypen in C -- sieht wie folgt aus. Es ist absichtlich so einfach gehalten.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="c"&gt;&lt;br /&gt;char * get_initState(void);&lt;br /&gt;char * get_finalState(void);&lt;br /&gt;char * get_toState(char *fromState, char *event);&lt;br /&gt;void do_action(char *fromState, char *event);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Es ist einfach zu erraten, wie der generierte Code zu "get_initState" und "get_finalState" aussieht:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="c"&gt;&lt;br /&gt;char * get_initState(void) { return "start"; }&lt;br /&gt;char * get_finalState(void) { return "end"; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Die Funktion "get_toState" liefert auf Angabe von "fromState" und "event" den dazugehörigen "toState" zurück. Ein Beispiel:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="c"&gt;&lt;br /&gt;char * get_toState(char *fromState, char *event) {&lt;br /&gt;  if (strcmp("idle",fromState) == 0 &amp;&amp; strcmp("o",event) == 0)&lt;br /&gt;      return "end";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ein Kinderspiel, nicht wahr? Die Funktion "do_action" arbeitet ganz ähnlich, sie bettet im if-Rumpf den Aktionscode zur Transition ein:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="c"&gt;&lt;br /&gt;void do_action(char *fromState, char *event) {&lt;br /&gt;  if (strcmp("idle",fromState) == 0 &amp;&amp; strcmp("o",event) == 0) {&lt;br /&gt;    printf("&gt;&gt;&gt; shut down\n");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Wenn wir einen Code-Generator haben, der die XML-Darstellung in diese Code-Schemata umwandelt, dann benötigen wir nur noch ein Abarbeitungsprogramm, das Steuerprogramm im Roboterarm, das auf Ereignisse wartet (Tastendrücke in unserem Beispiel), gemäß Zustandsmaschine die entsprechenden Aktionen ausführt und in einen neuen Zustand wechselt oder den bisherigen beibehält. (Die Funktion _getch() ist übrigens eine nicht standardgemäße Bibliotheksfunktion aus &lt;a href="http://en.wikipedia.org/wiki/Pelles_C"&gt;Pelles C&lt;/a&gt; zum Lesen eines Zeichens von der Tastatur.) &lt;br /&gt;&lt;br /&gt;&lt;textarea name="code" class="c"&gt;&lt;br /&gt;#include &lt;stdio.h&gt;&lt;br /&gt;#include &lt;stdlib.h&gt;&lt;br /&gt;#include &lt;conio.h&gt; // not C99&lt;br /&gt;#include &lt;assert.h&gt;&lt;br /&gt;&lt;br /&gt;#include "fsm.c"&lt;br /&gt;&lt;br /&gt;int main() {&lt;br /&gt;    char event[2] = "?"; // [0]: signal character, [1]: \0 (end of string)&lt;br /&gt;    char * currentState;&lt;br /&gt;    char * nextState;&lt;br /&gt;    char * finalState;&lt;br /&gt;&lt;br /&gt;    currentState = get_initState();&lt;br /&gt;    finalState = get_finalState();&lt;br /&gt;&lt;br /&gt;    printf("initializing: initState = %s, finalState = %s\n",currentState, finalState);&lt;br /&gt;    assert (strcmp(currentState,finalState) != 0);&lt;br /&gt;&lt;br /&gt;    // CONTROLLER&lt;br /&gt;    for (;;) {&lt;br /&gt;        printf("scanning ...\n");&lt;br /&gt;        event[0] = _getch();&lt;br /&gt;        printf("&lt;&lt;&lt; signal %s\n",event);&lt;br /&gt;&lt;br /&gt;        nextState = get_toState(currentState,event);&lt;br /&gt;        if (strcmp(nextState,"") == 0) {&lt;br /&gt;            printf("critical situation\n&gt;&gt;&gt; move to safety position\n");&lt;br /&gt;            break;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        do_action(currentState,event); &lt;br /&gt;        currentState = nextState;&lt;br /&gt;        if (strcmp(currentState,finalState) == 0) break;&lt;br /&gt;    }&lt;br /&gt;    printf("I'm done\n&gt;&gt;&gt; shut down\n");&lt;br /&gt;    return EXIT_SUCCESS;&lt;br /&gt;}&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Wie aus dem Code ersichtlich ist, ignoriert die Steuerung nicht etwa Ereignisse für die keine Transition in einem Zustand definiert ist, sondern aktiviert eine Safety-Routine. Das ist ein durchaus sinnvolles Vorgehen bei Steuerungsaufgaben, die im Fehlerfall schwerwiegende Folgen nach sich ziehen können.&lt;br /&gt;&lt;br /&gt;Stellt sich nur noch die Frage, wie der Code-Generator aussieht. Ich habe ihn in Python programmiert. Das Programm ist nicht sonderlich elegant, erfüllt aber zur Anschauung seinen Zweck.&lt;br /&gt;&lt;br /&gt;&lt;textarea name="code" class="python"&gt;&lt;br /&gt;import sys, time&lt;br /&gt;from xml.dom.minidom import parse&lt;br /&gt;&lt;br /&gt;assert len(sys.argv) &gt; 1, "file needed for code generation"&lt;br /&gt;fsm = parse(sys.argv[1])&lt;br /&gt;&lt;br /&gt;states = fsm.getElementsByTagName("state")&lt;br /&gt;transitions = fsm.getElementsByTagName("transition")&lt;br /&gt;&lt;br /&gt;for state in states:&lt;br /&gt;    statename = state.getAttribute("name")&lt;br /&gt;    statetype = state.getAttribute("type")    &lt;br /&gt;    if statetype == "init": initState = statename&lt;br /&gt;    elif statetype == "final": finalState = statename&lt;br /&gt;  &lt;br /&gt;## Assert that inital and final state are given  &lt;br /&gt;assert initState, "An init state must be given"&lt;br /&gt;assert finalState,"A final state must be given"&lt;br /&gt;&lt;br /&gt;## CodeGeneration: get_initState and get_finalState&lt;br /&gt;get_initState = 'char * get_initState(void) { return "%s"; }\n' % initState&lt;br /&gt;get_finalState = 'char * get_finalState(void) { return "%s"; }\n' % finalState&lt;br /&gt;&lt;br /&gt;## Assert constraints on fromState and toState&lt;br /&gt;statenames = [state.getAttribute("name") for state in states]&lt;br /&gt;for transition in transitions:&lt;br /&gt;    assert transition.getAttribute("fromState") in statenames,\&lt;br /&gt;           "fromState is given in list of states"&lt;br /&gt;    assert transition.getAttribute("toState") in statenames,\&lt;br /&gt;           "toState is given in list of states"&lt;br /&gt;           &lt;br /&gt;## Assert determinism&lt;br /&gt;stateevents = []&lt;br /&gt;for transition in transitions:&lt;br /&gt;    stateevent = (transition.getAttribute("fromState"),&lt;br /&gt;                  transition.getAttribute("event"))&lt;br /&gt;    assert stateevent not in stateevents, "FSM must be deterministic"&lt;br /&gt;    stateevents.append(stateevent)&lt;br /&gt;&lt;br /&gt;## CodeGeneration: get_toState&lt;br /&gt;## ~~~~~~~~~~~~~~~~~~~~~~~~~~~&lt;br /&gt;code = """&lt;br /&gt;char * get_toState(char *fromState, char *event) {&lt;br /&gt;"""&lt;br /&gt;for state in states:&lt;br /&gt;    for transition in transitions:&lt;br /&gt;        if transition.getAttribute("fromState") == state.getAttribute("name"):&lt;br /&gt;            code += """&lt;br /&gt;    if (strcmp("%s",fromState) == 0 &amp;&amp; strcmp("%s",event) == 0)&lt;br /&gt;        return "%s";&lt;br /&gt;            """ % (state.getAttribute("name"),&lt;br /&gt;                   transition.getAttribute("event"),&lt;br /&gt;                   transition.getAttribute("toState"))&lt;br /&gt;code += """&lt;br /&gt;    return "";&lt;br /&gt;} // end of function&lt;br /&gt;"""&lt;br /&gt;get_toState = code&lt;br /&gt;&lt;br /&gt;## CodeGeneration: do_action&lt;br /&gt;## ~~~~~~~~~~~~~~~~~~~~~~~~~&lt;br /&gt;code = """&lt;br /&gt;void do_action(char *fromState, char *event) {&lt;br /&gt;"""&lt;br /&gt;for state in states:&lt;br /&gt;    for transition in transitions:&lt;br /&gt;        if transition.getAttribute("fromState") == state.getAttribute("name"):&lt;br /&gt;            code += """&lt;br /&gt;    if (strcmp("%s",fromState) == 0 &amp;&amp; strcmp("%s",event) == 0) {&lt;br /&gt;        // ACTION CODE&lt;br /&gt;        %s&lt;br /&gt;        }&lt;br /&gt;            """ % (state.getAttribute("name"),&lt;br /&gt;                   transition.getAttribute("event"),&lt;br /&gt;                   transition.firstChild.data)&lt;br /&gt;code += """&lt;br /&gt;} // end of function&lt;br /&gt;"""           &lt;br /&gt;do_action = code            &lt;br /&gt;&lt;br /&gt;header = """/* THIS IS GENERATED CODE -- PLEASE DO NOT EDIT THIS FILE */&lt;br /&gt;/* CodeGeneration by %s, %s */&lt;br /&gt;#include &lt;string.h&gt;&lt;br /&gt;#include &lt;stdlib.h&gt;&lt;br /&gt;#include &lt;stdio.h&gt;&lt;br /&gt;&lt;br /&gt;""" % (sys.argv[0], time.ctime())&lt;br /&gt;&lt;br /&gt;print header + get_initState + get_finalState + get_toState + do_action&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Wenn Sie mögen, können Sie nun mit der Ergänzung um weitere Features beginnen. Wie wäre es mit hierachischen Zustandsmaschinen? Timer sind etwas sehr nützliches. Und wie wäre es mit nebenläufigen Zustandsmaschinen? Sehr leicht ist es, die Zustände um Aktionen zu bereichen. Ein Feature aus der UML sind Aktionen beim Eintritt (entry) und beim Verlassen (exit) eines Zustands. Transitionen kann man um Guards erweitern. Guards knüpfen das Ereignis an eine Bedingung, die zusätzlich erfüllt sein muss.&lt;br /&gt;&lt;br /&gt;Sie werden feststellen, dass es gar nicht so schwer ist, sich ein XML-Schema für sehr komplexe und mit allen Featuren ausgerüstete Zustandsmaschinen auszudenken und dazu einen Code-Generator zu entwickeln.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;(P.S.: Die an dieser Stelle zuvor berichteten Probleme mit dem Syntax-Highlighting haben sich gelöst. Allerdings scheint der Chrome-Browser Schwierigkeiten bei der Darstellung des letzten Code-Auszugs, dem Python-Code, zu haben. Strange! Kennt jemand einen Workaround?)&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-5070920527181686075?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/5070920527181686075/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=5070920527181686075' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5070920527181686075'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5070920527181686075'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2009/01/was-sind-das-fr-zustnde.html' title='Was sind das für Zustände?'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_XJMaba79IKU/SXTGvLghv6I/AAAAAAAAAHk/waGJyG1yVyg/s72-c/ZustandsmaschineRoboterarm.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-1897666785422117750</id><published>2009-01-16T13:12:00.002+01:00</published><updated>2009-01-16T13:27:00.040+01:00</updated><title type='text'>Nominiert für die Auslese08</title><content type='html'>Ich rechne es meiner treuen Leserschaft zu, zwei meiner Beiträge für die &lt;a href="http://www.wissenschafts-cafe.net/2009/01/longlist-nominierungen-fur-die-auslese-2008/"&gt;Auslese08 im Wissenschaftscafe&lt;/a&gt; nominiert zu haben. Vielen Dank dafür -- es freut mich natürlich sehr, zur Vorschlagsliste der 80 Blogbeiträge zu gehören. Wenngleich ich mir keine Hoffnungen mache, in die engere Auswahl zu kommen. Ich habe auf noch keiner Party die Stimmung hochgepeitscht mit einer Frage wie "&lt;a href="http://denkspuren.blogspot.com/2008/04/was-ist-ein-system.html"&gt;Was ist ein System?&lt;/a&gt;". Und Gedanken zu "&lt;a href="http://denkspuren.blogspot.com/2008/11/syntax-und-semantik.html"&gt;Syntax und Semantik&lt;/a&gt;" lassen auch nicht jedes Herz höher schlagen :-) Spaß macht es &lt;i&gt;mir&lt;/i&gt; dennoch, und es ist schön zu wissen, dass zumindest einige Leser solche Freuden mit mir teilen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-1897666785422117750?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/1897666785422117750/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=1897666785422117750' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1897666785422117750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1897666785422117750'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2009/01/nominiert-fr-die-auslese08.html' title='Nominiert für die Auslese08'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-6230451317311198806</id><published>2009-01-09T14:15:00.005+01:00</published><updated>2009-01-09T14:43:35.047+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fehler'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='float'/><title type='text'>Let it float!</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_XJMaba79IKU/SWdTkj86_lI/AAAAAAAAAHY/jLymRSBO5TI/s1600-h/rechnung-ausschnitt.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 180px;" src="http://2.bp.blogspot.com/_XJMaba79IKU/SWdTkj86_lI/AAAAAAAAAHY/jLymRSBO5TI/s400/rechnung-ausschnitt.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5289288174961098322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Minus 50 plus 50 macht Null -- in manchen Fällen muss man sich so ein Ergebnis &lt;a href="http://denkspuren.blogspot.com/2008/04/lidl-und-der-kassen-bug.html"&gt;autorisieren&lt;/a&gt; lassen. Plus 38.29 minus 38.29 macht auch Null und -- wenn man es nicht so genau nehmen will -- sogar &lt;b&gt;reich&lt;/b&gt;!&lt;br /&gt;&lt;br /&gt;Von diesem schönen und oben abgebildeten Fehler berichtet Michael Haupt auf seinem Blog in dem Beitrag "&lt;a href="http://haupz.blogspot.com/2009/01/ich-bin-reich.html"&gt;Ich bin reich!&lt;/a&gt;". Ein Fehler mit Pilgerwert. Ob ich irgendwann einmal diesen Zettel anfassen und in den Händen halten darf? Das sollte ich bei meinem nächsten Besuch in Potsdam tun!&lt;br /&gt;&lt;br /&gt;Herr Haupt wird genauso wie ich innigst hoffen, dass der Fehler von keinem unserer Studierenden "eingebaut" worden ist. Denn der Fehler ist fast so alt wie der erste Computer. Fließkommszahlen, floats, sollte man niemals auf Gleichheit überprüfen. Rundungsfehler können einem einen gewaltigen Strich durch die Rechnung machen (siehe oben). Finanzrechnungen sollte man stets genau rechnen, zum Beispiel in Cents und mit Integern und einem definierten Verhalten bei Rechnungen, die nicht in Cents sondern in gebrochenen Cents (z.B. bei einer Division) aufgehen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-6230451317311198806?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/6230451317311198806/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=6230451317311198806' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6230451317311198806'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6230451317311198806'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2009/01/let-it-float.html' title='Let it float!'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_XJMaba79IKU/SWdTkj86_lI/AAAAAAAAAHY/jLymRSBO5TI/s72-c/rechnung-ausschnitt.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-2864269237856167017</id><published>2008-12-14T00:44:00.000+01:00</published><updated>2008-12-14T00:45:19.600+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='buch'/><category scheme='http://www.blogger.com/atom/ns#' term='bücher'/><category scheme='http://www.blogger.com/atom/ns#' term='weihnachten'/><category scheme='http://www.blogger.com/atom/ns#' term='medina'/><category scheme='http://www.blogger.com/atom/ns#' term='waitzkin'/><title type='text'>Denken unter 150</title><content type='html'>184 Puls. Die Zone, in der ich nur noch renne. Kein Gedanke, kein denken -- nur kämpfen. Ich laufe gegen meinen Körper an. Längst bin ich im anaeroben Bereich. Ich kann nicht mehr soviel Sauerstoff in meine Lungen pumpen, wie ihn mein Körper benötigt. Ich spüre regelrecht, wie meine Zellen auf Hochtouren laufend die letzten Energien mobilisieren. Alles schmerzt. Warum tue ich mir diesen Berg eigentlich an? Gleich ist Schluss. Noch 23 Sekunden, die muss ich noch durchhalten, irgendwie.&lt;br /&gt;&lt;br /&gt;"Wie lautet die Binärzahl von 197?"&lt;br /&gt;&lt;br /&gt;Wie bitte? Die Aufgabe hämmert in meinem Kopf. Noch 18 Sekunden. Ich kann jetzt nicht rechnen. Ich schaue auf die Uhr. Noch 16 Sekunden den Körper durch die Qual treiben. Mein Puls fällt ab. Ich kann das Tempo nicht mehr halten. 197 ist kleiner als 256 und größer als 128. Mehr bekomme ich reflexartig nicht hin. Kämpfen steht im Vordergrund. Bei dem Puls kann ich keinen klaren Gedanken fassen. Wie auch? Ich versuche gerade meinen Körper zu bezwingen, das Limit noch für einen Moment aufrecht zu erhalten. Noch 6 Sekunden. Wie langsam die Zeit vergehen kann. Nicht aufgeben. Noch 4 Sekunden. Ja, gleich -- in meinem Kopf tobt der Wahnsinn. Ich kämpfe mit jedem Gedanken gegen all die Körpersignale an, die nicht mehr in 2 Sekunden, sondern sofort aufhören wollen. Da, 0 Sekunden. Erlösung.&lt;br /&gt;&lt;br /&gt;Stoppuhr an!&lt;br /&gt;&lt;br /&gt;Wie lange dauert es, bis ich einen "Denkpuls" erreicht habe? Bis sich mein Körper soweit von der Belastung erholt hat, dass mein Hirn wieder bereit für Input ist? Dass es bereit ist für eine Aufgabe? Dass es die Aufgabe lösen kann?&lt;br /&gt;&lt;br /&gt;Im Moment geht gar nichts. Ich atme tief und heftig. Spucke auf den Asphalt. Luft. Luft. Ich will nur atmen. In meinen Ohren, überall hämmert der Puls. Aber er fällt. Jetzt ist er unter 176. Denken? Nein. Geht nicht. Ich gehe. Die Schmerzen lassen nach. Der ganze Körper lechzt nach Erholung.&lt;br /&gt;&lt;br /&gt;Ab welchem Puls kann ich die Aufgabe lösen? Wie lautet die Binärzahl von 197?&lt;br /&gt;&lt;br /&gt;Erste Denkreflexe melden sich. 197 ist größer als 128, hatten wir schon, also haben wir "ganz links" eine 1. Ungerade Zahl, also "ganz rechts" eine 1. Sonst? Achja, 8 Bits reichen.&lt;br /&gt;&lt;br /&gt;Mehr geht nicht. Mein Puls fällt. So langsam regelt sich die Atmung wieder ein. 160 Puls. Erste Gedanken raten mir zu einem systematischen Vorgehen. Nächste Bitstelle? 64. Was ergibt 128 plus 64. Es fühlt sich nach weniger als 197 an. Wieviel weniger? Eine einfache Addition. Im Kopf -- derzeit unmöglich. Ich brauche noch etwas Pause.&lt;br /&gt;&lt;br /&gt;Ich wage einen neuen Versuch. Puls knapp über 150. 128 plus 64 macht etwas mehr als 180, fehlen noch 8 plus 4, also 12. 192, das könnte sein. Ich habe noch kein Vertrauen in meine Denke. Vieles ist mechanisch abgeleitet. Eine echte Kontrolle im Hirn fehlt. Dafür bin ich noch zu sehr aus der Puste.&lt;br /&gt;&lt;br /&gt;Ich spekuliere weiter. 128 plus 64 macht 192. Die 197 war gegeben, bleiben 5 übrig. Eine 1 hatte ich schon für das Ungerade-sein spendiert. Bleiben noch 4 übrig. Ok. Bitmuster "ganz rechts" 101, Bitmuster "ganz link" 11. Ich komme etwas zur Ruhe. Bin kurz vor 140 Puls. Jetzt weiß ich's. Ich habe fünf Bitstellen berechnet, noch drei weitere Bitstellen mit Null fehlen. Ergebnis: 11000101. Uff.&lt;br /&gt;&lt;br /&gt;Hätte ich mir eine ernstere Aufgabe gestellt, ich bin mir sicher, erst in einem Bereich von 120 bis 130 Puls wäre eine Problemlösung möglich, mit ersten sinnvollen Gedanken um die 140 abwärts.&lt;br /&gt;&lt;br /&gt;Angeregt zu diesem (virtuellen) Experiment hat mich das Buch von &lt;a href="http://www.joshwaitzkin.com"&gt;Josh Waitzkin&lt;/a&gt;: The Art of Learning -- An Inner Journey to Optimal Performance, Free Press, 2007. Er beschreibt in diesem Buch seine Lernerfahrungen als junges Schachgenie und später als Kampfsportler. In beiden Disziplinen ist bzw. war er sehr erfolgreich. Wem weder das Schachspiel noch der Kampfsport fremd sind, der wir seine Freude an diesem Buch haben und es vielleicht genauso wie ich verschlingen. Denn faszinierend sind seine Berichte und Einsichten schon, praktisch und anwendbar sind sie auch. So berichtet er unter anderem davon, wie wichtig der Zusammenhang zwischen körperlicher Fitness und der Fähigkeit zu sehr kurzer geistiger Erholung ist -- um Hochleistungen erbringen zu können, geistige ebenso wie sportliche. Es ist auch ein Weg, um bessere Klausuren schreiben und Prüfungen ablegen zu können.&lt;br /&gt;&lt;br /&gt;Das ist die eine Buchempfehlung, die ich zu Weihnachten für Sie habe. Die andere ist ein Buch von &lt;a href="http://www.johnmedina.com"&gt;John Medina&lt;/a&gt;: Brain Rules -- 12 Principles for Surviving and Thriving at Work, Home, and School, Pear Press, 2008. Und da erfahren wir, dass schon ein wenig körperliche Ertüchtigung die geistige Performanz boostet. Das ist Regel Nr. 1. Weitere elf Regeln verraten Ihnen noch mehr darüber, wie unser Gehirn tickert und wie wir gut mit ihm umgehen können. Selbst wenn Sie sich für das Buch nicht weiter interessieren, besuchen Sie die &lt;a href="http://www.brainrules.net"&gt;Webseite zu den Brain Rules&lt;/a&gt; -- es lohnt sich.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-2864269237856167017?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/2864269237856167017/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=2864269237856167017' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2864269237856167017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2864269237856167017'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/12/denken-unter-150.html' title='Denken unter 150'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-55964307311993839</id><published>2008-11-17T22:37:00.001+01:00</published><updated>2008-11-18T17:27:42.231+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Semantik'/><category scheme='http://www.blogger.com/atom/ns#' term='Chomsky-Hierarchie'/><category scheme='http://www.blogger.com/atom/ns#' term='Syntax'/><category scheme='http://www.blogger.com/atom/ns#' term='formale Sprachen'/><category scheme='http://www.blogger.com/atom/ns#' term='Grammatik'/><title type='text'>Syntax und Semantik</title><content type='html'>Was ist Syntax, was ist Semantik? Diese zwei Begriffe beschäftigen mich immer wieder, siehe zum Beispiel auch "&lt;a href="http://denkspuren.blogspot.com/2007/02/uniform-syntax.html"&gt;Uniform Syntax&lt;/a&gt;" (23. Feb. 2007). Beide Begriffe spielen eine entscheidende Rolle bei jeder Art von maschinell-verarbeitbarer Sprache. Vom Dritten im Bunde, der Pragmatik, will ich an dieser Stelle ganz absehen. &lt;br /&gt;&lt;br /&gt;Die &lt;em&gt;Syntax&lt;/em&gt; bezieht sich auf die Form und die Struktur von Zeichen in einer Sprache, ohne auf die Bedeutung der verwendeten Zeichen in den Formen und Strukturen einzugehen. Syntaktisch korrekte Ausdrücke werden auch als "wohlgeformt" (&lt;em&gt;well-formed&lt;/em&gt;) bezeichnet.&lt;br /&gt;&lt;br /&gt;Die &lt;em&gt;Semantik&lt;/em&gt; befasst sich mit der Bedeutung syntaktisch korrekter Zeichenfolgen einer Sprache. Im Zusammenhang mit Programmiersprachen bedeutet Semantik die Beschreibung des Verhaltens, das mit einer Interpretation (Auslegung) eines syntaktisch korrekten Ausdrucks verbunden ist.&lt;br /&gt;&lt;br /&gt;[Die obigen Begriffserläuterungen sind angelehnt an das Buch von Kenneth Slonneger und Barry L. Kurtz: &lt;a href="http://www.cs.uiowa.edu/~slonnegr/plf/Book/"&gt;Formal Syntax and Semantics of Programming Languages -- A Laboratory Based Approach&lt;/a&gt;, Addison-Wesley, 1995, &lt;a href="http://www.cs.uiowa.edu/~slonnegr/plf/Book/Chapter1.pdf"&gt;Kapitel 1&lt;/a&gt;.]&lt;br /&gt;&lt;br /&gt;Die Grenze zwischen Syntax und Semantik ist fließend und lässt sich schön am Beispiel mit Hilfe regulärer Ausdrücke erläutern. Spezifizieren wir eine Syntax für die Angabe der Uhrzeit. Gemeint sind minutengenaue Zeitangaben im 24-Stunden-Format.&lt;br /&gt;&lt;br /&gt;Ein einfacher regulärer Ausdruck beschreibt die Syntax sehr direkt: "\d\d:\d\d" --  dieser Ausdruck kam schon in der Einführung "&lt;a href="http://denkspuren.blogspot.com/2008/10/regulre-ausdrcke.html"&gt;Reguläre Ausdrücke&lt;/a&gt;" zur Anwendung und ist dort ausführlich beschrieben. Dieser reguläre Ausdruck ist zu allgemein, denn die Angabe "14:72" wäre genauso möglich wie "25:13". Das sind keine Uhrzeitangaben. Ein regulärer Ausdruck, der nur gültige, 4-stellige Zeitangaben erlaubt, ist "([01]\d)|(2[0-3]):[0-5]\d".&lt;br /&gt;&lt;br /&gt;Worauf es mir hier ankommt, ist Folgendes: Der erste reguläre Ausdruck spezifiziert eine Uhrzeitsyntax, die so allgemein gefasst ist, dass eine Nachverarbeitung (Teil der Semantik(!)) prüfen muss, ob die Kombination von Stunden und Minutenangaben eine gültige Uhrzeit ist. Der zweite reguläre Ausdruck hingegen erfasst gültige, vierstellige Uhrzeitangaben vollständig syntaktisch. Jegliche Weiterverarbeitung, sprich jegliche Semantik kann sich darauf verlassen, mit ausschließlich gültigen Uhrzeitangaben zu arbeiten.&lt;br /&gt;&lt;br /&gt;Wir beobachten an diesem Beispiel, dass es einen Spielraum gibt, was Syntax und was Semantik in einer Sprache ist. Je allgemeiner die Syntax, desto mehr Form- und Strukturwissen muss als Teil der Semantik behandelt werden. Je spezifischer die Syntax ist, desto weniger muss sich die Semantik um eine Erkennung bemühen. Im Idealfall ist die Semantik von aller Klärung befreit, wenn die Syntax eindeutig ist. &lt;br /&gt;&lt;br /&gt;Im Fall der Uhrzeit ist es relativ leicht möglich, Uhrzeitangaben vollständig syntaktisch zu spezifizieren. Das geht nicht immer. Nehmen wir Datumsangaben. Eine vollständige syntaktische Spezifikation, welche Monate 30 bzw. 31 Tage haben, ist noch machbar -- ob sie sinnvoll ist, ist die Frage. Denn spätestens für den Monat Februar ist mit regulären Ausdrücken nicht mehr entscheidbar, ob 28 oder 29 Tage die korrekte Angabe sind. Es sind 29 Tage, sofern das Jahr ein Schaltjahr, also durch 4 teilbar ist. Es bleibt jedoch bei 28 Tagen, wenn die Jahreszahl durch 100 teilbar ist, nicht jedoch durch 400. Eine Datumsangabe kann nicht vollständig syntaktisch erkannt werden -- es sei denn, die Syntax hätte Rechenfähigkeiten.&lt;br /&gt;&lt;br /&gt;Und damit sind wir genau an dem Punkt angelangt, was Syntax von Semantik unterscheidet: Syntax ist der Anteil einer Sprachdefinition, der gültige Zeichenfolgen einer Sprache erkennt (Form- und Strukturerkennung) und zwar mit einem Formalismus, der &lt;em&gt;keine&lt;/em&gt; Rechenfähigkeit hat, sprich, der &lt;em&gt;nicht&lt;/em&gt; Turing-äquivalent ist. Dieser syntaktische Anteil liefert die Vorverarbeitung. (In der Theorie der formalen Sprachen sind damit reguläre (Typ-3) bzw. kontextfreie (Typ-2) Grammatiken gemeint, siehe &lt;a href="http://de.wikipedia.org/wiki/Chomsky-Hierarchie"&gt;Chomsky-Hierarchie&lt;/a&gt;.). Die Semantik betrifft alle weitere Symbol-Verarbeitung, die mit einem Formalismus beschrieben ist, der Turing-äquivalent ist.&lt;br /&gt;&lt;br /&gt;Mit diesem Verständnis von Syntax und Semantik kann man sinnvoll den Begriff der syntaktischen Obergrenze definieren: Die syntaktische Obergrenze reizt die Form- und Strukturerkennung aus und minimiert den semantischen Anteil, der eventuell notwendig ist, um die Erkennung von Formen und Strukturen eindeutig zu machen. Zum Beispiel beschreibt ein regulärer Ausdruck die syntaktische Obergrenze für eine Datumsangabe im Format "Tag-Monat-Jahr" (TT-MM-JJJJ), wenn semantisch einzig die Tagesangabe für den Februar überprüft werden muss. Das Muster "\d\d-\d\d-\d\d\d\d" liegt offensichtlich nicht an der syntaktischen Obergrenze. Der Semantik-Anteil muss umfangreiche Gültigkeitsprüfungen vornehmen.&lt;br /&gt;&lt;br /&gt;Man kann in diesem konkreten Beispiel auch auf einen Formalismus für die Syntax zurückgreifen, der zwar Rechenfähigkeiten hat, in seinem Verarbeitungshorizont jedoch strikt begrenzt ist. Dann liegt eine kontextsensitive Grammatik vor (Typ-1). Kontextsensitive Grammatiken sind eher die Ausnahme. (Anmerkung: Grundsätzlich ist auch ein Formalismus für die Syntax denkbar, der Turing-äquivalent ist (Typ-0), allerdings fällt dann die Grenzziehung zwischen Syntax und Semantik schwer. Ein anderes Kriterium muss dann gefunden werden.)&lt;br /&gt;&lt;br /&gt;Meine These ist, dass diese Zerlegung einer Verarbeitung in einen Anteil, der aus einem nicht Turing-äquivalenten Mechanismus und einem Turing-äquivalenten Mechanismus besteht, ein stets wiederkehrendes Thema in der Informatik ist. Pipe-Filter-Architekturen sind ein Beispiel, die Zerlegung eines Programms in Interfaces und Verhalten ein anderes. Interessanterweise habe ich bislang keinen Hinweis darauf gefunden, dass dieses Zerlegungsmuster bereits von jemand anderem postuliert worden wäre. Ich glaube, man könnte dieses Zerlegungsmuster sehr viel systematischer in der Software-Entwicklung einsetzen.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;Ein Anmerkung, siehe im vorletzten Absatz, ist hinzu gekommen, um die Diskussion etwas abzurunden. (2008-11-18)&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-55964307311993839?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/55964307311993839/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=55964307311993839' title='4 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/55964307311993839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/55964307311993839'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/11/syntax-und-semantik.html' title='Syntax und Semantik'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-2955487512534308585</id><published>2008-11-04T01:36:00.000+01:00</published><updated>2008-11-04T01:36:48.695+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Hochschule Heilbronn'/><category scheme='http://www.blogger.com/atom/ns#' term='cell'/><title type='text'>Studieren mit der PS3</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_XJMaba79IKU/SQ-YaNm5EaI/AAAAAAAAAFY/2mHDnCFX6jw/s1600-h/StudierenMitDerPS3.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 156px;" src="http://3.bp.blogspot.com/_XJMaba79IKU/SQ-YaNm5EaI/AAAAAAAAAFY/2mHDnCFX6jw/s400/StudierenMitDerPS3.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5264594065516204450" /&gt;&lt;/a&gt;&lt;br /&gt;Ungefähr 1000 PS3-Spielkonsolen dürften in etwa der Rechenleistung unseres Gehirns gleichkommen. Vielleicht ist das eine gewagte Schätzung, so ganz seriös sind solche Computer/Hirn-Vergleiche nie. Aber wer als "Niko" Bellic in die Welt von GTA IV eintaucht, dem wird diese Zahl vermutlich gar nicht so abwegig vorkommen. Es ist unglaublich, wieviel Welt so eine Spielkonsole simulieren kann. &lt;br /&gt;&lt;br /&gt;In der PS3 leistet ein Spezialprozessor, der Cell-Chip, diese beachtliche Arbeit. Ein etwa 10 Jahre altes Rechenzentrum im Schachtelformat. Mehrere Einheiten arbeiten parallel und fressen Zahlen, was das Zeug hält. &lt;br /&gt;&lt;br /&gt;Es hat eine ganz eigene Faszination, wenn man Linux auf die PS3 installiert und sich die Konsole zum ersten Mal meldet. Man hat Kontakt mit dieser geballten Rechenkraft aufgenommen. Plötzlich gehorcht sie einem aufs Wort. Und irgendwie hört man die Maschine nach Arbeit rufen. Das bisschen Linux, die paar Befehle, die über die Konsole reinwandern, die machen so ein Maschinchen nicht müde. Da steht ein Apparat, der es gewohnt ist, Sie durch Häuserschluchten zu jagen, Ihnen Aliens aufzuhetzen, Sie unter Beschuss zu nehmen und Ihnen wilde Verfolgungsjagden zu liefern. Diese Maschine hat Hunger! Diese Maschine sucht die Herausforderung und die Auseinandersetzung!&lt;br /&gt;&lt;br /&gt;Nehmen Sie die Herausforderung an?&lt;br /&gt;&lt;br /&gt;Geben Sie der Maschine Futter, programmieren Sie die PS3 selbst! Jagen Sie die PS3 mit Ihren Programmen an den Rand des Machbaren! Fangen Sie da an, wo der PC schlapp macht!&lt;br /&gt;&lt;br /&gt;Einen Start bietet Ihnen unsere Webseite &lt;a href="http://ps3.hs-heilbronn.de"&gt;http://ps3.hs-heilbronn.de&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-2955487512534308585?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/2955487512534308585/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=2955487512534308585' title='3 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2955487512534308585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2955487512534308585'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/11/studieren-mit-der-ps3.html' title='Studieren mit der PS3'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_XJMaba79IKU/SQ-YaNm5EaI/AAAAAAAAAFY/2mHDnCFX6jw/s72-c/StudierenMitDerPS3.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-3448867249901574379</id><published>2008-10-27T10:53:00.001+01:00</published><updated>2008-10-27T11:44:53.364+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Diplomarbeit'/><category scheme='http://www.blogger.com/atom/ns#' term='schreibbar'/><category scheme='http://www.blogger.com/atom/ns#' term='Master Thesis'/><category scheme='http://www.blogger.com/atom/ns#' term='Studienarbeit'/><category scheme='http://www.blogger.com/atom/ns#' term='Bachelor Thesis'/><category scheme='http://www.blogger.com/atom/ns#' term='wissenschaftliche Abschlussarbeit'/><title type='text'>Einladung in die Schreibbar</title><content type='html'>Daran kommt keine Studentin und kein Student vorbei: am Verfassen einer wissenschaftlichen Arbeit. Früher gab es (in den technisch orientierten Fächern) die Studien- und die Diplomarbeit, jetzt ist eine Bachelor oder Master Thesis zu schreiben. Seinerzeit hatte man die Chance, sich mit der Studienarbeit auf die Diplomarbeit vorzubereiten. Die Studienarbeit war so etwas wie eine Fahrschule zum wissenschaftliche Arbeiten und Schreiben. Jetzt geht es mit der Bachelor oder Master Thesis relativ unvorbereitet auf die Wissenschaftspiste. Plötzlich muss man alles beherrschen: das Zitieren, das Referenzieren, das Gliedern, Schreiben, Bewerten, Recherchieren etc. Es macht es nicht einfacher, dass man für eine Bachelor Thesis nicht gerade viel Zeit hat.&lt;br /&gt;&lt;br /&gt;In der &lt;a href="http://schreibbar.wordpress.com/"&gt;Schreibbar&lt;/a&gt;, "da werden Sie geholfen"! Die &lt;a href="http://schreibbar.wordpress.com/"&gt;Schreibbar&lt;/a&gt; möchte das erste deutschsprachige Blog sein, das das wissenschaftliche Arbeiten zum Thema hat und Studierenden dabei Hilfestellung und Anleitung bietet. Die &lt;a href="http://schreibbar.wordpress.com/"&gt;Schreibbar&lt;/a&gt; hat einen gewissen Fokus auf technisch-orientierte Fächer, aber sie wird in ihrem Themenspektrum sicher vielen Studierenden eine Hilfe sein.&lt;br /&gt;&lt;br /&gt;Schauen Sie doch einfach mal vorbei. Meine Mitstreiterinnen und ich, wir würden uns auf Ihren Besuch freuen.&lt;br /&gt;&lt;br /&gt;Link: &lt;a href="http://schreibbar.wordpress.com/"&gt;schreibbar.wordpress.com&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-3448867249901574379?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/3448867249901574379/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=3448867249901574379' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3448867249901574379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3448867249901574379'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/10/einladung-in-die-schreibbar.html' title='Einladung in die Schreibbar'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-3350745373598524086</id><published>2008-10-20T11:46:00.001+02:00</published><updated>2008-10-20T12:26:04.947+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RegEx'/><category scheme='http://www.blogger.com/atom/ns#' term='reguläre Ausdrücke'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='RegExp'/><title type='text'>Reguläre Ausdrücke</title><content type='html'>Eine typische Aufgabenstellung, mit der sich ein Software-Entwickler bzw. eine Software-Entwicklerin immer wieder konfrontiert sieht, ist die Verarbeitung von Textdateien. In der Regel interessiert die Verarbeitung von Textdateien oder Zeichenströmen, die von Maschinen für Maschinen gedacht sind. Solche Textdateien folgen klaren, eindeutigen Regeln des Aufbaus. Sonst ist die maschinelle Verarbeitung eher schwierig bis unmöglich.&lt;br /&gt;&lt;br /&gt;Bei der Verarbeitung von Textdateien bzw. Zeichenströmen kommt man an regulären Ausdrücken (&lt;em&gt;regular expressions&lt;/em&gt;) nicht vorbei. Mit ihnen kann man Zeichenfolgen in einem Text suchen und weiter verarbeiten. Reguläre Ausdrücke stehen in praktisch jeder Programmiersprache als nachladbare Bibliothek zur Verfügung (so z.B. in Java) oder sie sind bereits fester Bestandteil der Sprache (wie z.B. in Perl oder JavaScript). Jeder moderne Texteditor erlaubt die Suche nach Zeichenketten mit Hilfe von regulären Ausdrücken.&lt;br /&gt;&lt;br /&gt;Reguläre Ausdrücke selbst sind Zeichenketten (&lt;em&gt;strings&lt;/em&gt;). Die in dem String verwendeten Zeichen folgen bestimmten Vereinbarungen (Konventionen). Zum Beispiel steht die Zeichenfolge "\d" in einem regulären Ausdruck nicht für die Folge der Zeichen "\" und "d". Der Backslash "\" ist ein sogenanntes &lt;em&gt;escape symbol&lt;/em&gt;. Die normale Bedeutung des Zeichens "\" als Backslash wird ausgehebelt. Zusammen mit dem "d" bekommt es eine Sonderfunktion. Die Zeichen "\d" stehen für eine beliebige Ziffer (&lt;em&gt;digit&lt;/em&gt;) von 0 bis 9. Gleichwertig dazu ist der reguläre Ausdruck "[0-9]". In der Tat ist "\d" nicht mehr als eine Kurzform für "[0-9]". Die eckigen Klammer haben ebenso wie der Backslash eine Sonderbedeutung. Die zwischen den eckigen Klammern gelisteten Zeichen stellen Alternativen dar. Ein "[012]" steht entweder für eine "0" oder eine "1" oder eine "2". Ein Digit ist also ein "[0123456789]". Die von/bis-Notation "[0-9]" verkürzt den Schreibaufwand.&lt;br /&gt;&lt;br /&gt;Und was ist, wenn man die Sonderbedeutung von "\", "[" bzw. "]" aufheben möchte? Dann kommt wieder das Escape-Zeichen, der Backslash, zum Einsatz. Ein "\\" meint genau das Zeichen "\". Und ein "\[" bzw. "\]" schaltet die Sonderbedeutung der eckigen Klammern aus und meint nun ausdrücklich die Zeichen "[" und "]".&lt;br /&gt;&lt;br /&gt;Nachfolgende ist eine kurze Einführung in die Arbeit mit regulären Ausdrücken in der Programmiersprache Python gegeben. Diese Einführung ist weder vollständig noch umfassend. Ziel ist, Ihnen die Einstiegshürde zu nehmen.&lt;br /&gt;&lt;br /&gt;In Python werden reguläre Ausdrücke über eine Bibliothek (ein Modul) zur Verfügung gestellt.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; import re&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Ist die Suche nach einem Muster erfolgreich, liefert das re-Modul ein "Muster erkannt"-Objekt zurück. Schlägt die Suche fehl, wird None als Wert ausgeliefert.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; re.search("ll","hello")&lt;br /&gt;&lt;_sre.SRE_Match object at 0x00B8DBB8&gt;&lt;br /&gt;&gt;&gt;&gt; re.search("ll","hexxo")&lt;br /&gt;&gt;&gt;&gt; re.search("ll","hexxo") == None&lt;br /&gt;True&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Neben der search-Methode steht auch eine match-Methode zur Verfügung. Ein Match erwartet im Gegensatz zum Search eine Passung des regulären Ausdrucks mit dem Anfang des übergebenen Strings. Bei Search wird im gesamten String nach dem Muster gefahndet.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; re.search("ll","hello")&lt;br /&gt;&lt;_sre.SRE_Match object at 0x00B8DB80&gt;&lt;br /&gt;&gt;&gt;&gt; re.match("ll","hello")&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Zur effizienten Verarbeitung können reguläre Ausdrücke intern compiliert werden. Das macht vor allem dann Sinn, wenn ein Muster mehrfach zum Einsatz kommt.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; hhmmRE = re.compile("\d\d:\d\d")&lt;br /&gt;&gt;&gt;&gt; hhmmRE&lt;br /&gt;&lt;_sre.SRE_Pattern object at 0x00B24870&gt;&lt;br /&gt;&gt;&gt;&gt; hhmm = hhmmRE.search("It's 14:00!")&lt;br /&gt;&gt;&gt;&gt; hhmm&lt;br /&gt;&lt;_sre.SRE_Match object at 0x00B8DC28&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Match-Objekte bieten eine Reihe von Methoden an. Man kann z.B. den zum Muster passenden String erfragen oder sich die Position des Muster-Treffers im String angeben lassen.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; hhmm.group()&lt;br /&gt;'14:00'&lt;br /&gt;&gt;&gt;&gt; hhmm.start()&lt;br /&gt;5&lt;br /&gt;&gt;&gt;&gt; hhmm.end()&lt;br /&gt;10&lt;br /&gt;&gt;&gt;&gt; hhmm.string&lt;br /&gt;"It's 14:00!"&lt;br /&gt;&gt;&gt;&gt; hhmm.string[hhmm.start():hhmm.end()]&lt;br /&gt;'14:00'&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Teile eines regulären Ausdrucks können in Gruppen strukturiert werden. Auf die einzelnen Teile kann dann über das Match-Objekt zugegriffen werden. Angenommen, wir wollen die Stunden und die Minuten einer Uhrzeitangabe separat erfassen. Runde Klammern in einem regulären Ausdruck markieren Gruppen, die von 1 an aufsteigend durchgezählt werden.&lt;br /&gt;&lt;br /&gt;Zusätzlich verbessern wir unser Suchmuster dahingehend, dass auch Uhrzeiten mit einstelliger Stundenangabe (z.B. 7:00 Uhr) erkannt werden. Ein Fragezeichen markiert als Sondersymbol die Optionalität des voranstehenden Zeichens. Ein "\d?" steht für einen Digit, der optional ist.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; hhmmRE = re.compile("(\d?\d):(\d\d)")&lt;br /&gt;&gt;&gt;&gt; hhmm = hhmmRE.search("Let's meet at 2:00 pm.")&lt;br /&gt;&gt;&gt;&gt; hhmm&lt;br /&gt;&lt;_sre.SRE_Match object at 0x00B97578&gt;&lt;br /&gt;&gt;&gt;&gt; hhmm.group(1)&lt;br /&gt;'2'&lt;br /&gt;&gt;&gt;&gt; hhmm.group(2)&lt;br /&gt;'00'&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Gruppen können auch mit sprechenden Namen assoziiert werden, was aus software-technischer Sicht zu empfehlen ist. Beim Durchzählen von Gruppen kann sich ein Programmierer oder eine Programmiererin leicht verzählen. Referenzbezüge mit sprechenden Namen sind weniger fehleranfällig.&lt;br /&gt;&lt;br /&gt;Eine benamte Gruppe wird mit "(?P&amp;lt;name&amp;gt;...)" markiert.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; hhmmRE = re.compile("(?P&amp;lt;hh&amp;gt;\d?\d):(?P&amp;lt;mm&amp;gt;\d\d)")&lt;br /&gt;&gt;&gt;&gt; hhmm = hhmmRE.search("Let's meet at 13:45.")&lt;br /&gt;&gt;&gt;&gt; hhmm.group("hh")&lt;br /&gt;'13'&lt;br /&gt;&gt;&gt;&gt; hhmm.group("mm")&lt;br /&gt;'45'&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Soweit der Einstieg mit Python. Es gibt noch eine Menge zu regulären Ausdrücken zu entdecken. Sie sind ein leistungsfähiges Werkzeug bei der Verarbeitung von Strings.&lt;br /&gt;&lt;br /&gt;Es lohnt nicht unbedingt, sich ein Buch zu regulären Ausdrücken zuzulegen, auch wenn es zu diesem Thema exzellente Werke gibt. Einen raschen Überblick zur Historie und zum theoretischen Hintergrund liefern Ihnen beispielsweise der &lt;a href="http://de.wikipedia.org/wiki/Regulärer_Ausdruck"&gt;deutsche&lt;/a&gt; und der &lt;a href="http://en.wikipedia.org/wiki/Regular_expression"&gt;englische&lt;/a&gt; Wikipedia-Eintrag. Dort finden Sie auch etliche hilfreiche Weblinks. Im "Tagesgeschäft" sollte die Dokumentation zu den regulären Ausdrücken in der von Ihnen verwendeten Programmiersprache vollends ausreichen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-3350745373598524086?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/3350745373598524086/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=3350745373598524086' title='6 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3350745373598524086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3350745373598524086'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/10/regulre-ausdrcke.html' title='Reguläre Ausdrücke'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-2073708850294292404</id><published>2008-09-27T10:24:00.006+02:00</published><updated>2008-09-27T10:47:04.117+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='funktionale Programmierung'/><category scheme='http://www.blogger.com/atom/ns#' term='Lambda Calculus'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Zuweisung, Verzögerung, Rekursion - alles Lambda, oder was?!</title><content type='html'>Es mag Spaß machen, einigermaßen komplexe Programme in eine einzige, unleserliche Zeile zu stopfen. In der Programmiersprache Perl sind die "one-liners" ja beinahe Kult.&lt;br /&gt;&lt;br /&gt;Von geradezu didaktischem Wert ist die Konstruktion von Einzeilern für Python von Dan Piponi. Bei ihm lernt man, was die Mächtigkeit von Lambda-Ausdrücken ausmacht. Zuweisung, Verzögerung, Rekursion -- das alles kann man leicht mit Lambdas ausdrücken. Mit ihrer Hilfe kann man sich beliebige Einzeiler basteln, siehe "&lt;a href="http://sigfpe.blogspot.com/2008/09/on-writing-python-one-liners.html"&gt;On writing Python one-liners&lt;/a&gt;".&lt;br /&gt;&lt;br /&gt;Nicht, dass ich Sie zu Einzeilern ermutigen möchte. Aber Lambda-Ausdrücke sollte jeder Programmierer kennen. Sie sind &lt;em&gt;die&lt;/em&gt; Wunderwaffe der funktionalen Programmierer!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-2073708850294292404?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/2073708850294292404/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=2073708850294292404' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2073708850294292404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2073708850294292404'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/09/zuweisung-verzgerung-rekursion-alles.html' title='Zuweisung, Verzögerung, Rekursion - alles Lambda, oder was?!'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-6331135678942713365</id><published>2008-09-23T11:27:00.001+02:00</published><updated>2008-09-23T11:28:16.073+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Parser'/><category scheme='http://www.blogger.com/atom/ns#' term='Parser Combinator'/><category scheme='http://www.blogger.com/atom/ns#' term='EBNF'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='Parsing'/><category scheme='http://www.blogger.com/atom/ns#' term='LaTeX'/><category scheme='http://www.blogger.com/atom/ns#' term='Grammatik'/><category scheme='http://www.blogger.com/atom/ns#' term='Parser-Kombinator'/><title type='text'>Objekt-orientierte Parser-Kombinatoren in Python</title><content type='html'>Ich möchte Ihnen eine Technik zur Syntaxanalyse vorstellen, die zwar gar nicht so neu ist, aber immer wieder Aufmerksamkeit erregt. Zum Beispiel in der Smalltalk-Gemeinde durch einen Beitrag von &lt;a href="http://bracha.org"&gt;Gilad Bracha&lt;/a&gt; zu &lt;a href="http://newspeaklanguage.org"&gt;Newspeak&lt;/a&gt; ("&lt;a href="http://bracha.org/executableGrammars.pdf"&gt;Executable Grammars in Newspeak&lt;/a&gt;"). In der Haskell-Welt machen Parser-Kombinatoren und die Forschung zu ihnen immer wieder von sich reden, siehe z.B. aktuell "&lt;a href="http://cs.uwindsor.ca/~hafiz/PADL_PAPER_FINAL.pdf"&gt;Parser Combinators for Ambiguous Left-Recursive Grammars&lt;/a&gt;" von R.A. Frost, R. Hafiz und P. Callaghan, &lt;a href="http://www.ist.unomaha.edu/padl2008/"&gt;PADL 2008&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Im Folgenden setze ich voraus, dass Sie wissen, was ein &lt;a href="http://de.wikipedia.org/wiki/Parsing"&gt;Parser&lt;/a&gt; ist und Ihnen auch die &lt;a href="http://de.wikipedia.org/wiki/Erweiterte_Backus-Naur-Form"&gt;EBNF&lt;/a&gt; zur Darstellung von Grammatiken bekannt ist. Wenn wir weiter unten von einer Parser-Funktion reden, dann meinen wir eine Funktion, die einen String entgegennimmt, diesen parst und ein geeignetes Ergebnis der Parse-Analyse zurückgibt.&lt;br /&gt;&lt;br /&gt;Der Begriff des Kombinators kommt aus der Ecke der funktionalen Programmiersprachen. Ein Kombinator ist eine Funktion höherer Ordnung, eine Higher-Order Function (HOF), die selbst eine Funktion zurückgibt. Eine HOF ist eine Funktion, die Funktionen als Argumente entgegennimmt und gegebenenfalls eine Funktion zurückgibt. Von einem Kombinator wird dann gesprochen, wenn die HOF syntaktisch als Infix notiert werden kann. Anschaulich: Statt der bei Funktionen verbreiteten Prefix-Notation &lt;code&gt;combinatorX(functionA,functionB)&lt;/code&gt; steht in der Infix-Notation der Kombinator in der Mitte: &lt;code&gt;functionA combinatorX functionB&lt;/code&gt;. Damit wird hervorgehoben, dass der Kombinator, ähnlich einem Operator wie etwa "+", zwei Funktionen "kombiniert".&lt;br /&gt;&lt;br /&gt;Ein Parser-Kombinator verknüpft Parser-Funktionen und liefert selber eine Parser-Funktion zurück. Nehmen wir an, wir haben eine Parser-Funktion &lt;code&gt;token()&lt;/code&gt;, die Token erkennt. Angenommen, der Parser-Kombinator für Sequenzen oder Folgen von Parser-Funktionen kann mit einem Komma "," notiert werden. So lässt sich dann sehr kompakt ein Parser ausdrücken, der zwei Token-Parser als Sequenz kombiniert: &lt;code&gt;token("Hell"),token("o")&lt;/code&gt;. Mit dieser Schreibweise kann die Struktur einer EBNF-Beschreibung einer Grammatik direkt als Kombination von Parser-Funktionen ausgedrückt werden. Die Funktionen bilden die Struktur einer EBNF-Beschreibung nach ("&lt;em&gt;function follows form&lt;/em&gt;").&lt;br /&gt;&lt;br /&gt;Da der Parser-Kombinator selber wieder ein Parser ist, können wir ihn mit einem String aufrufen: &lt;code&gt;(token("Gut"),token("en"))("Guten Tag!")&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In vielen Programmiersprachen ist es nicht so ohne weiteres möglich, die Syntax zur Schreibweise von Funktionen zu ändern. Eine Infix-Notation verbietet sich meist. So bleibt einem nur, Parser-Kombinatoren in der nicht ganz so eleganten Prefix-Notation zu nutzen. Ein sehr schönes Beispiel, wie man mit Python Parser-Kombinatoren bauen kann, liefert ein Autor namens "Stefan" (Kürzel "sma") im deutschen Python-Forum in dem Beitrag "&lt;a href="http://www.python-forum.de/topic-13554.html?sid=bf474f4b57e49fa617023529a8187d16"&gt;Kleine Parser-Kombinator-Bibliothek&lt;/a&gt;" (16. Feb. 2008, 16:31). Wenn Sie diesen Beitrag lesen, werden Sie das Folgende besser verstehen.&lt;br /&gt;&lt;br /&gt;Will man einen Parser-Kombinator konsequent objekt-orientiert anlegen, dann wird die Idee der Kombination von Parser-Funktionen abgelöst durch eine Kombination von Parser-Objekten, die wieder ein Parser-Objekt statt einer Parser-Funktion liefern. Die Kombination von Objekten, die wieder ein Objekt zurückliefern ist sehr elegant und einfach realisierbar durch Konstruktor-Methoden.&lt;br /&gt;&lt;br /&gt;Werden wir konkret. Mit den folgenden zwei Parser-Klassen führen wir einen Token-Parser bzw. einen Parser für reguläre Ausdrücke ein. In Python kann man Objekte aufrufbar (&lt;em&gt;callable&lt;/em&gt;) machen, indem man sie mit einer &lt;code&gt;__call__&lt;/code&gt;-Methode ausstattet. Ein Objekt wird damit gleichermaßen zu einer "zustandsbehafteten Funktion". Die &lt;code&gt;__repr__&lt;/code&gt;-Methode dient zur Überschreibung der standardmäßigen Selbstrepräsentation eines Objekts, vergleichbar mit der "toString"-Methode in anderen Sprachen.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;import re, types&lt;br /&gt;&lt;br /&gt;class Parser(object): pass&lt;br /&gt;&lt;br /&gt;class Token(Parser):&lt;br /&gt;    def __init__(self,token,annotation=None):&lt;br /&gt;        self.token, self.annotation = token, annotation&lt;br /&gt;        assert isinstance(annotation,types.StringType) or annotation == None&lt;br /&gt;    def __call__(self,text):&lt;br /&gt;        if text.startswith(self.token):&lt;br /&gt;            return Node(self,self.token), text[len(self.token):]&lt;br /&gt;        return None, text&lt;br /&gt;    def __repr__(self):&lt;br /&gt;        return "Token('" + str(self.token) + "')"&lt;br /&gt;&lt;br /&gt;class RegExp(Parser):    &lt;br /&gt;    def __init__(self,regexp,annotation=None):&lt;br /&gt;        self.regexp, self.annotation  = re.compile(regexp), annotation&lt;br /&gt;        assert isinstance(annotation,types.StringType) or annotation == None&lt;br /&gt;    def __call__(self,text):&lt;br /&gt;        match = self.regexp.match(text)&lt;br /&gt;        if match: return Node(self,match.group()),text[match.end():]&lt;br /&gt;        return None, text&lt;br /&gt;    def __repr__(self):&lt;br /&gt;        return "RegExp(" + str(self.regexp.pattern) + ")"&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Schauen wir uns einmal den Gebrauch der Token-Klasse über die Kommandozeile an:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; Token("Hey")&lt;br /&gt;Token('Hey')&lt;br /&gt;&gt;&gt;&gt; Token("Hey")("Hey!")&lt;br /&gt;(Hey, '!')&lt;br /&gt;&gt;&gt;&gt; Token("Hey")("Heu")&lt;br /&gt;(None, 'Heu')&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Der Token-Parser liefert immer ein Tupel zurück. Der erste Teil des Tupels ist None, wenn der Parser nicht erfolgreich ist. Bei Erfolg wird ein Knoten-Objekt zurückgegeben. Der zweite Teil des Tupels ist der String-Anteil, den es noch zu parsen gilt. Bei Erfolg ist es der Rest-String (hier "!"), bei Misserfolg der gesamte übergebene String ("Heu").&lt;br /&gt;&lt;br /&gt;Hier, der Vollständigkeit halber, der Code zu Node, den Sie der Parser-Klasse voranstellen müssen:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;class Node(object):&lt;br /&gt;    def __init__(self,parser,result):&lt;br /&gt;        self.parser = parser&lt;br /&gt;        self.result = result&lt;br /&gt;    def __repr__(self): # reconstruct the parsed input&lt;br /&gt;        if self.result == None: return ""&lt;br /&gt;        if isinstance(self.result,types.TupleType):&lt;br /&gt;            assert all([isinstance(e,Node) for e in self.result])&lt;br /&gt;            return "".join([str(element) for element in self.result])&lt;br /&gt;        return str(self.result)      &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Nun wird es interessant. Kommen wir zu den Kombinatoren der Parser-Objekte um Sequenzen bzw. Alternativen abzubilden:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;class NaryOperator(Parser):&lt;br /&gt;    def __init__(self,annotation="",*parsers):&lt;br /&gt;        assert all([isinstance(parser,Parser) for parser in parsers])&lt;br /&gt;        assert isinstance(annotation,types.StringType)&lt;br /&gt;        self.parsers, self.annotation = parsers, annotation&lt;br /&gt;&lt;br /&gt;class Sequence(NaryOperator):    &lt;br /&gt;    def __init__(self,annotation,*parsers):&lt;br /&gt;        NaryOperator.__init__(self,annotation,*parsers)&lt;br /&gt;        assert len(self.parsers) &gt;= 1&lt;br /&gt;    def __call__(self,text):&lt;br /&gt;        results = ()&lt;br /&gt;        text_ = text&lt;br /&gt;        for parser in self.parsers:&lt;br /&gt;            node, text_ = parser(text_)&lt;br /&gt;            if not node: return None, text&lt;br /&gt;            results += (node,)&lt;br /&gt;        assert len(results) == len(self.parsers)&lt;br /&gt;        return Node(self,results), text_&lt;br /&gt;    def __repr__(self):&lt;br /&gt;        return "("+",".join([str(parser) for parser in self.parsers])+")"&lt;br /&gt;        &lt;br /&gt;class Alternative(NaryOperator):&lt;br /&gt;    def __init__(self,annotation,*parsers):&lt;br /&gt;        NaryOperator.__init__(self,annotation,*parsers)&lt;br /&gt;        assert len(self.parsers) &gt;= 1&lt;br /&gt;    def __call__(self,text):&lt;br /&gt;        for parser in self.parsers:&lt;br /&gt;            node, text_ = parser(text)&lt;br /&gt;            if node: return Node(self,node), text_&lt;br /&gt;        return None, text&lt;br /&gt;    def __repr__(self):&lt;br /&gt;        return "("+"|".join([str(parser) for parser in self.parsers])+")"&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Sie sehen, dass ich die Annotation von Parser-Objekten erlaube, womit später die Verarbeitung des erzeugten Parsebaums vereinfacht wird. Das soll hier aber nicht unser Thema sein. Schauen wir uns den Gebrauch der Parser-Kombinatoren an:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; s = Sequence("",Token("Gut"),Token("en"))&lt;br /&gt;&gt;&gt;&gt; s&lt;br /&gt;(Token('Gut'),Token('en'))&lt;br /&gt;&gt;&gt;&gt; s("Guten Tag!")&lt;br /&gt;(Guten, ' Tag!')&lt;br /&gt;&gt;&gt;&gt; s("Was ein Tag!")&lt;br /&gt;(None, 'Was ein Tag!')&lt;br /&gt;&gt;&gt;&gt; a = Alternative("",Token("Gut"),Token("en"))&lt;br /&gt;&gt;&gt;&gt; a&lt;br /&gt;(Token('Gut')|Token('en'))&lt;br /&gt;&gt;&gt;&gt; a("Guten Tag!")&lt;br /&gt;(Gut, 'en Tag!')&lt;br /&gt;&gt;&gt;&gt; a("Tag!")&lt;br /&gt;(None, 'Tag!')&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Parser-Kombinatoren sind also tatsächlich selbst wiederum Parser -- genau so soll es sein!&lt;br /&gt;&lt;br /&gt;Lassen Sie uns noch ein paar einwertige Parser-Kombinatoren hinzufügen, damit wir alles zusammen haben, um eine Grammatik vollständig beschreiben zu können:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;class UnaryOperator(Parser):&lt;br /&gt;    def __init__(self,parser,annotation=None):&lt;br /&gt;        assert isinstance(parser,Parser)&lt;br /&gt;        assert isinstance(annotation,types.StringType) or annotation == None&lt;br /&gt;        self.parser, self.annotation = parser, annotation&lt;br /&gt;&lt;br /&gt;class Optional(UnaryOperator):&lt;br /&gt;    def __call__(self,text):&lt;br /&gt;        node, text = self.parser(text)&lt;br /&gt;        if node: return Node(self,node), text&lt;br /&gt;        return Node(self,None), text&lt;br /&gt;    def __repr__(self):&lt;br /&gt;        return str(self.parser) + "?"&lt;br /&gt;&lt;br /&gt;class ZeroOrMore(UnaryOperator):&lt;br /&gt;    def __call__(self,text):&lt;br /&gt;        results = ()&lt;br /&gt;        while True:&lt;br /&gt;            node, text = self.parser(text)&lt;br /&gt;            if not node: break&lt;br /&gt;            results += (node,)&lt;br /&gt;        return Node(self,results), text&lt;br /&gt;    def __repr__(self):&lt;br /&gt;        return str(self.parser) + "*"&lt;br /&gt;&lt;br /&gt;class OneOrMore(UnaryOperator):&lt;br /&gt;    def __call__(self,text):&lt;br /&gt;        results = ()&lt;br /&gt;        text_ = text&lt;br /&gt;        while True:&lt;br /&gt;            node, text_ = self.parser(text_)&lt;br /&gt;            if not node: break&lt;br /&gt;            results += (node,)&lt;br /&gt;        if results == (): return None, text&lt;br /&gt;        return Node(self,results), text_&lt;br /&gt;    def __repr__(self):&lt;br /&gt;        return str(self.parser) + "+"&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Ein Konsolenbeispiel zu OneOrMore:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; OneOrMore(Token('a'))('aaabbbccc')&lt;br /&gt;(aaa, 'bbbccc')&lt;br /&gt;&gt;&gt;&gt; OneOrMore(Token('a'))('bbbccc')&lt;br /&gt;(None, 'bbbccc')&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Wir sind fast am Ziel! Wenn Sie eine Grammatik aufschreiben, in der es rekursive Bezüge gibt, werden Sie auf ein Problem stoßen. Probieren Sie mal Folgendes:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;group   = Sequence("group",Token("{"),doc,Token("}"))&lt;br /&gt;config  = Sequence("config",Token("["),doc,Token("]"))&lt;br /&gt;comment = Sequence("comment",RegExp(r'%.*\n'))&lt;br /&gt;&lt;br /&gt;doc = ZeroOrMore(Alternative("doc",comment,config,group))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Sie können nicht in "group" auf "doc" verweisen, bevor Sie "doc" eingeführt haben! Würden Sie die Regel von "doc" dem "group" voranstellen, hätten Sie dasselbe Problem, nur anders herum.&lt;br /&gt;&lt;br /&gt;Eine Lösung ist, eine Delay-Klasse einzuführen, mit der Sie ein Parser-Objekt anlegen und seine "Logik" per set-Methode nachrüsten. In einer OO-Umgebung ist das eine sehr einfache Lösung, in einer funktionalen Programmierumgebung müssten Sie sich etwas anderes einfallen lassen.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;class Delay(Parser):&lt;br /&gt;    def set(self,parser,annotation=None):&lt;br /&gt;        assert isinstance(parser,Parser)&lt;br /&gt;        assert isinstance(annotation,types.StringType) or annotation == None&lt;br /&gt;        self.parser = parser&lt;br /&gt;        self.annotation = annotation&lt;br /&gt;    def __call__(self,text):&lt;br /&gt;        return self.parser(text)&lt;br /&gt;    def __repr__(self):&lt;br /&gt;        if self.parser.annotation:&lt;br /&gt;            return "{"+ str(self.parser.annotation) + "}"&lt;br /&gt;        return "{" + self.parser.__class__.__name__ + "}"&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Nun können wir die aus dem letzten Post vorgestellte einfache Grammatik für LateX ("&lt;a href="http://denkspuren.blogspot.com/2008/09/eine-einfache-grammatik-fr-latex.html"&gt;Eine einfache Grammatik für LaTeX&lt;/a&gt;") mit unserem objekt-orientierten Parser-Kombinator beschreiben und mit ihr arbeiten:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;doc = Delay()&lt;br /&gt;&lt;br /&gt;text = RegExp(r"[^\\\{\}\[\]%]+","text")&lt;br /&gt;&lt;br /&gt;group   = Sequence("group",Token("{"),doc,Token("}"))&lt;br /&gt;config  = Sequence("config",Token("["),doc,Token("]"))&lt;br /&gt;comment = Sequence("comment",RegExp(r'%.*\n'))&lt;br /&gt;&lt;br /&gt;commandToken = RegExp(r"\\\\?[^\\\{\}\[\]%\s]*","commandToken")&lt;br /&gt;&lt;br /&gt;commandConfig = Sequence("commandConfig",Optional(comment),config)&lt;br /&gt;commandGroup  = Sequence("commandGroup" ,Optional(comment),group)&lt;br /&gt;&lt;br /&gt;command = Sequence("command",&lt;br /&gt;                   commandToken,&lt;br /&gt;                   Optional(commandConfig,"head"),&lt;br /&gt;                   ZeroOrMore(commandGroup,"tail"))&lt;br /&gt;                   &lt;br /&gt;doc.set(ZeroOrMore(Alternative("doc",command,comment,config,group,text)))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Ein erster Härtetest einer jeden Grammatik ist, ob der geparste Input als Output wieder erzeugt werden kann. Wenn Sie Spaß daran haben, probieren Sie es einmal mit einem LaTeX-File.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;(Eine Anmerkung am Rande: Die Konstruktortechnik, hier zur Kombination von Parser-Objekten verwendet, habe ich schon einmal kurz erwähnt in dem Blogbeitrag "&lt;a href="http://denkspuren.blogspot.com/2007/02/uniform-syntax.html"&gt;Uniform Syntax&lt;/a&gt;")&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-6331135678942713365?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/6331135678942713365/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=6331135678942713365' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6331135678942713365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6331135678942713365'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/09/objekt-orientierte-parser-kombinatoren.html' title='Objekt-orientierte Parser-Kombinatoren in Python'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-2999853998361011047</id><published>2008-09-18T01:06:00.003+02:00</published><updated>2008-09-23T11:37:48.739+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Parser'/><category scheme='http://www.blogger.com/atom/ns#' term='Parser Combinator'/><category scheme='http://www.blogger.com/atom/ns#' term='TeX'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='LaTeX'/><category scheme='http://www.blogger.com/atom/ns#' term='Grammatik'/><title type='text'>Eine einfache Grammatik für LaTeX</title><content type='html'>Informatiker schreiben ihre Artikel, Berichte und Arbeiten natürlich mit &lt;a href="http://de.wikipedia.org/wiki/TeX"&gt;TeX&lt;/a&gt; bzw. mit &lt;a href="http://de.wikipedia.org/wiki/LaTeX"&gt;LaTeX&lt;/a&gt; -- sonst gehört man einfach irgendwie nicht dazu ;-) Es gibt unzählige Erweiterungen (im LaTeX-Slang "packages" genannt), die ebenso unzählige Features und Gimmicks nachrüsten für so ziemlich jedes Problem, das man sich vorstellen kann.&lt;br /&gt;&lt;br /&gt;Für die Überarbeitung eines Artikels hatte mir der Verlag die Auflage gemacht, alle Änderungen zur vorigen Version hervorzuheben. In Microsoft Word ein Klacks, in LaTeX zugegebenermaßen ein Umstand. Aber mit &lt;a href="http://www.ctan.org/tex-archive/macros/latex/contrib/changes/"&gt;&lt;code&gt;\usepackage{changes}&lt;/code&gt;&lt;/a&gt; steht einem glücklicherweise ein Paket zur Verfügung, das an dieser Stelle aushilft. So übersäte ich mein LaTeX-Dokument mit &lt;code&gt;\added{...}&lt;/code&gt;, &lt;code&gt;\deleted{...}&lt;/code&gt; und &lt;code&gt;\replaced{...}{...}&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Für eine erneute Überarbeitung wollte ich nun die vielen Änderungsauszeichnungen aus dem LaTeX-Dokument entfernen und zwar so, dass die Änderungen selbst im Text zurückbleiben. Natürlich automatisch und nicht per Hand. Das heißt, etwas vereinfacht gesagt: In dem LaTeX-Dokument können die &lt;code&gt;\deleted{...}&lt;/code&gt;-Auszeichner samt Inhalt einfach verschwinden, von einem &lt;code&gt;\added{...}&lt;/code&gt; muss der Inhalt in der geschweiften Klammerung erhalten bleiben, von einem &lt;code&gt;\replaced{...}{...}&lt;/code&gt; nur der Inhalt der ersten geschweiften Klammerung.&lt;br /&gt;&lt;br /&gt;Diese kleine Herausforderung ist ein fast klassisches Informatik-Problem. Die Anwendung von regulären Ausdrücken für einfache Ersetzungen funktioniert in LaTeX nicht, da LaTeX-Auszeichner verschachtelt sein können und somit das schließende Ende zu einer geöffneten geschweiften Klammer "&lt;code&gt;{&lt;/code&gt;" nicht zuverlässig gefunden werden kann. Also muss man das LaTeX-Dokument parsen. Da TeX seine Grammatik zur Laufzeit ändern kann, ist auch das im Prinzip ein hoffnungsloses Unterfangen -- doch ganz so schlimm ist es in der Realität erfreulicherweise nicht. Für 99.99% aller LaTeX-Dokumente kommt ein sehr regelmäßiges Schema zum Tragen. Nur findet man dazu wenig im Netz.&lt;br /&gt;&lt;br /&gt;Ich habe mir einen Parser in Python geschrieben (einen "&lt;a href="http://en.wikipedia.org/wiki/Parser_Combinator"&gt;Parser Combinator&lt;/a&gt;"), mit dem ich mit einigen einfachen Grammatiken für LaTeX-Dokumente experimentiert habe. Hier das Ergebnis, das mir für meine Zwecke gereicht hat:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;text   := RegExp(r"[^\\\{\}\[\]%]+")&lt;br /&gt;&lt;br /&gt;group  := "{" doc "}"&lt;br /&gt;config := "[" doc "]"&lt;br /&gt;comment := RegExp(r'%.*\n')&lt;br /&gt;&lt;br /&gt;commandToken := RegExp(r"\\\\?[^\\\{\}\[\]%\s]*")&lt;br /&gt;&lt;br /&gt;commandConfig := comment? config&lt;br /&gt;commandGroup  := comment? group&lt;br /&gt;&lt;br /&gt;command := commandToken commandConfig? commandGroup*&lt;br /&gt;&lt;br /&gt;doc := ( command | comment | config | group | text )*&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Ein kleiner Hinweis: Der reguläre Ausdruck für "text" schließt alle die Zeichen aus, die bei "group", "config" und "comment" eine Sonderrolle haben. Auf diese Weise holt sich der Parser mit "text" immer möglichst zusammenhängende Textblöcke rein, ohne jedoch die Trigger "\[]{}%" für die anderen Regeln zu überlaufen. &lt;br /&gt;&lt;br /&gt;Wenn Sie also mal in der Verlegenheit sind, eine Nachverarbeitung für LaTeX-Dokumente vornehmen zu müssen, so mag Ihnen diese einfache Grammatik den Einstieg möglicherweise erleichtern.&lt;br /&gt;&lt;br /&gt;Sollte ich einmal Zeit dazu haben, &lt;a href="http://denkspuren.blogspot.com/2008/09/objekt-orientierte-parser-kombinatoren.html"&gt;dann erkläre ich Ihnen&lt;/a&gt;, wie man sich in einer objekt-orientierten Sprache einen Parser Combinator schreibt. Das geht erstaunlich einfach.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-2999853998361011047?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/2999853998361011047/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=2999853998361011047' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2999853998361011047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2999853998361011047'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/09/eine-einfache-grammatik-fr-latex.html' title='Eine einfache Grammatik für LaTeX'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-5992707385742188918</id><published>2008-09-07T00:38:00.001+02:00</published><updated>2008-09-07T00:39:00.768+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='addons'/><category scheme='http://www.blogger.com/atom/ns#' term='extensions'/><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><category scheme='http://www.blogger.com/atom/ns#' term='chrome'/><category scheme='http://www.blogger.com/atom/ns#' term='HTML'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='addon'/><title type='text'>Add-ons for Chrome - or - A new architecture for browsers</title><content type='html'>On September 2nd, on Tuesday, Google released Chrome -- their own web browser. Chrome has a simple, unobtrusive user interface, it's based on WebKit, it's powered by a new JavaScript implementation, it runs a process for each new tab, and it promises a new approach to safe browsing. On this one, Chrome failed. Chrome has some severe security holes Google needs to fix. Nonetheless, I like the new browser.&lt;br /&gt;&lt;br /&gt;Some hours after Google had released Chrome, I read a lot of comments about the Chrome experience. Most users seemed to be quite enthusiastic, some few were not. But one sort of comments caught my attention: Some folks argued that Firefox users will stay with Firefox. Why? Because of all these nice add-ons you can extend Firefox with.&lt;br /&gt;&lt;br /&gt;My spontaneous reaction was: Who needs add-ons?&lt;br /&gt;&lt;br /&gt;Before you laugh at me. I run Firefox with extensions like Firebug, Web Developer, ScrapBook and others. I use them extensively and like them a lot. Who wants to miss Firebug, for instance? Nobody, right?! I wouldn't use a browser without my beloved add-ons. And one is for sure. A browser without extension capabilities won't make it in the long run. (Ok, I'm not sooo sure.)&lt;br /&gt;&lt;br /&gt;So what made me think "Who needs add-ons"?&lt;br /&gt;&lt;br /&gt;I contemplated some time over my spontaneous reaction. Forgive me, I don't know much about how to write extensions for Firefix. I am an extension user, not an extension programmer. But my gut feeling tells me that the approach to extensions in Firefox is wrong. It's the worst Google could do to copy the extension mechanism of Firefox. I should rephrase my first reaction: "Who needs such an add-on architecture?"&lt;br /&gt;&lt;br /&gt;Instead of criticizing Firefox's extension mechanism, of which I don't know much about, let me sketch an alternative approach to extensions.&lt;br /&gt;&lt;br /&gt;Assume a "naked" browser: no buttons to click on, no url field, no menu, nothing. Assume that all the browser does after startup is run a JavaScript program. Let's call this program the "Controller". The key point is: You can change the Controller. Don't like the default Controller? Change it. The Controller is under your control!&lt;br /&gt;&lt;br /&gt;The default Controller is a JavaScript program that creates buttons to click on and implements a history of web pages visited. It provides the url input field and displays suggestions while you type. It lets you have menus and so on.&lt;br /&gt;&lt;br /&gt;Got it? The Controller is a program that creates a user interface that mimics Firefox. Or Chrome. Or IE. Or Opera. Or Safari. Whatever you want.&lt;br /&gt;&lt;br /&gt;If you type in a url in the url field and hit enter, it's the Controller, which -- so to speak -- creates an IFrame and loads the given web page into that frame. So the web page remains fully under control of the Controller.&lt;br /&gt;&lt;br /&gt;It does not require that much imagination to see that the Controller can easily be extended by -- right, by extensions or add-ons. These extensions are just other JavaScript programs, which are plugged into the Controller.&lt;br /&gt;&lt;br /&gt;To oversimplify things, I envision a browser, which consists only of an HTML and CSS rendering engine and a virtual machine running JavaScript. The rest is initiated by an ordinary JavaScript program using web technology. In other words: My favorite browser is fully programmable with web technology.&lt;br /&gt;&lt;br /&gt;The idea is simple, isn't it? It thrills me.&lt;br /&gt;&lt;br /&gt;The development of such a "naked" browser inevitably raises questions like:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;How do we guarantee that the Controller doesn't loose control?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;How do we compose add-ons? How do we avoid interference of add-ons?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Do we need a component architecture? Or do we need a service-oriented architecture?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;How do we ensure safe browsing and secure execution?&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;It's much about architecture thinking and a JavaScript implementation that supports fundamental notions of modularization, safety and security. These are aspects which should IMHO drive the standardization activities of JavaScript. Implementors of browsers should radically rethink the way browsers are built and function. Google did a first, tiny step in that direction with Chrome. But there's more to strive for.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-5992707385742188918?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/5992707385742188918/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=5992707385742188918' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5992707385742188918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5992707385742188918'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/09/add-ons-for-chrome-or-new-architecture.html' title='Add-ons for Chrome - or - A new architecture for browsers'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-6418777650150651733</id><published>2008-09-03T09:09:00.001+02:00</published><updated>2008-09-03T09:10:08.885+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MetaOCaml'/><category scheme='http://www.blogger.com/atom/ns#' term='Multi-Stage Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Scheme'/><category scheme='http://www.blogger.com/atom/ns#' term='Lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='MSP'/><title type='text'>Multi-Stage Programming in Scheme</title><content type='html'>Vor nicht allzu langer Zeit habe ich mich in einem Beitrag mit "&lt;a href="http://denkspuren.blogspot.com/2008/08/multi-stage-programming.html"&gt;Multi-Stage Programming&lt;/a&gt;" (MSP) beschäftigt. Ich warf in dem Blog-Posting die Frage auf, ob MSP im Grunde nicht mit der Makroprogrammierung wie z.B. in Scheme oder Lisp vergleichbar sei.&lt;br /&gt;&lt;br /&gt;In der Tat kann das MetaOCaml-Beispiel, die Auflösung der Power-Funktion, sehr leicht mit &lt;code&gt;defmacro&lt;/code&gt;, dem Urmakro aus Lisp, in Scheme nachgebildet werden. Hier kommt &lt;a href="http://www.plt-scheme.org/"&gt;PLT-Scheme&lt;/a&gt; zum Einsatz -- mit Dank an &lt;a href="http://bitsandproofs.blogspot.com/"&gt;Tim&lt;/a&gt; für den Code:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;(require (lib "defmacro.ss"))&lt;br /&gt;; POWER MACRO &lt;br /&gt;(define-macro power&lt;br /&gt;  (lambda (n x)&lt;br /&gt;    (if (= n 0)&lt;br /&gt;        '1&lt;br /&gt;        `(* ,x (power ,(- n 1) ,x)))))&lt;br /&gt;(power 2 4)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Stellt man dem Code in PLT-Scheme noch ein&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;(require (lib "../macro-debugger/expand.ss"))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;voran und gibt dann interaktiv ein&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;(expand/step '(power 2 2))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;ein, dann öffnet sich ein Fenster zum schrittweisen Makroauflösen. Ich habe ein wenig mit den Check-Boxen experimentiert: Mit "Enable macro hiding?" und "Hide mzscheme syntax" sieht die Auflösung unkryptisch aus.&lt;br /&gt;&lt;br /&gt;Nun lese ich die Tage von Oleg Kiselyov etwas über "&lt;a href="http://okmij.org/ftp/Computation/Generative.html#meta-scheme"&gt;MetaScheme, or untyped MetaOCaml&lt;/a&gt;". In seinem Beitrag implementiert er "the four MetaOCaml special forms -- bracket, escape, cross-stage persistence (aka `lift'), and run -- in R5RS Scheme." Er argumentiert, dass eine 1:1-Übersetzung der MetaOCaml Special Forms in Scheme ("MetaOCaml's bracket is like quasiquote, escape is like unquote, and `run' is eval") nicht zum gewünschten Ergebnis führt. Vor allem übersieht Scheme die Bindungsstrukturen, die MetaOCaml natürlich sauber berücksichtigt.&lt;br /&gt;&lt;br /&gt;Kiselyov bietet die MetaOCaml Special Forms als Macros für R5RS an, die nun dasselbe Verhalten zeigen wie die Special Forms in MetaOCaml. Eine beeindruckende Lösung, die -- wie alles bei Kiselyov -- ein tiefes Verständnis für Scheme aufweist. Sie verrät aber auch, wie MSP implementiert werden kann.&lt;br /&gt;&lt;br /&gt;Eine Einsicht bleibt dennoch: Macros sind der Fast Track zu MSP in Scheme bzw. Lisp -- ohne Netz und doppelten Boden.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-6418777650150651733?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/6418777650150651733/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=6418777650150651733' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6418777650150651733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6418777650150651733'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/09/multi-stage-programming-in-scheme.html' title='Multi-Stage Programming in Scheme'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-5567582000755639456</id><published>2008-09-02T09:03:00.005+02:00</published><updated>2008-09-04T20:08:55.569+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='chrome'/><category scheme='http://www.blogger.com/atom/ns#' term='google'/><title type='text'>Browsing aufpoliert: Google Chrome</title><content type='html'>Firefox, Opera, Safari, Internet Explorer -- die großen "Player" im Browser-Markt versuchen sich immer wieder an neuen, oft kleinen Features, die das Surfen im Internet angenehmer, komfortabler, sicherer und vielleicht auch ein wenig spaßiger gestalten sollen. Jüngst stellte Microsoft seinen neuen Internet Explorer 8 in der Beta-Version vor.&lt;br /&gt;&lt;br /&gt;Seit gestern ist es semi-offiziell. Google möchte heute der Welt einen eigenen und etwas anderen Browser bescheren: Google Chrome ("&lt;a href="http://googleblog.blogspot.com/2008/09/fresh-take-on-browser.html"&gt;A fresh take on the browser&lt;/a&gt;", 1. Sep. 2008). Man scheint es sehr ernst zu nehmen. Ein unterhaltsames Comic soll den Anwender bzw. die Anwenderin vom Vorteil und Nutzen des aufpolierten Browser-Modells überzeugen: "&lt;a href="http://www.google.com/googlebooks/chrome/"&gt;Google Chrome: Behind the Open Source Browser Project&lt;/a&gt;".&lt;br /&gt;&lt;br /&gt;Technisch hat man das Browser-Modell auf neue Beine gestellt. Mehrere Webseiten lassen sich, wie gehabt, über Tabs gleichzeitig öffnen und organisieren. Doch nun stellt jeder Tab einen eigenen Prozess dar, was echte Parallelität liefert. So blockiert eine "hängende" Seite in einem Tab nicht die Arbeit des ganzen Browsers und damit der anderen Tab-Seiten. Erstaunlich, dass es zu diesem Mehr-Prozess-Fundament des Engagements von Google bedurfte. Doch scheint dieses Feature zusammen mit der neuen JavaScript-Engine namens V8 in der Techie-Szene bereits Begeisterung hervorzurufen (John Resig: "&lt;a href="http://ejohn.org/blog/google-chrome-process-manager/"&gt;Google Chrome Process Manager&lt;/a&gt;"). Selbstredend ist auch Google Gears in Google Chrome integriert. Und Chrome soll open-source sein!&lt;br /&gt;&lt;br /&gt;Ich bin gespannt -- und warte schon auf den &lt;a href="http://www.google.com/chrome"&gt;Link zum Download&lt;/a&gt;! Bis dahin: Haben auch Sie viel Spaß an der Vorfreude mit dem Comic.&lt;br /&gt;&lt;br /&gt;[[Update: Zwei Tipps zu Chrome. Der Browser verrät einige Interna durch sogenannte "about"-Seiten, siehe "&lt;a href="http://googlesystem.blogspot.com/2008/09/google-chromes-about-pages.html"&gt;Google Chrome's about:Pages&lt;/a&gt;". Ein paar Bedienhinweise liefert "&lt;a href="http://googlesystem.blogspot.com/2008/09/google-chrome-tips.html"&gt;Google Chrome Tips&lt;/a&gt;".]]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-5567582000755639456?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/5567582000755639456/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=5567582000755639456' title='6 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5567582000755639456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5567582000755639456'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/09/browsing-aufpoliert-google-chrome.html' title='Browsing aufpoliert: Google Chrome'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-5966336094786082791</id><published>2008-08-26T16:54:00.003+02:00</published><updated>2008-08-26T17:28:51.600+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Internet'/><title type='text'>Zu den Ursprüngen: Das Internet</title><content type='html'>Ich weiß nicht, ob Sie auch zu den Freaks gehören, die gerne technische Standards lesen und sich immer mal wieder auf den &lt;a href="http://www.ietf.org/rfc.html"&gt;RFC-Seiten&lt;/a&gt; der &lt;a href="http://www.ietf.org/"&gt;IETF&lt;/a&gt;, der Internet Engineering Task Force, wiederfinden. Manche mögen die technischen Sachverhalte, die in den "Request for Comments" (RFCs) dargelegt sind, für langweilig halten. Ich finde sie spannend. Man lernt eine Menge über das Internet. Wie es funktioniert, welche Ideen es angeleitet und getrieben haben und welche Konzepte und Ideen den einzelnen Netzschichten und Protokollen zugrunde liegen. Eine Unmenge an interessanten Informationen findet sich da, frei verfügbar und für jeden zugreifbar. Ein Wissen, das nicht unbedingt in den Lehrbüchern zu den "Rechnernetzen" oder "Web-Technologien" zu finden ist.&lt;br /&gt;&lt;br /&gt;Via &lt;a href="http://www.ehrensenf.de"&gt;Ehrensenf&lt;/a&gt; (&lt;a href="http://www.ehrensenf.de/shows/ehrensenf/videokommentare-lichtufos-%C2%A0vierte-dimension"&gt;Sendung vom 26. August&lt;/a&gt;) bin ich auf eine wunderbare Webseite der National Science Foundation (NSF) gestoßen. Auf der Seite "&lt;a href="http://www.nsf.gov/news/special_reports/nsf-net/"&gt;NSF and the Birth of the Internet&lt;/a&gt;" setzen sich die Amerikaner medial sehr gelungen als Erfinder und Pioniere des Internets in Szene und erzählen seine Geschichte. Eine Geschichte mit Menschen zum "Anfassen", ein Zurückblättern in eine Welt, in der es noch keine Blogs, Chats, ICQs, EMails, Internet-Telefonie und all das gab. Unvorstellbar, nicht wahr?&lt;br /&gt;&lt;br /&gt;Vielleicht können Sie nach dem Besuch der NSF-Seite nachvollziehen, warum ein Blättern und Lesen in den alten RFCs aus den 80ern so aufregend und spannend sein kann. Leider lassen die jüngeren RFCs einiges an Qualität und Brillanz vermissen, die noch die "alten" RFCs auszeichnete.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-5966336094786082791?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/5966336094786082791/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=5966336094786082791' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5966336094786082791'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5966336094786082791'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/08/zu-den-ursprngen-das-internet.html' title='Zu den Ursprüngen: Das Internet'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-6639158786481987348</id><published>2008-08-15T11:55:00.005+02:00</published><updated>2008-08-15T12:29:12.240+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MetaOCaml'/><category scheme='http://www.blogger.com/atom/ns#' term='Multi-Stage Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='DSL'/><category scheme='http://www.blogger.com/atom/ns#' term='Walid Taha'/><category scheme='http://www.blogger.com/atom/ns#' term='MSP'/><title type='text'>Multi-Stage Programming</title><content type='html'>Neben den Programmiersprachen gibt es eine Vielzahl von verschiedenen Techniken und Ansätzen des Gebrauchs, des Einsatzes, der Verwendung und der Erweiterung von Programmiersprachen. Alle diese Techniken bzw. Ansätze enden auf "Programming": Generative Programming, Aspect-Oriented Programming, Object-Oriented Programming, Context-Oriented Programming, Subject-Oriented Programming -- es gibt unzählige solcher Bezeichnungen. Hinter den meisten dieser Namen stecken interessante Ansätze, die auf nur wenigen Konzepten oder Ideen beruhen.&lt;br /&gt;&lt;br /&gt;In den vergangenen Tagen habe ich mich mit "Multi-Stage Programming" (MSP) beschäftigt. Dieser Blog-Beitrag ist eine Aufbereitung des Papers "&lt;a href="http://www.cs.rice.edu/~taha/publications/journal/dspg04a.pdf"&gt;A Gentle Introduction to Multi-Stage Programming&lt;/a&gt;" von &lt;a href="http://http://www.cs.rice.edu/~taha/"&gt;Walid Taha&lt;/a&gt;. Das Paper ist auf seiner &lt;a href="http://www.cs.rice.edu/~taha/publications.html"&gt;Publikationsseite&lt;/a&gt; zu finden. Alle Zitate und Code-Beispiele stammen aus dem Paper.&lt;br /&gt;&lt;br /&gt;Ich bitte um Nachsicht und um Korrekturen, sollten sich in der folgenden Darstellung des Papers von Taha Fehler finden. Ich bin kein MSP-Experte und bringe dazu auch keine &lt;i&gt;hands on&lt;/i&gt;-Erfahrung mit. Auch über klärende Kommentare freue ich mich, insbesondere, was den Vergleich mit Makros angeht.&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;&lt;br /&gt;Multi-Stage Programming (MSP) ist eine besondere Form der generativen Programmierung und damit eine Technik der Meta-Programmierung. Zwei Gedanken führen zum MSP: (1) Programmgenerierung bringt einige Probleme mit sich, die in der Generierungsproblematik selber liegen, die also inhärent sind. (2) Es gibt wenig Unterstützung für die Erstellung von Generatoren in Hochsprachen wie Java oder C.&lt;br /&gt;&lt;br /&gt;MSP ist der Ansatz mit einer Sprache zu arbeiten, die ausdrücklich zur Generierung von Programmen &lt;i&gt;in ihrer eigenen Sprache&lt;/i&gt; geeignet ist und die die mit der Programmgenerierung verbundenen Probleme vermeidet.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Was sind die Probleme?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Man kann Programme in Textform mit Strings generieren. Das Problem: Man kann Programme konstruieren, die syntaktisch ungültig sind.&lt;br /&gt;&lt;br /&gt;Eine andere Option ist, ein Programme durch Datentypen zu kodieren, z.B. mit einem abstrakten Syntaxbaum (AST). Es werden immer syntaktisch korrekte Programme zurück geliefert. Das Problem: Datentypen können zwar syntaktische korrekte Programme garantieren, nicht aber, ob diese auch well-typed sind.&lt;br /&gt;&lt;br /&gt;MSP nimmt sich dieser Problematik an: MSP stellt sicher, dass ein generiertes Programm syntaktisch korrekt und well-typed ist. Darüber hinaus verhindert MSP Namenskonflikte und unbeabsichtigte Variablenübernahmen. Das klingt gut, besonders, wenn man mit statisch typisierten Sprachen arbeiten möchte.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Drei Basiskonzepte für MSP in MetaOCaml&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.metaocaml.org/"&gt;MetaOCaml&lt;/a&gt; ist eine Erweiterung zu OCaml für MSP. Lediglich drei Konzepte werden in der Sprachwelt von OCaml mit MetaOCaml verankert mit denen eine typkonforme Manipulation von Programmfragmenten in OCaml möglich ist.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Brackets&lt;/b&gt; ".&lt; &gt;." können einen Ausdruck (expression) umgeben. Sie verzögern seine Ausführung. Brackets konservieren einen Ausdruck als Code-Fragment zur späteren Berechnung (= Compilierung und Ausführung), im Beispiel ".&lt;1+2&gt;.":&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# let a = 1+2;;&lt;br /&gt;val a : int = 3&lt;br /&gt;# let a = .&lt;1+2&gt;.;;&lt;br /&gt;val a : int code = .&lt;1+2&gt;.&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Neben der Verzögerung weiß ein Bracket um den Typen, den ein geklammerter Ausdruck im Falle der Ausführung zurück gibt. Oben kann man sehen, wie "int code" als Typ auf der Kommandozeile ausgegeben wird. Die Typen "int code" und "int" sind unterschiedlich und lassen sich nicht mixen. Ein "1 + .&lt;5&gt;." ist nicht erlaubt.&lt;br /&gt;&lt;br /&gt;Mit einem &lt;b&gt;Escape&lt;/b&gt; ".~" können verzögerte Ausdrücke zu neuen verzögerten Ausdrücken komponiert werden. Das "a" bezieht sich aus dem vorangegangenen Beispiel.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# let b = .&lt;.~a * .~a &gt;. ;;&lt;br /&gt;val b : int code = .&lt;(1 + 2) * (1 + 2)&gt;.&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Schlussendlich wird mit einem &lt;b&gt;Run&lt;/b&gt; ".!" ein verzögerter Ausdruck compiliert und ausgeführt:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# let c = .! b;;&lt;br /&gt;val c : int = 9&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Eine Funktion, die Brackets und Escapes enthält (anscheinend auch Annotationen genannt), wird als &lt;i&gt;staged&lt;/i&gt; bezeichnet; eine normale Funktion ohne Annotationen als &lt;i&gt;"unstaged"&lt;/i&gt;. Mit den Annotationen kann die Reihenfolge der Ausführung (evaluation order) explizit spezifiziert werden.&lt;br /&gt;&lt;br /&gt;That's it! So einfach sich das anhört, aber gerade die eingebaute Typsicherheit bringt es mit sich, dass man in der Tat nur gültige Programme aus verzögerten Ausdrücken komponieren kann. Für dynamisch typisierte Sprachen wäre das nicht möglich. Mit MSP kann man Staged Interpreters bauen. Sie gelten als ebenso einfach zu bauen wie "normale" Interpreter, sind aber nahezu so effizient wie Compiler.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;The primary goal of MSP is to help the programmer reduce the runtime overhead of sophisticated abstraction mechanisms.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Staged Programms = Programming with Makros?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Es schleicht sich allmählich der Verdacht ein, dass es sich bei Bracket, Escape und Run lediglich um ein Makrosystem handelt, das darauf achtet, typkonforme Konstrukte zu erzeugen. Trifft dieses Mapping auf Lisp zu, wenn man mal von der Typisierung absieht? Bracket = Quote, Escape = Makrodefinition, Run = Makroauflösung?&lt;br /&gt;&lt;br /&gt;Ein Beispiel, das diese Beobachtung stützt findet sich in Kapitel 2.2 "A Classic Example". Die Power-Funktion x^n löst sich auf in die n-fache Anwendung der Multiplikation von x. x^3 liefert also x*x*x. Das kann in einer rein funktionalen Programmiersprache nur iterativ ausgedrückt werden. In MetaOCaml sieht das wie folgt aus:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;let rec power (n, x) =&lt;br /&gt;match n with&lt;br /&gt;0 -&gt; 1 | n -&gt; x * (power (n-1, x));;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Nehmen wir an, wir machen häufig Gebrauch von der Quadratfunktion power2:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;let power2 (x) = power (2,x);;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Oder alternativ in etwas anderer Ausdrucksweise, die wir unten wieder verwenden werden:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;let power2 = fun x -&gt; power (2,x);;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Ärgerlich ist der Overhead, das bei jeder Quadrierung der parametrisierte Aufruf power(2,x) eine Rekursion ausführt. Das führt zu Performanzverlusten. Günstiger wäre es, power2 iterationslos auf "x*x" abzubilden. Annotieren wir power(n,x) entsprechend, dann kann man diese Auflösung forcieren:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;let rec power (n, x) =&lt;br /&gt;match n with&lt;br /&gt;0 -&gt; .&lt;1&gt;. | n -&gt; .&lt;.~x * .~(power (n-1, x))&gt;.;;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Damit hat sich aber auch der Typ des zweiten Arguments (x) verändert: Hier muss ein Code vom Typ Integer übergeben werden, z.B. .&lt;3&gt;., so dass power (2,.&lt;3&gt;.) aufgelöst wird zu:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;.&lt; .&lt;3&gt;. * .&lt;3&gt;. * .&lt;1&gt;. &gt;.&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Das ist auch der Grund, warum der match-Fall für 0 abgebildet wird auf .&lt;1&gt;. und nicht 1, so sonst die Multiplikation nicht mehr konform Typen vom Typ "code of type int" verkettet.&lt;br /&gt;&lt;br /&gt;Folglich kann nun power2 definiert werden über eine staged function:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;let power2 = .! .&lt;fun x -&gt; .~(power (2,.&lt;x&gt;.))&gt;.;;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;power2 erzeugt eine verzögerte Funktion mit x als Eingabeparameter. Bereits zur Compilezeit wird über das Escape ein Aufruf der Funktion power vorgenommen (so verstehe ich das zumindest), wobei x via .&lt;x&gt;. typmäßig angepasst wird. Der Aufruf von power liefert ein verzögertes x*x*1 zurück. Das Run .! erlaubt dem Compiler auch diesen Code gleich weiter zu übersetzen, so als ob er direkt x*x*1 übersetzt hätte.&lt;br /&gt;&lt;br /&gt;Das Ergebnis ist also, dass wir über das power-"Makro", Code generieren konnten, der so effizient ist wie handgeschriebener Code für power2.&lt;br /&gt;&lt;br /&gt;In Kapitel 3 "Implementing DSLs Using Staged Intepreters" demonstriert Taha, wie man mit stage programming eine DSL umsetzen kann, die &lt;i&gt;im Stil&lt;/i&gt; eines Interpreters geschrieben wird, durch Staging jedoch soviel wie möglich zur Compilezeit erledigt. Im Endeffekt soll damit zur Ausführungszeit der DSL eine Performanz erreicht werden, die der Performanz entspricht, hätte man einen Compiler für die DSL geschrieben. Natürlich ist mit einem Compiler als Zielsprache die Implementierungssprache gemeint, mit der auf der staged Interpreter geschrieben wird. Ansonsten ist der Vergleich natürlich absurd. So heißt es bei Taha:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;A staged interpreter is a translator&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Das Paper demonstriert an einer sehr simplen DSL den Bau eines Staged Interpreters, und merkt dann an: "... further reserach is need [Schreibfehler im Original] to show that we can apply MSP to realistic programming languages.". Das heißt: Wir müssen noch lernen, unserer MSP strukturiert in verschiedenen Themenbereichen einzusetzen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-6639158786481987348?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/6639158786481987348/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=6639158786481987348' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6639158786481987348'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6639158786481987348'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/08/multi-stage-programming.html' title='Multi-Stage Programming'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-3614436276375259797</id><published>2008-08-11T22:47:00.005+02:00</published><updated>2008-08-12T00:27:13.505+02:00</updated><title type='text'>Der Computer als "verlängertes" Hirn</title><content type='html'>Schließen Sie die Augen! Konzentrieren Sie sich! Gehen Sie in Gedanken durch das Zimmer oder den Raum, in dem Sie sich gerade befinden. Beginnen Sie, vor Ihrem geistigen Auge die Möbel umzuräumen. Wie wäre es mit ein paar Pflanzen in der Ecke? Bekommen sie dort genug Licht? Lassen Sie die Morgensonne durch das Fenster scheinen. Dann die Mittags- und zu guter letzt die Abendsonne. Gefällt Ihnen, wie sich die Lichtverhältnisse ändern? Geht es der Pflanze an ihrem Standort gut? Streichen Sie die Tapeten in Gedanken einmal rot, blau oder gelb. Wie wäre es mit grün? Mehr hellgrün oder dunkelgrün?&lt;br /&gt;&lt;br /&gt;Ihnen geht es sicher wie mir. Ich bin mit meiner Vorstellungskraft überfordert. Ich kann mein Arbeitszimmer gedanklich zwar irgendwie einfärben, aber willentlich klare Farben aussuchen und diese Szenerie vor dem geistigen Auge so zu betrachten als sei es real -- unmöglich. Wie ich mir Lichteindrücke vorstellen soll, ich habe keine Ahnung.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.grandin.com/"&gt;Prof. Dr. Temple Grandin&lt;/a&gt; kann sowas. Sie beschreibt es in ihrem Buch "&lt;a href="http://www.grandin.com/inc/book.html"&gt;Thinking in Pictures&lt;/a&gt;". Ihr Gedächtnis speichert "Filme". Sie hat die Fähigkeit, sich in ihrer "Filmwelt" dreidimensional zu bewegen und die Welt aus verschiedenen Blickwinkeln zu betrachten. Sie kann auch Änderungen in der Vorstellungswelt vornehmen. Wir dürfen uns das vermutliche wie eine Simulationswelt denken, in der man beliebige Kamerafahrten machen und beliebige Eingriffe durchspielen kann. So eine Art &lt;i&gt;Grand Theft Auto IV&lt;/i&gt; im Kopf. Wobei man nicht nur Spieler, sondern auch Spieleentwickler ist. Frau Grandin nutzt ihre Begabung zum Entwurf von Anlagen zur Viehhaltung und -schlachtung.&lt;br /&gt;&lt;br /&gt;Es ist beeindruckend, zu welchen Ausnahme-Leistungen unser Gehirn in der Lage ist. Doch der Preis für solche Inselbegabungen scheint hoch zu sein. Temple Grandin ist Autistin. &lt;a href="http://de.wikipedia.org/wiki/Autismus"&gt;Autismus&lt;/a&gt; ist eine Entwicklungsstörung, die die betroffenen Menschen in ihrem Vermögen zu sozialer und kommunikativer Interaktion erheblich einschränkt. Frau Grandin ist insofern eine Ausnahme, als dass sie einen Weg der Kommunikation mit uns Nicht-Autisten gefunden hat.&lt;br /&gt;&lt;br /&gt;Doch es geht mir in diesem Beitrag weniger um den Autismus. Als ich &lt;a href="http://www.grandin.com/inc/visual.thinking.html"&gt;das erste Kapitel&lt;/a&gt; zu Grandins Buch las, war ich beeindruckt von dieser Fähigkeit. Mit solchen Hirnleistungen kann man Dinge tun und erreichen, die Otto-Normal-Hirn verwehrt sind.&lt;br /&gt;&lt;br /&gt;Oder?&lt;br /&gt;&lt;br /&gt;Ja, das ist richtig. Aber wir Menschen haben uns ein wunderbares Werkzeug erschaffen, das sozusagen als "verlängertes" Hirn fungieren kann: der Computer. Mit einem Computer können wir Simulationen durchführen. Wir können uns in selbst erschaffenen Welten bewegen, können Autos crashen lassen ohne einem Dummy ein Haar zu krümmen. Wir können das Wetter vorhersagen, die Höhe der Altersrente errechnen, Risikoanalysen durchführen und und und.&lt;br /&gt;&lt;br /&gt;Aber nutzen wir dieses Werkzeug eigentlich systematisch? &lt;br /&gt;&lt;br /&gt;Haben Sie in Schule, Ausbildung oder Studium jemals mit Simulationen gearbeitet? Haben Ihre Lehrer, Ausbilder oder Dozenten Sie dazu animiert, selber Gedankenexperimente mit dem Rechner auszuführen. Sei es um Häuser an virtuellen Baugruben zu errichten, um zu verstehen, wie ein Staubsauber funktioniert (Wie saugt man Luft an?) und wie es auf Autobahnen zu Staus aus dem Nichts kommen kann. Welche einfachen Regeln erklären die Streifen auf dem Zebra? Haben Sie's mal am Rechner ausprobiert? Heute schon die zu erwartende Projektdauer per Monte-Carlo-Simulation ermittelt?&lt;br /&gt;&lt;br /&gt;Der Computer ist ein wunderbares Werkzeug. Jedem von uns steht diese "Hirnprothese" zur Verfügung. Nur nutzen wir sie nicht. Jedenfalls nicht zur Modellierung und Simulation alltäglicher Phänomene. Wir haben's nicht gelernt, den Rechner als Verstehens- und Entscheidungshilfe zu verwenden; haben nicht einmal die richtigen Programme dazu zur Hand und auf dem Rechner installiert. Eigentlich schade.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-3614436276375259797?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/3614436276375259797/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=3614436276375259797' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3614436276375259797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3614436276375259797'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/08/der-computer-als-verlngertes-hirn.html' title='Der Computer als &quot;verlängertes&quot; Hirn'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-3030557402197188687</id><published>2008-08-04T11:31:00.005+02:00</published><updated>2008-08-06T10:09:38.196+02:00</updated><title type='text'>Im Kampf gegen Monstersysteme</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_XJMaba79IKU/SJlbaxtlfEI/AAAAAAAAAFA/uZDVwGnYglk/s1600-h/kaptainkobold.382081834.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_XJMaba79IKU/SJlbaxtlfEI/AAAAAAAAAFA/uZDVwGnYglk/s400/kaptainkobold.382081834.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5231312957746805826" /&gt;&lt;/a&gt;&lt;br /&gt;Im Urlaub war es wieder soweit: Das, was wir Informatiker den Menschen um uns herum so zumuten, das machte mir ein fürchterlich schlechtes Gewissen.&lt;br /&gt;&lt;br /&gt;Was war geschehen? Eigentlich nichts spektakuläres. Die Vermieterin unserer Ferienwohnung brauchte Hilfe bei der Einrichtung ihres neu erworbenen Laptops. In drei Stunden war der Rechner mit Windows Vista hergerichtet, die neuesten Updates installiert, Flash Player, Adobe Reader, OpenOffice nachgerüstet -- das Übliche halt. Schon dabei wurde mir ganz mulmig.&lt;br /&gt;&lt;br /&gt;Und dann, am nächsten Abend, begann ich der guten Frau eine Einführung in Vista zu geben. "Hier klicken, da klicken, gucken Sie mal, alles ganz einfach, dann hier klicken, da klicken. Huch, die Firewall meldet sich. Wissen Sie, was das ist? Nein? Egal, hier klicken, da klicken, dann geht's weiter. Lassen sie sich von sowas nicht irritieren." Was fühlte ich mich elend. "Wenn Sie Ihre Kochrezepte anschauen wollen, hier klicken, da klicken, sehen Sie, OpenOffice startet, dann hier klicken, da klicken. Voilà. Einfach, gell?" Und ich wusste, dass ich log. Nix einfach! Ganz und gar nicht einfach. Da sitzt eine ältere Frau neben mir, die ich in einer Informationsflut ertränkte, die gerade einmal ins Internet möchte, EMails und Briefe schreiben will, vielleicht einmal mit Videotelefonie übers Internet Familienkontakte pflegen möchte und ansonsten an die Archivierung und den Ausbau ihrer Sammlung von Kochrezepten denkt.&lt;br /&gt;&lt;br /&gt;Wozu muss so jemand ein komplexes Betriebssystem erlernen? Was belästigen wir die Menschen mit der Nachfrage zu Software-Updates? Welche Arten von Entscheidungen verlangt da eigentlich eine Firewall? Warum muss Otto-Normal-Verbraucher erst einen VHS-Kurs zu OpenOffice machen, bevor er oder sie sich einigermaßen in den Büro-Programmen zurechtfindet? &lt;br /&gt;&lt;br /&gt;Warum in aller Welt sind unsere Betriebssysteme, Browser und Anwendungen so kompliziert? &lt;br /&gt;&lt;br /&gt;Wir sind's selber schuld! Wir erschaffen wahre Monster, derer wir selber nicht mehr Herr sind. Auf dem &lt;a href="http://www.swa.hpi.uni-potsdam.de/s3/index.html"&gt;"Workshop on Self Sustaining Systems (S3) 2008"&lt;/a&gt; am Hasso-Plattner-Institut (HPI) illustrierte Ian Piumarta Mitte Mai als Invited Speaker die Komplexität heutiger Systeme anhand folgender Zahlen: Windows Vista besteht seinen Angaben zufolge aus 50 Millionen Zeilen Programmcode, Mac OSX aus 86 Millionen Zeilen, OpenOffice aus 10 Millionen Zeilen Code (Links zum &lt;a href="http://piumarta.com/papers/S3-2008-slides.pdf"&gt;Foliensatz&lt;/a&gt; und zum Talk "Late-bound Object Lambda Architectures" als &lt;a href="http://www.tele-task.de/page50_lecture3616.html"&gt;Video&lt;/a&gt;). Solche Systeme sind allein ihrer schieren Größe wegen von einem Entwickler bzw. einer Entwicklerin nicht mehr überschau- und verstehbar. Kein Wunder, das ein BugFixing das nächste jagt und manche Probleme oder Fehler über Monate, wenn nicht gar Jahre, im System bleiben, obwohl sie bekannt sind.&lt;br /&gt;&lt;br /&gt;Kann es sein, dass wir den Bau solcher Systeme grundlegend falsch angehen? Piumarta glaubt, dass das alles viel einfacher geht, gehen muss, dass es auch mit 20.000 Zeilen Code möglich sein muss, eine Umgebung auf einem Rechner zu erstellen, die all das abdeckt, was moderne Betriebssysteme bereitstellen. Mit 20.000 Zeilen Code ist eine Größe erreicht, die einem 400 Seiten-Buch entspricht. Ein Umfang, der von einem Menschen in wenigen Wochen vollständig erfassbar und verdaubar ist.&lt;br /&gt;&lt;br /&gt;Ich glaube, dass Piumarta mehr als Recht mit seinem Anliegen hat. Die Systeme, die wir heutzutage bauen, sind zu komplex. Es geht einfacher, es muss einfacher gehen. Piumarta selbst liefert in seinem Vortrag einige Beispiele dazu. Wir müssen lernen Systeme zu bauen, die einfach und klein im Kern sind, damit einfach verstehbar sind, und skalieren. Erst damit schaffen wir die Grundlage für Systeme, die vielleicht irgendwann auch einmal einfach bedienbar sind und sich zuschneiden lassen auf die Bedürfnisse ganz spezieller Nutzergruppen. &lt;br /&gt;&lt;br /&gt;Wer sich für solche Überlegungen interessiert, dem sei der oben verlinkte Vortrag ans Herz gelegt. Über das zugrunde liegende Objektsystem habe ich schon einmal berichtet im Beitrag "&lt;a href="http://denkspuren.blogspot.com/2007/03/open-reusable-object-models-in-python.html"&gt;'Open, reusable object models' in Python&lt;/a&gt;". Mehr an solchen radikalen Überlegungen lassen sich beim &lt;a href="http://www.vpri.org"&gt;Viewpoint Research Institute&lt;/a&gt; unter "&lt;a href="http://www.vpri.org/html/writings.htm"&gt;Fundamental New Computer Technologies&lt;/a&gt;" finden. Geistiger Urheber vieler dieser Gedanken ist übrigens &lt;a href="http://en.wikipedia.org/wiki/Alan_Kay"&gt;Alan Kay&lt;/a&gt;, ein Urgestein der Informatik.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;Hinweis: &lt;a href="http://www.flickr.com/photos/kaptainkobold/382081834"&gt;Monster-Bild&lt;/a&gt; von &lt;a href="http://www.flickr.com/photos/kaptainkobold"&gt;Kaptain Kobold&lt;/a&gt;&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-3030557402197188687?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/3030557402197188687/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=3030557402197188687' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3030557402197188687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3030557402197188687'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/08/im-kampf-gegen-monstersysteme.html' title='Im Kampf gegen Monstersysteme'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_XJMaba79IKU/SJlbaxtlfEI/AAAAAAAAAFA/uZDVwGnYglk/s72-c/kaptainkobold.382081834.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-1982778827697518407</id><published>2008-07-10T13:52:00.005+02:00</published><updated>2008-07-10T14:17:53.244+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Typen'/><category scheme='http://www.blogger.com/atom/ns#' term='Scheme'/><category scheme='http://www.blogger.com/atom/ns#' term='Lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Typen in Wandlung: Das Paar, die Liste und der Stack</title><content type='html'>Ich habe meinen lieben HardCore-Informatik-Leser(inne)n schon lange keinen Programmcode mehr als Denkspur hinterlassen. Heute ist es mal wieder soweit. Zwei Punkte haben mich umgetrieben: (1) Die Fähigkeit von Objekten, ihren Typ zu verändern. (2) Der Vergleich von Liste und Stack.&lt;br /&gt;&lt;br /&gt;Es wird ein langes Posting werden, aber vielleicht haben Sie Lust auf diese kleine Denk-Reise. Ein wenig setze ich voraus, dass Sie sich mit Scheme/Lisp und dort mit den Datentypen der Liste und des Paars auskennen. Und was ein Stack ist, wissen Sie als Informatiker sowieso.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Einleitung&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Ein einfaches Beispiel mag die Idee von einem Objekt veranschaulichen, das seinen Typ ändern kann: Eine Ellipse ist beispielsweise über die Größe der Hauptachse und die Größe der Nebenachse eindeutig definiert. Sind Haupt- und Nebenachse gleich groß, dann haben wir einen Kreis, und die Unterscheidung in Haupt- und Nebenachse wird hinfällig; es genügt die Angabe eines Wertes, des Radius'. So kann ein sich veränderndes Ellipsen-Objekt zum Kreis-Objekt werden.&lt;br /&gt;&lt;br /&gt;Nachfolgend möchte ich anhand der Datenstrukturen von Liste und Paar (beide bilden die Grundlage der Programmiersprache Scheme) zeigen, dass die Typbestimmung und -anpassung zur Laufzeit eine reizvolle Technik ist, die elegant mit Objekt-Orientierung umgesetzt werden kann. In Scheme wird die Liste wie auch das Paar mit ein- und derselben Grundoperation erzeugt, der cons-Operation. Einzig und allein die Verwendung einer leeren Liste an einer bestimmten Stelle im Konstruktor entscheidet, ob das resultierende Objekt eine Liste oder ein Paar ist.&lt;br /&gt;&lt;br /&gt;Es zeigt sich aber auch ein schwerwiegendes Problem: Die OO-Lösung koppelt die Typen (Liste und Paar) in der Vererbungshierarchie über den Typen der leeren Liste miteinander. Das macht es andererseits unmöglich, die Liste wie einen Stack zu benutzen. Und das, obwohl Liste und Stack praktisch identisch sind. Ohne die Kopplung wäre das eine triviale Anpassung.&lt;br /&gt;&lt;br /&gt;Die dynamische Typauflösung verträgt sich nicht mit der Konstruktion eines durchgehenden objekt-orientierten Typsystems. Ich frage mich, ob diese Kopplung von Liste, Paar und leerer Liste nicht zwangsläufig zu Problemen im Typsystem führen muss. Handelt es sich hier gar um einen Designfehler in Scheme/Lisp? [Anbei: Ich würde mich freuen, Gedanken und Hinweise von Typ-Experten zu bekommen.]&lt;br /&gt;&lt;br /&gt;Bevor die Anwendung des Codes die Sachverhalte demonstrieren soll, bietet es&lt;br /&gt;sich an, den Python-Code durchzugehen.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Programmcode: EmptyList, Cons, Pair, List&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Die Codezeilen für __repr__ blasen den Code ein wenig auf. Ansonsten ist der Code schlank, er trägt alle Konzepte (EmptyList, List und Pair) explizit vor und nutzt Vererbung, um die Gemeinsamkeiten von List und Pair via Shared klar hervorzuheben. Die Klasse Cons dient dazu, die Typfestlegung erst durch den Gebrauch einer EmptyList() am "Ende" der Konstruktion via Cons möglich zu machen. Der Typ wird also, wenn man so möchte, dynamisch angepasst.&lt;br /&gt;&lt;br /&gt;Es sei bereits an dieser Stelle darauf hingewiesen, dass der Code für List und Pair zwar wunderbar symmetrisch aussieht, es im Kern aber nicht ist. List und EmptyList bilden eine Allianz gegen Pair, obwohl List und Pair als gleichberechtigte Partner in der Vererbungshierarchie auftauchen. Diese Asymmetrie ist für die Unmöglichkeit verantwortlich, warum List nicht mit Stack überein gebracht werden kann. Wir kommen darauf noch zurück.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class EmptyList(object):&lt;br /&gt;    def is_empty(self): return type(self) == EmptyList&lt;br /&gt;    def __repr__(self): return "()"&lt;br /&gt;&lt;br /&gt;class Cons(object):&lt;br /&gt;    def __new__(cls,car,cdr):&lt;br /&gt;        if type(cdr) in (List,EmptyList): return List(car,cdr)&lt;br /&gt;        return Pair(car,cdr)&lt;br /&gt;&lt;br /&gt;class Shared(EmptyList):&lt;br /&gt;    def __init__(self,car,cdr):&lt;br /&gt;        self._car, self._cdr = car, cdr&lt;br /&gt;    def car(self): return self._car&lt;br /&gt;    def cdr(self): return self._cdr&lt;br /&gt;    def __repr__(self):&lt;br /&gt;        return "(%s %s" % (self._car,self._cdr.__repr__()[1:])&lt;br /&gt;&lt;br /&gt;class List(Shared):&lt;br /&gt;    def __init__(self,car,cdr):&lt;br /&gt;        assert type(cdr) in (List,EmptyList)&lt;br /&gt;        Shared.__init__(self,car,cdr)&lt;br /&gt;    def __repr__(self):&lt;br /&gt;        if type(self._cdr) != List: # =&gt; type is EmptyList&lt;br /&gt;            return "(%s)" % self._car&lt;br /&gt;        return Shared.__repr__(self)&lt;br /&gt;        &lt;br /&gt;class Pair(Shared):&lt;br /&gt;    def __init__(self,car,cdr):&lt;br /&gt;        assert type(cdr) not in (List, EmptyList)&lt;br /&gt;        Shared.__init__(self,car,cdr)&lt;br /&gt;    def __repr__(self):&lt;br /&gt;        if type(self._cdr) != Pair:&lt;br /&gt;            return "(%s . %s)" % (self._car, self._cdr)&lt;br /&gt;        return Shared.__repr__(self)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Programmcode: EmptyStack und Stack&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Vergleicht man den Aufbau des Stack mit dem der Liste, so fällt die absolute&lt;br /&gt;Gleichheit ins Auge. EmptyStack entspricht EmptyList, Stack entspricht List.&lt;br /&gt;Ich habe den Stack natürlich nicht ohne Absicht genau der gleichen Bauweise&lt;br /&gt;unterworfen. Es ist lediglich abzugleichen, dass oben bei der Liste via&lt;br /&gt;Shared Vererbung genutzt wird, um die gleichen Anteile von Pair und List&lt;br /&gt;zusammenzufassen.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class EmptyStack(object):&lt;br /&gt;    def push(self,element): return Stack(element,self)&lt;br /&gt;    def is_empty(self): return type(self) == EmptyStack&lt;br /&gt;    def __repr__(self): return "[]"&lt;br /&gt;&lt;br /&gt;class Stack(EmptyStack):&lt;br /&gt;    def __init__(self,ontop,bottom):&lt;br /&gt;        assert type(bottom) in (Stack,EmptyStack)&lt;br /&gt;        self.ontop, self.bottom = ontop, bottom&lt;br /&gt;    def top(self): return self.ontop&lt;br /&gt;    def pop(self): return self.bottom&lt;br /&gt;    def __repr__(self):&lt;br /&gt;        if type(self.bottom) != Stack: # =&gt; type is EmptyStack&lt;br /&gt;            return "[%s]" % self.ontop&lt;br /&gt;        return "[%s %s" % (self.ontop,self.bottom.__repr__()[1:])&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Diskussion&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Beginnen wir mit der leeren Liste. Sie können all das in einer interaktiven Python-Console ausprobieren.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt;&gt; EmptyList()&lt;br /&gt;()&lt;br /&gt;&gt;&gt;&gt; EmptyList().is_empty()&lt;br /&gt;True&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Paare können direkt erzeugt werden.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt;&gt; Pair(1,2)&lt;br /&gt;(1 . 2)&lt;br /&gt;&gt;&gt;&gt; Pair(1,2).is_empty()&lt;br /&gt;False&lt;br /&gt;&gt;&gt;&gt; Pair(Pair(1,2),Pair(3,4))&lt;br /&gt;((1 . 2) 3 . 4)&lt;br /&gt;&gt;&gt;&gt; Pair(Pair(1,2),Pair(3,4)).car()&lt;br /&gt;(1 . 2)&lt;br /&gt;&gt;&gt;&gt; Pair(Pair(1,2),Pair(3,4)).cdr()&lt;br /&gt;(3 . 4)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ein Paar darf in seinem cdr keine leere Liste beheimaten -- das Paar würde sonst zur Liste mutieren.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt;&gt; Pair(1,EmptyList())&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;    ...&lt;br /&gt;AssertionError&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Listen können direkt erzeugt werden. Im Konstruktor wird strikt eingefordert, dass der cdr selbst eine Liste oder eine EmptyList ist.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt;&gt; List(1,2)&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;    ...&lt;br /&gt;AssertionError&lt;br /&gt;&gt;&gt;&gt; l1 = List(1,EmptyList())&lt;br /&gt;&gt;&gt;&gt; l1&lt;br /&gt;(1)&lt;br /&gt;&gt;&gt;&gt; l1.is_empty()&lt;br /&gt;False&lt;br /&gt;&gt;&gt;&gt; l2 = List(1,List(2,EmptyList()))&lt;br /&gt;&gt;&gt;&gt; l2&lt;br /&gt;(1 2)&lt;br /&gt;&gt;&gt;&gt; List(l1,List(3,l2))&lt;br /&gt;((1) 3 1 2)&lt;br /&gt;&gt;&gt;&gt; List(3,List(l2,EmptyList()))&lt;br /&gt;(3 (1 2))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Die Klassen List und Pair erzwingen ein vorheriges Festlegen auf einen Typen. Mittels Cons kann in gewohnter Lisp-Manier der Konstruktor bemüht werden. Abhängig vom cdr wird der entsprechende Typ (Liste oder Paar) automatisch erzeugt. Ein Punkt im Ausgabestring gibt wie zuvor an, ob es sich um ein Paar handelt oder nicht.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt;&gt; Cons(1,2)&lt;br /&gt;(1 . 2)&lt;br /&gt;&gt;&gt;&gt; Cons(1,EmptyList())&lt;br /&gt;(1)&lt;br /&gt;&gt;&gt;&gt; Cons(1,Cons(2,Cons(3,EmptyList())))&lt;br /&gt;(1 2 3)&lt;br /&gt;&gt;&gt;&gt; Cons(1,Cons(2,Cons(3,4)))&lt;br /&gt;(1 2 3 . 4)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Car und cdr arbeiten natürlich wie Lisp/Scheme.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt;&gt; Cons(1,2).car()&lt;br /&gt;1&lt;br /&gt;&gt;&gt;&gt; Cons(1,2).cdr()&lt;br /&gt;2&lt;br /&gt;&gt;&gt;&gt; Cons(1,Cons(2,Cons(3,EmptyList()))).car()&lt;br /&gt;1&lt;br /&gt;&gt;&gt;&gt; Cons(1,Cons(2,Cons(3,EmptyList()))).cdr()&lt;br /&gt;(2 3)&lt;br /&gt;&gt;&gt;&gt; Cons(1,Cons(2,Cons(3,EmptyList()))).cdr().car()&lt;br /&gt;2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Kommen wir zum Stack, der -- wenn man möchte -- wie eine Liste aufgesetzt werden kann. Ich habe die Beispiele zur Liste hier übernommen. Ersetzt man gedanklich die vormals runden Klammern durch eckige, dann kommt exakt dasselbe raus. Wen wundert's, da doch der Code praktisch dergleiche ist?!&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt;&gt; EmptyStack()&lt;br /&gt;[]&lt;br /&gt;&gt;&gt;&gt; EmptyStack().is_empty()&lt;br /&gt;True&lt;br /&gt;&gt;&gt;&gt; Stack(1,2)&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;    ...&lt;br /&gt;AssertionError&lt;br /&gt;&gt;&gt;&gt; s1 = Stack(1,EmptyStack())&lt;br /&gt;&gt;&gt;&gt; s1&lt;br /&gt;[1]&lt;br /&gt;&gt;&gt;&gt; s1.is_empty()&lt;br /&gt;False&lt;br /&gt;&gt;&gt;&gt; s2 = Stack(1,Stack(2,EmptyStack()))&lt;br /&gt;&gt;&gt;&gt; s2&lt;br /&gt;[1 2]&lt;br /&gt;&gt;&gt;&gt; Stack(s1,Stack(3,s2))&lt;br /&gt;[[1] 3 1 2]&lt;br /&gt;&gt;&gt;&gt; Stack(3,Stack(s2,EmptyStack()))&lt;br /&gt;[3 [1 2]]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Der Unterschied zwischen einer Liste und einem Stack besteht jedoch im grundsätzlichen Gebrauch. In Scheme/Lisp kann eine Liste ausschließlich über den Konstruktor cons erzeugt werden (wir lassen set-car! und set-cdr! außen vor, wir bleiben rein funktional).&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt;&gt; l = Cons(1,Cons(2,EmptyList()))&lt;br /&gt;&gt;&gt;&gt; l&lt;br /&gt;(1 2)&lt;br /&gt;&gt;&gt;&gt; l.car()&lt;br /&gt;1&lt;br /&gt;&gt;&gt;&gt; l.cdr()&lt;br /&gt;(2)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ein Stack hingegen wird ausgehend vom EmptyStack über push-Operationen gefüllt.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt;&gt; s = EmptyStack().push(2).push(1)&lt;br /&gt;&gt;&gt;&gt; s&lt;br /&gt;[1 2]&lt;br /&gt;&gt;&gt;&gt; s.top()&lt;br /&gt;1&lt;br /&gt;&gt;&gt;&gt; s.pop()&lt;br /&gt;[2]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Schaut man in die Umsetzung der push-Operation, so verbirgt sie nur den Konstruktor-Aufruf, der im Hintergrund ausgeführt wird.&lt;br /&gt;&lt;br /&gt;Im Grunde können die Liste und der Stack als vollkommen gleichwertige Datenstrukturen aufgefasst werden. Für eine Liste gälte es lediglich, eine der Push-Operation entsprechende Methode hinzuzufügen, die man "add" oder besser noch "prefix" nennen könnte. (Das "prefix" scheint mir als Gegenentwurf zu "append" gut zu passen, da die Liste ja sozusagen nach vorne wächst und nicht über Anhängsel erweitert wird.) Den Stack könnte man analog den Aufbau über eine Konstruktor-Funktion erlauben, wie hier schon geschehen. Das sind, wenn man so möchte, Details, die es anzugleichen gilt. Liste gleich Stack, Stack gleich Liste.&lt;br /&gt;&lt;br /&gt;Im Scheme/Lisp-Kontext ist das jedoch nicht ganz korrekt. Und das hat mit dem Pair-Typen zu tun. Das Pair bringt einen neuen Twist in die Angelegenheit.&lt;br /&gt;&lt;br /&gt;Da bei Pair im cdr jedes beliebige Element stehen kann außer EmptyList und List, verbietet sich die Möglichkeit, von einem Ausgangselement (z.B. der Zahl 7) via push bzw. prefix ein Pair zu konstruieren! Denn das hieße, dass jeder Objekttyp (Zahl, String, Boolean etc.) diese push/prefix-Operation anbieten müsste. EmptyList könnte eine solche Operation für die Konstruktion von Listen anbieten. Dort passt die Operation logisch hin. Aber warum um alles in der Welt sollte eine 7 ein push kennen und realisieren. In OO-Denke hieße das, dass der Typ an der Spitze des Typsystem eine push-Operation anbieten muss, von dem alle anderen Typen erben. Damit wäre allen Objekten im System die Grundmöglichkeit gegeben, sich via push in einen Container namens Pair zu verfrachten. Ein eigenartiges Typsystem wäre das.&lt;br /&gt;&lt;br /&gt;Aus dieser Problematik heraus hat man natürlich das push/prefix bei Scheme nicht im Angebot. Der minimalen Asymmetrie im nicht gleichen Umgang mit EmptyList durch Pair und List ist es geschuldet, dass Listen nicht dasselbe Interface wie Stacks anbieten und damit in letzter Konsequenz auch nicht als solche zu gebrauchen sind.&lt;br /&gt;&lt;br /&gt;Man sieht die Folgen dieser Konzeption (der asymmetrischen Verschneidung von Listen und Paaren) auch im Python-Code. List und Pair erben von EmptyList über den Zwischenschritt von Shared. Ergo kennen beide die Operation is_empty(). Tatsächlich ist ein is_empty() für Pairs vollkommen überflüssig, da die Anfrage an den falschen Typen adressiert wird. Ein Pair kann niemals empty sein! Genauso wenig, wie eine Zahl jemals empty sein kann.&lt;br /&gt;&lt;br /&gt;Ich finde es verwunderlich, dass man bei List, Pair und EmptyList im Grunde kein konsistentes OO-Typgebäude errichten kann, was dem "gefühlten" Zusammenhang von Pair, List und EmptyList gerecht wird _und_ offen bleibt für Erweiterungen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-1982778827697518407?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/1982778827697518407/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=1982778827697518407' title='4 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1982778827697518407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1982778827697518407'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/07/typen-in-wandlung-das-paar-die-liste.html' title='Typen in Wandlung: Das Paar, die Liste und der Stack'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-3330318076311576663</id><published>2008-07-07T17:14:00.004+02:00</published><updated>2008-07-07T17:23:08.087+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='interview'/><title type='text'>17 Fragen</title><content type='html'>Marc Scheloske, der Betreiber des Wissenschafts-Cafes, hat mit mir ein Interview geführt. Marc macht diese Interviews seit einiger Zeit mit den unterschiedlichsten Bloggern und stellt seinen Interview-Partnern 17 Fragen. &lt;a href="http://www.wissenschafts-cafe.net/blogportal/2008/07/17-fragen-an-dominikus-herzberg-von-denkspuren/"&gt;Viel Spaß beim Lesen!&lt;/a&gt; Und halten Sie sich mal eine Weile im Wissenschafts-Cafe auf, ich könnte mir vorstellen, dass es Ihnen dort gefällt!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-3330318076311576663?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/3330318076311576663/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=3330318076311576663' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3330318076311576663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3330318076311576663'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/07/17-fragen.html' title='17 Fragen'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-1729853775738291959</id><published>2008-06-24T11:48:00.002+02:00</published><updated>2008-06-24T11:52:56.306+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UML'/><category scheme='http://www.blogger.com/atom/ns#' term='Service'/><category scheme='http://www.blogger.com/atom/ns#' term='POJO'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='Komponente'/><title type='text'>Komponenten-Orientierung: Service vs. Funktionsbaustein</title><content type='html'>Wenn man sich mit Komponenten-Orientierung befasst, wird man feststellen, dass es zwei "Schulen" gibt, die etwas unterschiedliche Sichten auf den Komponenten-Begriff haben. Die eine Denkschule hat die Enterprise Applications vor Augen. Bei den Unternehmensanwendungen stehen Themen wie Persistenz, Transaktionen, Verteilung, Webservices etc. im Vordergrund. Im Systems Engieering dominieren hingegen Gesichtspunkte der Modularisierung und Komposition.&lt;br /&gt;&lt;br /&gt;Für einen Systems Engieer kann jede Software-Komponente grundsätzlich auch durch einen funktionsgleichen Baustein aus Hardware ersetzt werden -- und umgekehrt. Für Enterprise-Entwickler wird eine Komponente als Software-Einheit gesehen, die vielmehr einen Service realisiert, der zur Erfüllung definierter Aufgaben herangezogen werden kann. Der Systems Engineer baut Systeme, die er aus Komponenten und Subsystemen zusammensetzt. Der Enterprise-Entwickler baut Netze von Mehrwertdiensten, die aus der Kollaboration (möglicherweise transparent verteilter) mehrerer Services entstehen.&lt;br /&gt;&lt;br /&gt;So erklärt sich auch, dass in der Enterprise-Welt etwa im Java Kontext die Plain Old Java Objects (POJOs) als Basis für eine Komponente vollauf genügen. Vom Entwickler wird lediglich gefordert, seine POJOs so weit als möglich nur gegen Interfaces zu programmieren. Komponenten-Frameworks wie Spring erledigen dann den Rest. Sie kümmern sich um die Verschaltung von Komponenten, um das Lifecycle-Management und bieten einfache Anbindungen an andere Service-Komponenten, die Persistenz, Zugriffssteuerung etc. ermöglichen.&lt;br /&gt;&lt;br /&gt;Systems Engineers benötigen einen konzeptionellen Überbau, wenn Software-Einheiten als Komponenten fungieren sollen. Denn die meisten objekt-orientierten Programmiersprachen bieten keine Komposition an. Objekte lassen sich via Referenzen zwar zu Kollaborationsnetzen verschalten (die Denke der Enterpriseler), nicht jedoch zu Kompositionsbeziehungen. Eine Komponente ist ein Container, der andere Komponenten kapselt und verwaltet. In der Kommunikation zwischen Komponenten arbeiten Systems Engineers typischerweise mit Nachrichten, nicht mit Methoden-Aufrufen. Methoden-Aufrufe sind zu software-spezifisch; Nachrichten taugen in einem Harware- wie auch in einem Software-Umfeld zur Kommunikation. Sie machen alle Kommunikation per se asynchron und frei von impliziten Objekt-Referenzen.&lt;br /&gt;&lt;br /&gt;Es ist wichtig, von dieser Unterscheidung zu wissen. Die UML 2 bietet beiden "Schulen" Möglichkeiten zur Modellierung von Komponenten an. Nur kümmert sich die UML nicht darum, den Werkzeugkasten zur Modellierung in die Fächer "Service-Komponenten" und "Komponenten als Funktionsbausteine" zu zerlegen. Darum muss sich der Modellierer selber kümmern.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-1729853775738291959?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/1729853775738291959/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=1729853775738291959' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1729853775738291959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1729853775738291959'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/06/komponenten-orientierung-service-vs.html' title='Komponenten-Orientierung: Service vs. Funktionsbaustein'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-7252384042124747839</id><published>2008-06-18T19:35:00.004+02:00</published><updated>2008-06-18T19:55:35.129+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Interfaces'/><title type='text'>Alles ist ein Eingabegerät</title><content type='html'>Ich weiß, ich bin spät dran, wenn schon Spiegel-Online darüber berichtet in "&lt;a href="http://www.spiegel.de/netzwelt/tech/0,1518,560116,00.html"&gt;Massenmordversuch an der Maus&lt;/a&gt;" (Christian Stöcker, 18. Juni 2008). Aber diese Idee ist so schön und abgefahren, das muss man sich ansehen -- ich habe ein Faible für solche Ideen (siehe auch "&lt;a href="http://denkspuren.blogspot.com/2008/03/sichtweisen-in-3d-balance-halten.html"&gt;Sichtweisen in 3D: Balance halten&lt;/a&gt;"). Genug der Worte. Nehmen Sie eine Flasche, einen Tacker, einen Stift, Ihren Fingerverband, was auch immer ... oder eine Maus, und legen Sie los:&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/v0srY37kkMw"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/v0srY37kkMw" type="application/x-shockwave-flash" wmode="transparent" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Ärgern Sie sich auch darüber, weder selbst darauf gekommen zu sein, noch -- falls Sie die Idee hatten -- es umgesetzt zu haben?&lt;br /&gt;&lt;br /&gt;Was könnte man damit alles machen? Haben Sie Ideen?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-7252384042124747839?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/7252384042124747839/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=7252384042124747839' title='5 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/7252384042124747839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/7252384042124747839'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/06/alles-ist-ein-eingabegert.html' title='Alles ist ein Eingabegerät'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-8399055247225992678</id><published>2008-06-13T14:45:00.000+02:00</published><updated>2008-06-13T14:46:36.901+02:00</updated><title type='text'>Von der falschen Rede</title><content type='html'>Eine kleine Anekdote: In der Vorlesung zu den Grundlagen der Informatik sprach ich heute von Rekursion und Iteration. Ich erklärte, was Rekursion ist. Die Studierenden merkten auf und unterbrachen mich: "Sie meinen Rekursion!". "Wie bitte? Habe ich etwas anderes gesagt?" "Ja, sie sagten Iteration." "Oh sorry, ich meinte Rekursion." Da hatte mir mein Hirn einen Streich gespielt, der mir vollkommen unbemerkt blieb. Ich glaubte mich etwas sagen zu hören, was ich nicht gesagt hatte. Kennen Sie das? Haben Sie bestimmt auch schon einmal erlebt.&lt;br /&gt;&lt;br /&gt;Also startete ich einen neuen Versuch "Rekursion ist, wenn sich die Funktion selber wieder aufruft." Und schoss die Frage hinterher: "Habe ich Rekursion gesagt?" "Ja", lautete die Antwort unisono.&lt;br /&gt;&lt;br /&gt;Während ich weiter sprach, blieben meine Gedanken an der letzten Frage hängen: Irgendwie war die Frage dumm gewesen. Stellen Sie sich einmal vor, das wäre nur mein Gedanke, meine Sprachabsicht gewesen. Tatsächlich hätte ich aber (fälschlicherweise) gesagt: "Iteration ist, wenn sich die Funktion selber wieder aufruft". Und meine Frage wäre mir ebenso falsch über die Lippen gekommen "Habe ich Iteration gesagt?". Dann wäre die Antwort der Studierenden mit "Ja" ebenso korrekt gewesen. Sprich, meine Nachfrage "Habe ich Rekursion gesagt?" war vollkommen unsinnig und überflüssig. Zumindest aus einer logischen Betrachtungsweise. Wenn mein Hirn mir einen Streich spielt und mir meine gedachten Worte unbemerkt mit der Lautbildung eines anderen Wortes über die Lippen kommen, dann bin ich chancenlos. Oder?&lt;br /&gt;&lt;br /&gt;In der Tat bin ich das, wenn mein Gehör die Rede anderer ebenso konsistent falsch hört. Die eigene Rede ist davon ausgenommen, da das Ohr bezüglich der eigenen Rede extrem voreingenommen ist. Es weiß ja, was es hören soll -- und das verführt zu einer gewissen Nachlässigkeit. Also muss das Sprechen und das Hören zeitlich entzerrt werden. Ich muss aktiv Feedback einholen. Und solange die Anteile zur Sprachbildung und Spracherkennung nicht über den gleichen Fehler gekoppelt sind, dann sind Abweichungen erkennbar, wenn man das richtige Feedback einfordert.&lt;br /&gt;&lt;br /&gt;Wie hätte nach meiner Erläuterung der Rekursion die Nachfrage lauten sollen? Richtig: "Wie nennt man den Prozess des Selbstaufrufs einer Funktion." Die Studis hätten "Rekursion" gesagt und ich hätte eine Chance zur Fehlererkennung gehabt, da mein Sprechen das Wort nicht wieder falsch einbringen konnte.&lt;br /&gt;&lt;br /&gt;Die Moral von der Geschicht? Stellen Sie niemals Ja/Nein-Fragen, wenn Sie Ihren Geisteszustand überprüfen wollen. Oder, um den Bezug zum Software Engineering herzustellen: Stellen Sie einem Kunden, wenn Sie z.B. Anforderungen erheben wollen, möglichst keine Ja/Nein-Fragen. Ja/Nein-Fragen erhöhen das Risiko, dass Sie eigene Inkonsistenzen oder ein irrtümliches Verständnis nicht aufdecken.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-8399055247225992678?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/8399055247225992678/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=8399055247225992678' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/8399055247225992678'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/8399055247225992678'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/06/von-der-falschen-rede.html' title='Von der falschen Rede'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-293478323998857833</id><published>2008-05-27T14:42:00.002+02:00</published><updated>2008-05-27T14:53:08.088+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Team'/><category scheme='http://www.blogger.com/atom/ns#' term='Projekt'/><category scheme='http://www.blogger.com/atom/ns#' term='Projektmanagement'/><category scheme='http://www.blogger.com/atom/ns#' term='Teamarbeit'/><title type='text'>Tipps zur Teamarbeit</title><content type='html'>Ein (Projekt-)Team ist ein Gruppe von Menschen, an die eine Herausforderung oder eine Aufgabe herangetragen wird und von der man die zielgerichtete Bewältigung der Herausforderung erwartet. Oft geschieht das unter Randbedingung wie begrenzten Geldmitteln und Zeitbeschränkungen. Die Teammitglieder sind außerdem gegenseitig voneinander abhängig, um die Herausforderung bewältigen zu können.&lt;br /&gt;&lt;br /&gt;Arbeitsteilung und Spezialisierung sind die Wunderwaffen der Teamarbeit. Ein gutes Team bewältigt eine Herausforderung schneller als ein schlechtes Team. Ein gutes Team teilt die Arbeit besser auf und bildet bessere Experten aus als ein schlechtes Team. Ein gutes Team schafft schneller oder mehr. Nachfolgend ein paar Tipps, die Ihnen helfen sollen, gute und effektive Teamarbeit zu leisten.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Definieren Sie eine Teamleitung.&lt;/b&gt; Machen Sie eine Person zu Ihrer Teamleitung und übertragen Sie ihr die Verantwortung zur Koordination des Teams. Im Zweifel hat die Teamleitung das Recht Entscheidungen zu treffen, damit eine Handlungsunfähigkeit mangels Entscheidung aufgelöst werden kann. Die Teamleitung trägt die Verantwortung für das Team und damit auch für das Ergebnis.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Nutzen Sie Ihre Stärken -- oder machen Sie sich stark.&lt;/b&gt; Teilen Sie sich die Arbeit gemäß den Spezialisierungen im Team auf und/oder nutzen Sie die Arbeitsteilung, um einzelne Personen zu Experten werden zu lassen. Klären Sie, wer welche Kompetenzen und Interessen mitbringt. Nutzen Sie die Stärken und Talente eines jeden Teammitglieds. Oder bauen Sie Stärken auf.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Keine Aufgabe, die nicht zielführend ist.&lt;/b&gt; Fragen Sie sich bei jeder Aufgabe, warum diese Aufgabe sein muss. Eine Aufgabe ist dann überflüssig, wenn auch ohne sie ein Erfolg denkbar ist.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Keine Aufgabe ohne ein klar definiertes Ergebnis.&lt;/b&gt; Das Ergebnis ist dann klar definiert, wenn entscheidbar ist, wann die Aufgabe beendet ist. Beispiel: "Ich schau mir mal JavaScript an" ist kein definiertes Ergebnis, "Ich stelle eine Übersicht der Kontrollstrukturen von JavaScript zusammen" hingegen schon.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Keine Aufgabe ohne Klarstellung, für wen das Ergebnis ist.&lt;/b&gt; Betrachten Sie Ihre Aufgabe und das Ergebnis als Dienstleistung, als Service für den Empfänger des Ergebnisses. Betrachten Sie den Empfänger als Kunden – und machen Sie ihn glücklich! Denken Sie daran, dass Ihr Kunde von dem Ergebnis profitieren und nicht mehr Zeit als nötig zum Verarbeiten des Ergebnisses investieren möchte. Dennoch sind Quellen, Begründungen etc. anzugeben, denn die Plausibilität ihrer Ergebnisse muss im Zweifelsfall nachvollziehbar sein.&lt;br /&gt; &lt;br /&gt;&lt;b&gt;Keine Aufgabe, die länger als zwei Wochen benötigt.&lt;/b&gt; Die Zeitspanne von maximal zwei Wochen ist für viele Menschen ein guter Maßstab. "Kleine" Aufgaben sind psychologisch wichtig. Es zwingt außerdem dazu, eine Herausforderung in überschaubare Aufgabe runterzubrechen und erlaubt der Teamleitung ein besseres Nachhalten über den Stand der Dinge. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Keine Aufgabe ohne einen(!) Aufgaben-Verantwortlichen.&lt;/b&gt; Wer treibt eine Aufgabe voran, wer kümmert sich darum, dass sie in Angriff genommen wird, wer hält den Arbeitsforschritt nach, wer meldet rechtzeitig Probleme, wer erklärt eine Aufgabe für erledigt? Der Verantwortliche bzw. die Verantwortliche erntet Ruhm wie auch Tadel. Bei kleinen Aufgaben fallen die Rollen zusammen: dann ist eine Person sowohl Aufgaben-Verantwortliche als auch Ausführende. Bei größeren Aufgaben mag man sich die Arbeit teilen, die Verantwortung jedoch nicht. Denn: Verantwortung ist nicht teilbar!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Lernen Sie, auf das Ende einer Aufgabe hinzuarbeiten&lt;/b&gt; -- alles andere ist uninteressant. Nehmen wir an, Sie haben die Aufgabe, die Kontrollstrukturen von JavaScript in einer Übersicht zusammenzustellen. Diese Aufgabe ist schnell erledigt, Sie bedarf vielleicht gerade einer halben Stunde, selbst wenn Sie als Informatik-Student noch nie mit JavaScript Kontakt hatten. Natürlich ist es verführerisch, im Web Links zu JavaScript zu verfolgen und vieles Interessantes über die Sprache in Erfahrung zu bringen; ergebnisorientiert ist das nicht.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Definieren Sie Zeiten zur thematischen Orientierung und zum zielorientierten Kompetenzaufbau.&lt;/b&gt; Wir sind Menschen, wir können nicht andauernd in Ergebnissen arbeiten und denken. Wir benötigen Zeiten, um uns zu orientieren oder um Kompetenzen aufzubauen, ohne uns dem Druck und dem Stress von Zielen und Ergebnissen unterwerfen zu müssen. Diese Zeiten sind notwendig um (a) überhaupt Ergebnisse und Ziele definieren zu können (Orientierung) und um (b) in die Lage versetzt zu werden, sich Ergebnisse erarbeiten zu können (Kompetenzaufbau). Aber begrenzen Sie diese Zeiten und vereinbaren Sie sich auf ein Thema. Und: Das Thema muss zielführend sein. Beachten Sie, dass sich Kompetenzen in der Regel anhand konkreter Aufgaben aufbauen lassen. Themenarbeit endet mit einem kurzen Tätigkeits- und Erkenntnisbericht an das Team, schließlich ist auch der Lern- oder Orientierungsprozess für das Team von Interesse.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Keine Person im Team ohne aktuelle Aufgabe oder Themenzeit.&lt;/b&gt; Sobald eine Person gar nichts tut und etwa einer anderen Person bei der Arbeit zuschaut (gerne maskiert unter "Wir arbeiten zusammen."), läuft irgendetwas schief mit der Teamarbeit. Es kann an mangelnder Koordination bzw. Kommunikation des Teams liegen. Möglicherweise sind aber auch einfach zu viele Personen in einem Team, mehr, als die Aufgabe hergibt.&lt;br /&gt; &lt;br /&gt;&lt;b&gt;Arbeiten Sie allein.&lt;/b&gt; Sobald mehr als eine Person das Gleiche tut, findet keine Arbeitsteilung mehr statt. Teamarbeit schließt gemeinsames Arbeiten zur gleichen Zeit in einer gemeinsamen Umgebung nicht aus, aber sie verfehlt ihr Ziel, wenn zwei oder mehr Personen grundlos das Gleiche tun. (Auch hier ist die Maskierung "Wir arbeiten zusammen." nicht selten.) Es ist eine der größten Herausforderungen, die Teamarbeit mit sich bringt: alleine arbeiten zu können. Es sind typische Verhaltensmuster von Unsicherheit und Flucht vor der Herausforderung, die Menschen dazu bewegen, mit jemand anderem an der gleichen Aufgabe zusammen arbeiten zu wollen. Auch wenn es paradox zu sein scheint: Teamfähigkeit heißt, weite Strecken über autonom arbeiten zu können. Anders ist Teamarbeit z.B. über das Web in Form von remote collaboration gar nicht möglich.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Definieren Sie regelmäßige, kurze Treffen zur Koordination.&lt;/b&gt; Die Arbeiten müssen regelmäßig unter allen Teammitgliedern abgestimmt werden, wobei Anwesenheit (physisch oder virtuell) mehr als sinnvoll ist. Solche Treffen sind kurz zu halten, da diese Zeiten keine Produktivzeiten sind.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Schaffen Sie Möglichkeiten zur Kommunikation.&lt;/b&gt; Menschen in einem Team müssen kommunizieren, um eine Identität als Gruppe entwickeln zu können -- und das gilt es gezielt zu kultivieren. Zum Beispiel durch Kommunikationsecken (die berühmte Ecke oder Küche mit der Kaffeemaschine), gemeinsame Arbeitsräume, gemeinsame Mittagessen, Mailing-Listen, Diskussionsforen, Chat-Rooms etc.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Schaffen Sie sich Zeitblöcke zur ungestörten, konzentrierten Arbeit.&lt;/b&gt; Ob Sie an einer Aufgabe arbeiten oder mit einem Themenblock beschäftigt sind, Sie brauchen Zeitblöcke von 1 1/2 bis 4 Stunden, um produktive Arbeit leisten zu können. In dieser Zeit sollten sie ungestört sein und auch für Ihre Teammitglieder nicht zur Verfügung stehen.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Zusammenfassung&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Teamarbeit ist Arbeitsteilung -- was wörtlich zu nehmen ist: Sie teilen sich die Arbeit. In aller Regel wird mit der Arbeitsteilung eine Spezialisierung einhergehen. Sie arbeiten meist ergebnisorientiert, gelegentlich themenbezogen. Eine Aufgabe ist zeitlich klar begrenzt und hat ein definiertes Ergebnis. Es gibt einen Aufgaben-Verantwortlichen und eine Person bzw. Personengruppe, für die das Resultat der Aufgabe von Nutzen ist. Die Aufbereitung des Resultats sollte an der Zielgruppe ausgerichtet sein. Themenarbeit ist ebenfalls zeitlich klar begrenzt, zielorientiert und endet mit einem Bericht ans Team.&lt;br /&gt;&lt;br /&gt;Übrigens sollte ein Team nicht aus zu vielen Personen bestehen. Jenseits von elf, zwölf Personen bilden sich automatisch Untergruppen heraus, die ein Team in wenig gut steuerbare Einheiten zerfallen lassen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-293478323998857833?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/293478323998857833/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=293478323998857833' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/293478323998857833'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/293478323998857833'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/05/tipps-zur-teamarbeit.html' title='Tipps zur Teamarbeit'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-3624096659089643657</id><published>2008-05-21T13:07:00.001+02:00</published><updated>2008-05-21T13:11:40.864+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bootstrapping'/><category scheme='http://www.blogger.com/atom/ns#' term='philosophie'/><category scheme='http://www.blogger.com/atom/ns#' term='informatik'/><title type='text'>Informatik als angewandte Philosophie</title><content type='html'>Was war zuerst: Die Henne oder das Ei? Oder setzen wir noch früher an: Was bitte ist ein Ei, was genau ein Huhn? Informatiker setzen sich auf ihre eigene Art und Weise mit solchen Fragen auseinander -- eigentlich sogar tagtäglich. Zwar sprechen sie selten von Hühnern oder Eiern, aber sie haben Antworten zu bieten. &lt;br /&gt;&lt;br /&gt;Wollen Sie auch erfahren, was Informatiker so gedankenverloren in den Kaffee schauen lässt und warum Milchtüten eine echte Herausforderung sind?&lt;br /&gt;&lt;br /&gt;Dann möchte ich Sie herzlich einladen zu meinem Vortrag "Informatik als Angewandte Philosophie: Gedanken über Bits und Bytes" am Dienstag, 3. Juni 2008, um 17:30 Uhr bis 19 Uhr. Der Vortrag findet statt im Rahmen der Ringvorlesung "Mensch-Umwelt-Zukunft" an der &lt;a href="http://www.hs-heilbronn.de"&gt;Hochschule Heilbronn&lt;/a&gt; (Max-Planck-Str. 39) im Raum E010.&lt;br /&gt;&lt;br /&gt;Ich freue mich auf Ihren Besuch. Und wenn Sie Wünsche, Anregungen, Gedanken haben, zu denen Sie gerne etwas hören möchten, dann lassen Sie es mich wissen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-3624096659089643657?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/3624096659089643657/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=3624096659089643657' title='7 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3624096659089643657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3624096659089643657'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/05/informatik-als-angewandte-philosophie.html' title='Informatik als angewandte Philosophie'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-816170633312381636</id><published>2008-05-12T00:05:00.000+02:00</published><updated>2008-05-12T00:09:22.209+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Tamarin'/><category scheme='http://www.blogger.com/atom/ns#' term='ECMAScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Forth'/><category scheme='http://www.blogger.com/atom/ns#' term='Factor'/><category scheme='http://www.blogger.com/atom/ns#' term='SpiderMonkey'/><category scheme='http://www.blogger.com/atom/ns#' term='ActionMonkey'/><title type='text'>Forth gedacht: JavaScript 2</title><content type='html'>&lt;a href="http://en.wikipedia.org/wiki/Forth_(programming_language)"&gt;Forth&lt;/a&gt; ist eine der Programmiersprachen aus der Frühzeit der Informatik. Die Sprache entstand Anfang der 70er Jahre und wurde von Charles H. Moore erschaffen -- und sie hat bis heute überlebt. Sie ist stack-basiert, äußerst einfach aufgebaut, sie kann mühelos ohne Betriebssystem auskommen und ist beliebig erweiterbar. Die Programme sind schnell und äußerst kompakt, weshalb Forth gerade im Bereich der eingebetteten Systeme noch immer gerne genutzt wird. Und man kann mit Forth Programme interaktiv entwickeln; ein Vorteil, den man von interaktiven, dynamisch-typisierten Sprachen kennt. Was das spannende ist: Forth ist ein entscheidender Baustein im neuesten JavaScript 2 (&lt;a href="http://www.ecmascript.org/"&gt;ECMAScript 4&lt;/a&gt;) für den Mozilla-Browser Firefox 4.0. &lt;br /&gt;&lt;br /&gt;In der zukünftigen Generation des Firefox-Browsers 4.0 (ich spreche nicht von Firefox 3.0, der bald fertig gestellt sein wird) wollen die Mozilla-Entwickler das dann aktuelle JavaScript 2.0 auf einer Virtuellen Maschine (VM) mit JIT-Kompilierung (&lt;i&gt;just in time compilation&lt;/i&gt;) ausführen lassen. Im November 2006 erhielt die Mozilla-Organisation die dafür notwendige Technologie von Adobe Systems. Adobe spendete das etwa 135.000 Zeilen Code umfassende &lt;a href="http://en.wikipedia.org/wiki/Tamarin_%28JavaScript_engine%29"&gt;Tamarin&lt;/a&gt; an Mozilla. Tamarin ist der Name der VM, die Adobe seit Flash 9 für die Ausführung von ActionScript einsetzt. Derzeit läuft ein Projekt namens &lt;a href="http://wiki.mozilla.org/JavaScript:ActionMonkey"&gt;ActionMonkey&lt;/a&gt; bei Mozilla, das die aktuelle JavaScript-Implementierung für Firefox (&lt;a href="http://developer.mozilla.org/en/docs/SpiderMonkey"&gt;SpiderMonkey&lt;/a&gt;) und das &lt;a href="http://www.mozilla.org/projects/tamarin/"&gt;Tamarin-Projekt&lt;/a&gt; zusammenbringt.&lt;br /&gt;&lt;br /&gt;Der ByteCode von Tamarin wird in Files mit der Endung .abc abgelegt; sie sind das Analogon zu .class-Files für die Java VM. Der abc-ByteCode wird in Forth als Zwischensprache (Intermediate Language, IL) übersetzt. Für Forth gibt es dann einen C-Interpreter. Wer hier generell einen Einstieg finden möchte, dem sei der Blog "&lt;a href="http://masonchang.blogspot.com/"&gt;Hacking with Caffein&lt;/a&gt;" von Mason Chang empfohlen, insbesondere der Beitrag "&lt;a href="http://masonchang.blogspot.com/2008/03/tamarin-linking-forth-and-c.html"&gt;Getting started with Tamarin and Forth&lt;/a&gt;" (27. März 2008). Man darf gespannt sein, wie sich das ActionMonkey-Projekt machen wird und ob sich Forth als IL in der Virtuellen Maschine halten wird!&lt;br /&gt;&lt;br /&gt;Wer sich für ein modernes "Forth" interessiert, der sei auf &lt;a href="http://factorcode.org/"&gt;Factor&lt;/a&gt; verwiesen. Siehe dazu auch "&lt;a href="http://denkspuren.blogspot.com/2007/03/factor-in-der-krze-liegt-die-wrze.html"&gt;Factor: In der Kürze liegt die Würze&lt;/a&gt;".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-816170633312381636?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/816170633312381636/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=816170633312381636' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/816170633312381636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/816170633312381636'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/05/forth-gedacht-javascript-2.html' title='Forth gedacht: JavaScript 2'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-983641572494107560</id><published>2008-04-29T23:31:00.003+02:00</published><updated>2008-04-29T23:42:22.192+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Systemtheorie'/><category scheme='http://www.blogger.com/atom/ns#' term='Interfaces'/><category scheme='http://www.blogger.com/atom/ns#' term='Luhmann'/><category scheme='http://www.blogger.com/atom/ns#' term='Prozess'/><category scheme='http://www.blogger.com/atom/ns#' term='System'/><title type='text'>Was ist ein System?</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_XJMaba79IKU/SBeUtmmPtHI/AAAAAAAAADw/gJR24hZdbjU/s1600-h/UDR.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_XJMaba79IKU/SBeUtmmPtHI/AAAAAAAAADw/gJR24hZdbjU/s400/UDR.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5194784206371140722" /&gt;&lt;/a&gt;&lt;br /&gt;In der Informatik bleibt der Begriff des Systems seltsam unbesetzt. Begriffsprägungen aus der Elektrotechnik oder der Kybernetik lassen sich nicht so recht übertragen. Umso überraschender ist es, dass der Systembegriff des Soziologen Niklas Luhmann als Anregungsquelle taugt und sich überraschend gut mit Konzepten aus der Informatik füllen lässt. Hier ein Versuch interdisziplinärer Annäherung.&lt;br /&gt;&lt;br /&gt;Niklas Luhmann war ein Sozialwissenschaftler, er hatte 30 Jahre die Professur für Soziologie an der Universität Bielefeld inne und starb 1998 im Alter von 70 Jahren. Er gilt als einer der Begründer der soziologischen Systemtheorie. Sein Lebenswerk galt der Entwicklung einer "Theorie der Gesellschaft", die er über mehrere Veröffentlichungen hinweg entwarf. Sein Werk ist immens und hat einen bleibenden Einfluss zum Verständnis gesellschaftlicher Systeme hinterlassen.&lt;br /&gt;&lt;br /&gt;Luhmann interessierten soziale, psychische und biologische Systeme -- Systeme, die der Inbegriff des Lebendigen sind. Er nennt sie &lt;i&gt;autopoietische&lt;/i&gt;, sich selbst erschaffende Systeme. Technische Systeme sind keine Systeme, so Luhmann. Eine Abgrenzung, die ich problematisch finde. Ich habe den Eindruck, dass sich Systeme, wie sie die Informatik erschafft, deutlich näher an der Luhmann'schen Systemdefinition orientieren, als man es auf den ersten Blick glauben mag,&lt;br /&gt;&lt;br /&gt;Nach Luhmann definieren sich Systeme nicht aus Elementen und ihren Beziehungen. Das ist ein typisch technisches Systemverständnis, wie es besonders bei Ingenieuren sehr verbreitet ist. Systeme bestehen nicht aus Dingen oder Elementen, Systeme bestehen aus Operationen. Luhmann sagt: "Nur ein System kann operieren, und nur Operationen können ein System produzieren." (Zitat nach Berghaus 2004, S. 39). Durch das Operieren entsteht eine Differenz von System und Umwelt -- wir werden noch besprechen, was das meint. Ein System existiert nur, wenn es operiert. Einer Operation müssen weitere Operationen folgen bzw. folgen können. Das ist die Forderung nach der so genannten Anschlussfähigkeit eines Systems. Ein System muss sich also als operativ geschlossen darstellen. &lt;br /&gt;&lt;br /&gt;Durch sein Operieren bildet das System eine Differenz aus, es erschafft sich ein Inneres in Abgrenzung zu einem Äußeren. Dieses Äußere nennen wir die Umwelt des Systems. Entscheidend ist, dass es das System selbst ist, das diese Unterscheidung durch sein Operieren macht. Gleichzeitig bildet diese selbst erzeugte Grenzziehung auch die Grundlage des Systems, seine Umwelt beobachten zu können. Jede Beobachtung ist Unterscheidung, und jede Unterscheidung ist Beobachtung. Wer beobachtet, differenziert, grenzt ab, unterscheidet.&lt;br /&gt;&lt;br /&gt;Zu guter Letzt fordert Luhmann von Systemen die Fähigkeit zur Selbstreproduktion. Ein System muss selbst wieder etwas Operierendes hervorbringen können. Das ist die Autopoiesis eines Systems. Die Sprachwurzeln des Begriffs kommen aus dem Altgriechischen und sind leicht zu merken: "auto" wie in auto-matisch oder Auto-mobil heißt "selbst"; die "Poesie" ist im griechischem Wortsinne eine "Erschaffung". Autopoiesis ist also die "Selbsterschaffung".&lt;br /&gt;&lt;br /&gt;Ich möchte dieses Systemverständnis in Bezug auf soziale, psychische und biologische Systeme hier nicht ausbreiten, das würde zu weit führen. Wer sich genauer dafür interessiert, dem sei das Buch von Margot Berghaus empfohlen: "&lt;a href="http://www.utb.de/katalog_suchen_detailseite.jsp?buchid=1045"&gt;Luhmann leicht gemacht&lt;/a&gt;", Böhlau-Verlag, 2. Auflage, 2004. Von Luhmann selber ist die "&lt;a href="http://www.carl-auer.de/programm/978-3-89670-459-7"&gt;Einführung in die Systemtheorie&lt;/a&gt;", herausgegeben von Dirk Baecker, Carl-Auer-Verlag, 4. Auflage, 2008, für einen Laien einigermaßen verständlich.&lt;br /&gt;&lt;br /&gt;Fassen wir zusammen, was Luhmann als System definiert:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Ein System entsteht durch Operationen.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Einer Operation müssen Operationen folgen (können); sonst hört das System auf zu operieren, sprich zu existieren.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Durch die Operation wird eine Differenz, eine Unterscheidung erzeugt, durch die sich das System von einer Umwelt abgrenzt.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Die Differenzbildung begründet und beschränkt die Fähigkeit, die Umwelt beobachten zu können.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Systeme sind autopoietisch, d.h. sie können sich mit ihren Operationen selbst reproduzieren.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Das alles scheint schwer verständlich und kryptisch. Dennoch ist die Nähe zu Konzepten aus der Informatik auffällig. Starten wir einen Versuch, die Luhmann'sche Begriffswelt mit Informatik-Konzepten aufzuladen.&lt;br /&gt;&lt;br /&gt;Jedem Informatiker ist der Begriff der Operation vertraut. Eine Operation ist ein atomarer Verarbeitungsschritt. Ein Beispiel ist die Ausführung eines Maschinenbefehls.&lt;br /&gt;&lt;br /&gt;Um ein System durch Operationen entstehen zu lassen, muss eine Folge von Operationen irgendwann zu einer Operation führen, die bewirkt, dass es einen Rücksprung zu einer bereits ausgeführten Operation gibt. Der Fluss der Operationen muss zu einem Zirkelschluss führen, damit das System operativ bleibt. Denn nur durch andauerndes Operieren entsteht ein System. Wir wollen diesen geschlossenen Kreislauf von Operationen einen aktiven Prozess nennen. Den Begriff des Prozesses kennen sie zum Beispiel aus der Welt der Betriebssysteme.&lt;br /&gt;&lt;br /&gt;Die Operationen des aktiven Prozesses greifen notwendigerweise auf Speicherinhalte zu -- ansonsten passiert nichts Spannendes. Mit anderen Worten, ein aktiver Prozess ist mit einem endlichen Satz an Zuständen und Zustandswerten assoziiert. Darüber entsteht die Differenz zur Umwelt. Alles, was nicht zu den Operationen und zu dem Zustandsraum eines Prozesses gehört, ist die Außenwelt des Prozess-Systems. Der Zustandsraum ist sozusagen der verinnerlichte Teil einer Rechenwelt in den Grenzen eines abgeschlossenen Flusses von Operationen.&lt;br /&gt;&lt;br /&gt;Das schließt nicht aus, dass ein anderer Prozess ebenso dieselben Speicherinhalte bzw. Zustände verinnerlicht. Vielmehr sind diese geteilten Bereiche die einzige Möglichkeit zur Kommunikation von Prozessen untereinander. Die Veränderung des Werts einer gemeinsamen Speicherzelle ist Mitteilung einerseits und Beobachtung andererseits. Prozesse können auf diese Weise Informationen austauschen. Wir nennen solch eine geteilte Domäne eine Schnittstelle oder ein Interface. Ein Interface ist kein System!&lt;br /&gt;&lt;br /&gt;Wie Sie sehen, führt der abgeschlossene Fluss von Operationen zu einer Assoziation mit einem Speicherbereich und damit zu einer Abgrenzung vom Rest des Speichers. Teilen sich abgeschlossene Operationsflüsse Speicherbereiche, dann kann diese Gemeinsamkeit zur Kommunikation genutzt werden. Das alles ist in Einklang mit der Systemdefinition nach Luhmann!&lt;br /&gt;&lt;br /&gt;Prozesse können derart angelegt werden, dass sie sich selbst zu kopieren vermögen. Ist ihnen über eine Operation die Fähigkeit gegeben, einen separaten Fluss von Operationen auf der Kopie in Gang zu setzen, dann hat sich das Prozess-System reproduziert! Prozesse können, sofern sie eine Operation zur Initiierung eines eigenständigen Operationsflusses haben, als autopietisch bezeichnet werden.&lt;br /&gt;&lt;br /&gt;Das wird einem Luhmann und vielen anderen Systemtheoretikern sicher widerstreben. Denn Autopoiesis wird als auszeichnendes Merkmal lebender Systeme verstanden. Es scheint auch intuitiv nicht einleuchtend, ein Informatik-System als lebendig zu bezeichnen. Andererseits muss eine Definition des Lebendigen eine klare Aussage machen, was genau das Lebendige vom Nicht-Lebendigen unterscheidet, und dies in einer Weise tun, die durchaus auch den Raum lässt, von Menschenhand geschaffene Systeme eines Tages als lebendig zu klassifizieren.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-983641572494107560?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/983641572494107560/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=983641572494107560' title='4 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/983641572494107560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/983641572494107560'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/04/was-ist-ein-system.html' title='Was ist ein System?'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_XJMaba79IKU/SBeUtmmPtHI/AAAAAAAAADw/gJR24hZdbjU/s72-c/UDR.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-2435452539264336231</id><published>2008-04-15T17:50:00.003+02:00</published><updated>2009-02-28T13:13:41.296+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Lidl'/><title type='text'>Lidl und der Kassen-Bug</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_XJMaba79IKU/SATOwed1ViI/AAAAAAAAADo/XPHuvoqAy44/s1600-h/LidlBug.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_XJMaba79IKU/SATOwed1ViI/AAAAAAAAADo/XPHuvoqAy44/s400/LidlBug.jpg" alt="" id="BLOGGER_PHOTO_ID_5189500002844890658" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Es gibt Fehler, im Informatiker-Jargon "Bugs", die etwas anrühriges haben. Ich bat den Menschen an der Kasse bei Lidl um einen Moment Geduld und meine Kinder um Ruhe, um nicht den wunderbaren Moment zu verpassen, bei dem &lt;i&gt;es&lt;/i&gt; passierte. Der Lidl-Mensch fluchte kurz auf -- und ich war entzückt! "Einen Moment, davon muss ich ein Foto machen!" Und dann machte ich noch eines.&lt;br /&gt;&lt;br /&gt;Ich bin heute extra für diesen Fehler zu Lidl gepilgert -- ich wollte es mit eigenen Augen sehen. Gestern hat mir ein Student (vielen Dank Herr Breyer) von diesem Fehler in einer EMail berichtet. Ein richtig schöner Fehler, ein Klassiker geradezu. Ein Fehler, den man selten zu Gesicht bekommt, so einer mit Museumswert. Dafür wäre ich sogar noch weiter gereist als bis zum nächsten Lidl.&lt;br /&gt;&lt;br /&gt;Der Fehler tritt auf, wenn Sie an der Kasse Waren im Wert von 0 Euro (Null Euro) bezahlen. Dann streikt das System. Die kurze Einkaufsliste dazu: Geben Sie zwei Pfandflaschen zurück und Lidl steht mit 50 Cent bei Ihnen in der Kreide. Zu dem Pfandzettel, den Ihnen der Automat ausspuckt, besorgen Sie sich eine Wasserflasche (19 Cent plus 25 Cent Pfand macht 44 Cent) und begehen die Umweltsünde und greifen nach einer Einkaufstüte für 6 Cent. Ab zur Kasse damit. Minus 50 Cent plus 50 Cent machen 0 Cent bzw. 0 Euro. Rien ne va plus!&lt;br /&gt;&lt;br /&gt;Herrlich, die Kasse streikt und ruft nach "Autorisierung". Wie Sie auf dem rechten Bild sehen, hat die Schlange hinter mir gleich das Weite gesucht. "Das kommt so einmal im halben Jahr vor", erfuhr ich vom Kassierer.&lt;br /&gt;&lt;br /&gt;Ich habe im Netz einen Blogeintrag gefunden, der belegt, dass der Fehler mindestens seit Mitte November 2007 bekannt ist (Alphawinkel.de: "&lt;a href="http://www.alphawinkel.de/?p=22"&gt;Der tägliche Blödsinn: Lidl und die Kasse&lt;/a&gt;", 13. Nov. 2007). Vermutlich tritt der Fehler zu selten auf, als dass Lidl ein schnelles Bug-Fixing für nötig erachtet.&lt;br /&gt;&lt;br /&gt;Das Faszinierende jedoch ist, dass dieser Fehler überhaupt auftritt. Warum hat man bei der Programmierung des Kassensystems diesen einfachen Testfall übersehen? Haben Sie oben beim Lesen kurz gestockt, als ich schrieb&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Der Fehler tritt auf, wenn Sie an der Kasse Waren im Wert von 0 Euro (Null Euro) bezahlen.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Haben Sie für einen Moment gedacht "Wie soll das denn gehen"? Dann sind wir der Ursache schon auf der Spur. Wir selbst mit unseren eingefahrenen Denkmustern sind das Problem.&lt;br /&gt;&lt;br /&gt;Die Kunst des Testens ist, Grenzfälle möglich zu machen, nicht sie für unmöglich zu halten.&lt;br /&gt;&lt;br /&gt;[Nachtrag: Lesen Sie auch auf den Denkspuren: "&lt;a href="http://denkspuren.blogspot.com/2009/02/ist-der-kassen-bug-von-lidl-ein-bug.html"&gt;Ist der Kassen-Bug von Lidl ein Bug?&lt;/a&gt;"]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-2435452539264336231?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/2435452539264336231/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=2435452539264336231' title='49 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2435452539264336231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2435452539264336231'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/04/lidl-und-der-kassen-bug.html' title='Lidl und der Kassen-Bug'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_XJMaba79IKU/SATOwed1ViI/AAAAAAAAADo/XPHuvoqAy44/s72-c/LidlBug.jpg' height='72' width='72'/><thr:total>49</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-4883591429229003405</id><published>2008-04-15T11:34:00.003+02:00</published><updated>2008-04-15T11:49:45.038+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Projektmanagement'/><title type='text'>Kleinprojekte und ihre Kosten</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_XJMaba79IKU/SAR3Eud1VhI/AAAAAAAAADg/R7Bogi4EllU/s1600-h/ProjektFallStudie.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_XJMaba79IKU/SAR3Eud1VhI/AAAAAAAAADg/R7Bogi4EllU/s400/ProjektFallStudie.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5189403593713997330" /&gt;&lt;/a&gt;&lt;br /&gt;Was in Büchern zum Software-Projektmanagement gerne übergangen wird, sind die Kleinprojekte. Vielleicht, weil das Management von Kleinprojekten als trivial angesehen wird. Dabei sind es die Kleinprojekte, von denen es so zahllos viele gibt.&lt;br /&gt;&lt;br /&gt;Als Kleinprojekt definiere ich ein Vorhaben, das beim Auftragnehmer von ein bis fünf Personen abgewickelt wird, das wenige Wochen bis einige Monate dauert und in der Regel den Auftraggeber ein paar Tausend bis wenige Zehntausend Euro kostet.&lt;br /&gt;&lt;br /&gt;Das Tagesgeschäft von vielen Kleinunternehmen ist geprägt von Kleinprojekten. Freiberufler müssen sich immer wieder auf Kleinprojekte einlassen. Der Schritt in die Selbstständigkeit bedeutet für viele die Abwicklung unzähliger Kleinprojekte -- ein Leben von der Hand in den Mund mit geringen Gewinnspannen. Und viele Informatik-Studierende versuchen, sich mit Kleinprojekten (oder auch Kleinstprojekten) ein Zubrot zu verdienen. Grund genug, sich mit dieser Sorte von Projekten einmal genauer zu befassen.&lt;br /&gt;&lt;br /&gt;Diese Woche habe ich in der Projektmanagement-Vorlesung eine Fallstudie besprochen. Ein reales, kleines Softwareprojekt, an dem ich auch beteiligt war bzw. bin -- es steht kurz vor dem Abschluss. Ich habe dazu die Projekthistorie aufgerollt und mich dabei ausschließlich auf die spannende Phase &lt;i&gt;vor&lt;/i&gt; der eigentlichen Software-Entwicklung konzentriert, die ich hier Vor-Entwicklungsphase nenne. Es geht also um die Zeit, in der mit dem Kunden diskutiert, überlegt, gebrütet und gelöst wird -- bis man verstanden hat, worum es eigentlich geht und was entwickelt werden soll. Mögliche Resultate sind Anforderungsdokumente, Konzeptpapiere, Prototypen und ein Vertrag bzw. ein Auftrag zur eigentlichen Entwicklung, sprich zur Realisierung der ausgereiften Idee. Diese Phase ist mit Aufwendungen und mit Kosten verbunden. Wissen Sie, wie hoch die Kosten da liegen? Haben Sie eine ungefähre Vorstellung wie der Kostenverlauf über die Zeit aussieht und mit welchem Kostenverhältnis der Kunde rechnen darf?&lt;br /&gt;&lt;br /&gt;Zur Fallstudie. Damit Sie eine grobe Vorstellung haben, es geht inhaltlich um eine webbasierte Anwendung mit einer relationalen Datenbank dahinter. Technisch unspektakulär, etwas, was in aller Welt immer wieder entwickelt wird. Am Ende wird sich herausstellen, dass die Softwarekonzeption samt prototypischem Datenbankschema durch ein sechsseitiges Dokument ausreichend dokumentiert ist. Es handelt sich also tatsächlich um ein "richtiges" Kleinprojekt. Dennoch ist erstaunlich, welcher Aufwände es bedarf, um von dem Kundenanliegen zu dieser klaren Dokumentation zu gelangen.&lt;br /&gt;&lt;br /&gt;Ich habe Folgendes zur frühen Projektphase aufgelistet: Wann gab es Treffen, was war der Anlass, wer war vom Kunden, wer vom Auftragnehmer dabei? Und: Wann wurde ein Resultat (in der Regel ein Dokument oder ein Prototyp) rausgegeben? Wer war an der Erstellung wie lange beteiligt -- und wen hat es wie viel Zeit zum "konsumieren" (lesen, verstehen, ausprobieren) gekostet? Ich habe dann noch auf der Kunden- wie auf der Auftragnehmerseite zwei Rollen unterschieden: einmal die Personengruppe, deren Zeit mehr kostet (Leitungsfunktionen, Manager, Koordinatoren) und die Gruppe, deren Zeit weniger kostet (Entwickler, Tester, technische Schreiber). Mit der Zuordnung möchte ich niemanden diskriminieren, sie spiegelt nur grob die Kostenverteilung wieder, wie wir sie in der Realität antreffen. So ungenau das ist, es hilft uns, einen Eindruck zu gewinnen.&lt;br /&gt;&lt;br /&gt;Übrigens habe ich mit Tiefstpreisen gerechnet: Die "Billigen" kosten 50 Euro die Stunde, die "Teuren" doppelt so viel. Das dürfen Sie gerne im Kopf nach oben korrigieren. (Bevor Sie unglückliche Mutmaßungen anstellen: Ich habe in dem Projekt unentgeltlich gearbeitet, meine Arbeitskraft in der Modellrechnung jedoch monetär berücksichtigt.) Zeitaufwände habe ich aus dem Gedächtnis rekonstruiert, da ich keine zuverlässigen Aufzeichnungen dazu habe, und bin mit meinen Schätzungen sehr sportlich vorgegangen. Sportlich heißt auch hier, dass ich mit Minimalaufwänden gearbeitet habe, die real in den meisten Fällen höher liegen dürften.&lt;br /&gt;&lt;br /&gt;Die Ergebnisse: In der Historie der frühen Projektphase habe ich in einem Zeitraum von 5 Monaten (Juli bis Dezember 2007) 13 Termine bzw. Ereignisse erfasst. Davon sind 6 Termine Besprechungen (4 Vis-a-Vis, 2 Telefonkonferenzen) und 7 Termine markieren den Versand eines entscheidenden Dokuments, entweder als Neuerstellung oder als Update. Die mit diesen Terminen bzw. Ereignissen assoziierten Kosten belaufen sich für den Kunden auf etwa 1600 Euro, für den Auftragnehmer auf 4300 Euro.&lt;br /&gt;&lt;br /&gt;Ich finde das sehr beachtlich. Der Kunde muss als Auftraggeber etwa 6000 Euro ausgeben, einzig um sein Anliegen in dieser Projektphase zu kommunizieren, zu reflektieren, zu diskutieren, zu revidieren, zu konkretisieren und zu präzisieren. In der Zeit hat der Auftragnehmer noch keinen einzigen Euro verdient! Er hat diesen Prozess lediglich gemeinsam und in Kooperation mit seinem Kunden durchlaufen und zu einem Resultat getrieben, der dann erst den Startpunkt für die konkreten Entwicklungsaktivitäten eines Softwareprodukts bildet.&lt;br /&gt;&lt;br /&gt;Ich halte übrigens die Kostenanteile meiner Erfahrung nach für relativ typisch, kann dies allerdings nicht durch Fakten aus anderen Projekten belegen. Das Verhältnis liegt bei etwa 2:5. Von 7 Anteilen, die der Kunde für diese Projektphase ausgeben muss (6000 Euro durch 7 macht ca. 850 Euro), muss der Kunde seine eigenen Kosten etwa mit 2 Anteilen (die 1600 Euro, gleich etwa 2 Mal 850 Euro) veranschlagen, die für den Auftragnehmer mit 5 Anteilen (4300 Euro).&lt;br /&gt;&lt;br /&gt;Interessant ist zu beobachten, wie die Kostenentwicklung über die Zeit aussieht. Die Analyse der 13 Termine bzw. Ereignisse zeigt, dass für den Kunden die Aufwände am Anfang liegen. In den ersten Treffen werden viele Mitarbeiter vom Kunden involviert (das kostet viel), was am hohen Diskussions- und Klärungsbedarf liegt. Der Auftragnehmer hingegen hat die ganze Zeit über relativ gleichbleibende Aufwände: er muss am Ball bleiben und seine Arbeit im Hintergrund machen. Die Erstellung etwa eines Prototypen ist nicht unaufwendig. Für die weitere Abstimmung und Klärung beschäftigt der Kunde nun nur noch eine Person, die die Verantwortung für das Projekt trägt.&lt;br /&gt;&lt;br /&gt;Ich habe diesen Kostenverlauf etwas überzeichnet in dem Bild oben in rot eingetragen. Die Verteilung der Kosten beim Kunden verläuft über die Zeit wie ein sich zuspitzendes Dreieck; die Aufwände werden zunehmend geringer. Beim Auftragnehmer zeigt das langgezogene Rechteck die Konstanz der Kosten an. Bringt man beide Kostenanteile zusammen, sieht man den Verlauf der Gesamtkosten.&lt;br /&gt;&lt;br /&gt;In dem Bild habe ich darüber hinaus in grau den Kostenverlauf für das Projekt eingetragen, wie er sich qualitativ für die sich anschließende Entwicklung des Softwareprodukts und seiner Einführung beim Kunden ergeben hat. Während der Entwicklung entstehen für den Kunden kaum Kosten -- er wartet auf das Produkt. Mit der Fertigstellung nimmt der Aufwand für den Kunden wieder zu: Die Abnahme des Produkts muss durchgeführt werden und die mit der Einführung des Produkts verbundenen Schulungen boosten die Kosten noch einmal.&lt;br /&gt;&lt;br /&gt;Der Auftragnehmer hat während der Entwicklungszeit relativ konstante Kosten. Ein, zwei oder drei Entwickler werden  in dieser Zeit in Kleinprojekten oft beschäftigt. Ist das Produkt fertig, halten die Aufwände noch kurz an, um eventuelle Korrekturen oder kleinere Änderungen durchzuführen, sie nehmen dann aber ab.&lt;br /&gt;&lt;br /&gt;Es ist nicht aus zeichnerischen Gründen so, dass die Vor-Entwicklungsphase so lange dauert und die eigentliche Entwicklungszeit so kurz ist. Ist das Anliegen des Kunden einmal geklärt und erfasst, kann die Entwicklung recht zügig abgewickelt werden. Aber es kann dauern, bis das Anliegen hinreichend gut verstanden und aufgearbeitet ist; in diesem Fall hat sich das auf ganze 5 Monate verteilt.&lt;br /&gt;&lt;br /&gt;Wo kann der Auftragnehmer eigentlich seine Gewinne einrechnen? Kaum in der Vor-Entwicklungsphase, denn hier geht es darum, Unsicherheiten abzuarbeiten und Klärung herzustellen. Es ist schwer kalkulierbar, wie viele Termine dazu ausreichen werden, wenn man das Kundenanliegen noch nicht einmal verstanden hat. Das ist ja genau das Merkmal dieser frühen Phase: vieles ist unklar, unscharf, uneindeutig, unausgesprochen. Hier geht es lediglich darum, kostendeckend zu arbeiten. Ein Grund, warum diese Phase gerne aufwandsorientiert abgerechnet wird -- nur wollen das die Auftraggeber für Kleinprojekte meist nicht tun, da ihnen ein Verständnis für die Problematik dieser Vor-Entwicklungsphase fehlt. Denn in ihren Augen geht es ja nur um diese kleine Sache, dieses kleine Projekt, das ja eigentlich klar ist. Außerdem neigt ein Auftraggeber zur Blindheit gegenüber seinen eigenen, internen Kosten in dieser Phase (das Dreieck), da diese für Kleinprojekte selten klar abgerechnet werden. Veranschaulicht man sich noch einmal den Kostenverlauf beim Kunden, scheint es durchaus verständlich, dass Kunden nach dem Initialaufwand wenig interne Kosten "spüren". Das Gefühl des internen Kostenverlaufs wird auf den Auftragnehmer projiziert.&lt;br /&gt;&lt;br /&gt;Erst nach der Vor-Entwicklungsphase kann gut kalkuliert werden. Ein gemeinsames Verständnis des Kundenanliegens liegt vor, die Angelegenheit ist planbar geworden. Ergo wird der Auftragnehmer hier beginnen, seine Gewinnmargen einzurechnen. Ich habe das durch die schraffierten Bereiche markiert. Allerdings ist aufgrund der Kürze der Entwicklungszeit die Marge nicht sehr "lange" ausschöpfbar -- auch ein Merkmal von Kleinprojekten. Kommen nur ein, zwei, drei ungeplante Entwicklertage hinzu, weil etwa der Kunde auf einer Nachbesserung besteht oder, viel simpler, ein Entwickler krank ist, dann steht das Kleinprojekt für den Auftragnehmer bereits kurz vor der Verlustzone. Wesentlich ertragreicher und noch besser kalkulierbar sind Schulungsmaßnahmen beim Kunden. Nur bedarf nicht jedes Softwareprodukt einer Schulung.&lt;br /&gt;&lt;br /&gt;Wie Sie vielleicht anhand dieser Ausführungen erahnen, sind Kleinprojekte ein taffes Unterfangen, die den Auftragnehmern nicht viel Gewinne schenken. Reich wird damit keiner. Es macht auch klar, warum viele Unternehmungen scheitern, wenn sie nicht den Sprung in die Klasse der mittelgroßen Projekte bis Großprojekte schaffen, dort sind die Gewinnmargen größer. &lt;br /&gt;&lt;br /&gt;Wenn Sie Ihre Erfahrungen mit Kleinprojekten teilen möchten, ich freue mich auf Ihre Kommentare. Können Sie meine Fallstudie bestätigen? Oder haben Sie andere Erfahrungen mit Kleinprojekten gemacht?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-4883591429229003405?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/4883591429229003405/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=4883591429229003405' title='5 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/4883591429229003405'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/4883591429229003405'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/04/kleinprojekte-und-ihre-kosten.html' title='Kleinprojekte und ihre Kosten'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_XJMaba79IKU/SAR3Eud1VhI/AAAAAAAAADg/R7Bogi4EllU/s72-c/ProjektFallStudie.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-3951475237422645195</id><published>2008-03-31T12:45:00.005+02:00</published><updated>2008-03-31T13:58:25.440+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='n95'/><category scheme='http://www.blogger.com/atom/ns#' term='wii'/><category scheme='http://www.blogger.com/atom/ns#' term='3d'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Sichtweisen in 3D: Balance halten</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_XJMaba79IKU/R_DQmnQc63I/AAAAAAAAADY/g-VNbe0dRxU/s1600-h/n95.Wasserwaage.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_XJMaba79IKU/R_DQmnQc63I/AAAAAAAAADY/g-VNbe0dRxU/s320/n95.Wasserwaage.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5183872532895034226" /&gt;&lt;/a&gt;&lt;br /&gt;Wie sehen wir dreidimensional? Die meisten Menschen denken dabei ans Stereosehen: Unsere beiden Augen liefern zwei Bilder, die ein und dieselbe Szenerie aus geringfügig abweichenden Blickwinkeln betrachten. Diese Winkelabweichung genügt, um Tiefeninformationen aus den Bilddaten abzuleiten.&lt;br /&gt;&lt;br /&gt;Das ist so richtig, wie es auch nur die halbe Wahrheit ist. Das Stereosehen erlaubt es uns, im direkten Nahbereich von wenigen Metern Distanzen im Raum einschätzen zu können. Aber Sie können auch mit nur einem Auge dreidimensional sehen! Glauben Sie nicht? Dann schauen Sie sich mal das Video von &lt;a href="http://www.cs.cmu.edu/~johnny/"&gt;Johnny Chung Lee&lt;/a&gt; an, einem genialen Kopf, der seinesgleichen sucht. Das Video, das seit Ende 2007 im WWW kursiert, zeigt Ihnen eine aufregend andere Art des Einsatzes der WiiRemote -- und ist gleichzeitig ein brillantes Lehrstück über unsere Grundlagen des 3D-Sehens!&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/Jd3-eiid-Uw&amp;hl=en"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/Jd3-eiid-Uw&amp;hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Unser Gehirn verrechnet also auch diese Winkelverschiebungen um in Tiefeninformation. Dazu muss sich etwas bewegen: entweder man sich selbst oder die Szenerie. Lee dreht hier den Spieß um: Er lässt den Computer umrechnen, wie sich die Szenerie verändert, wenn wir uns vor dieser Szenerie bewegen -- und erzeugt damit die Illusion der Tiefe eines Raumes. So rechnen beide: Gehirn und Computer. Die Täuschung ist perfekt!&lt;br /&gt;&lt;br /&gt;Hat man einmal gesehen, auf welche einfache und originelle Art und Weise man mit diesen neuen Schnittstellen umgehen kann, kommen einem auch gleich ganz andere Ideen. Vor wenigen Tagen zeigte mir ein Student sein N95-Handy von Nokia mit einer kleinen Applikation, die die Bewegungssensoren im Handy nutzt: eine "Wasserwaage" (siehe Bild oben). Der rote Punkt im Display kommt in der Mitte zur Ruhe, wenn sich das Display des Handys in der Waage befindet. Ansonsten wandert der Punkt nach rechts bzw. links. Die Applikation ist in Python geschrieben und läuft auf dem Python-Port für S60-Handys. Wir haben übrigens nicht mehr ausfindig machen können, wer der Autor des Programms ist und ob es eine Webseite dazu gibt. Hinweise sind willkommen.&lt;br /&gt;&lt;br /&gt;Wenn Sie ein Handy haben, das Sensoren für zwei Achsen hat (X- und Y-Achse), dann können Sie die Lee-Idee entweder direkt auf dem Handy umsetzen oder Sie lassen sich etwas anderes einfallen. Mein Vorschlag wäre folgender: Stellen Sie sich vor, auf Ihrem Handydisplay stünde senkrecht ein Stab mit einer roten Kugel als Kopf, eine Stecknadel. Sie schauen in der Draufsicht auf das Display, sprich, Sie sehen nur die rote Kugel von oben als Kreis. Nun kippen Sie das Handy hin und her. Sie sehen nun die Stecknadel von der Seite, je nach Neigungsgrad. Es wird sich ein starker, visueller 3D-Eindruck einstellen, ähnlich wie bei dem Video, das Sie oben gesehen haben. Wenn Sie wollen, können Sie die "Stecknadel" bei Neigung allmählich kipppen lassen, so dass die Herausforderung darin besteht, die Nadel wieder in Balance zu bekommen. Ein nettes Spielchen! Wenn Sie noch einen Sensor für die dritte Achse haben (Z-Achse), können Sie die Nadel auch "hochwerfen" und auf einer virtuellen Ebene im Raum landen lassen. Sie erahnen es. Man kann sich ganz neue und ganz andere Spielideen und Anwendungsgebiete einfallen lassen.&lt;br /&gt;&lt;br /&gt;Mag sich jemand an eine Umsetzung machen? Oder haben Sie noch andere nette, mehr oder minder sinnvolle (Spiel-)Ideen?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-3951475237422645195?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/3951475237422645195/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=3951475237422645195' title='4 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3951475237422645195'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3951475237422645195'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/03/sichtweisen-in-3d-balance-halten.html' title='Sichtweisen in 3D: Balance halten'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_XJMaba79IKU/R_DQmnQc63I/AAAAAAAAADY/g-VNbe0dRxU/s72-c/n95.Wasserwaage.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-116706792994325618</id><published>2008-03-04T12:38:00.003+01:00</published><updated>2008-03-04T12:50:47.098+01:00</updated><title type='text'>Der freie Wille</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_XJMaba79IKU/R801wdMrXaI/AAAAAAAAADQ/EBvEBZMXkg8/s1600-h/hcm80.289504238.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_XJMaba79IKU/R801wdMrXaI/AAAAAAAAADQ/EBvEBZMXkg8/s400/hcm80.289504238.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5173850653506362786" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;small&gt;&lt;a href="http://www.flickr.com/photos/hanscmueller/289504238/"&gt;Bild&lt;/a&gt; von &lt;a href="http://www.flickr.com/photos/hanscmueller/"&gt;hcm80&lt;/a&gt;&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;Wie frei sind wir Menschen eigentlich in unseren Entscheidungen? Kann eine Maschine, ein Computerprogramm einen "freien Willen" haben? Was überhaupt ist die willentliche Freiheit der Entscheidung?&lt;br /&gt;&lt;br /&gt;Nähern wir uns den Fragen aus der Sicht der &lt;a href="http://de.wikipedia.org/wiki/Informationstheorie"&gt;Informationstheorie&lt;/a&gt;. Die moderne Informationstheorie begründet sich auf &lt;a href="http://de.wikipedia.org/wiki/Claude_Shannon"&gt;Claude Shannon&lt;/a&gt;. Shannon sagt, vereinfacht gesprochen: Je überraschender ein Ereignis ist, desto höher ist sein Informationsgehalt. Ein Beispiel: Jeden Morgen sehen Sie auf dem Weg zur Arbeit einen Mann mit einem roten Schal an der Bushaltestelle stehen. Immer der rote Schal. Schal und Mann scheinen ein untrennbar zu sein. Es überrascht sie wenig, ihn jeden Morgen mit dem roten Schal zu sehen. Sie erwarten es regelrecht. Der rote Schal ist keine Neuigkeit, keine Information mehr für Sie. Er gehört einfach dazu. An einem Morgen, Sie erinnern sich noch genau, es war der 1. Mai, da steht er plötzlich da mit einem grünen Schal. Große Überraschung, hoher Neuigkeitswert. Diese Überraschung verstehen wir im Sinne von Shannon als Information.&lt;br /&gt;&lt;br /&gt;Die Überraschung, oder anders herum, Ihre Erwartung hängt zusammen mit der Wahrscheinlichkeit des Ereignisses. Eine hohe Wahrscheinlichkeit drückt Ihren Erwartungswert aus. Tritt das Ereignis im Rahmen Ihrer Erwartungshaltung auf, dann sind sie nicht überrascht. Geringer Informationswert.&lt;br /&gt;&lt;br /&gt;Schauen wir uns nun einmal an, was wir aus dieser Sicht als "freien Willen" verstehen könnten:&lt;br /&gt;&lt;br /&gt;Nehmen wir Ihre Freundin Alica. Sie kochen für sie und machen ihr drei Teller fertig: einen Teller mit Spaghetti ohne alles, einen Teller Spaghetti mit Tomatensauce und einen Teller Spaghetti mit Tomatensauce und Parmesan. Sie wissen, dass Alica weder ein "trockenes" Essen noch Käse mag. Ihre Erwartung ist, dass Sie den Teller mit der Tomatensauce nehmen wird. Und so ist es dann auch!&lt;br /&gt;&lt;br /&gt;Hat sich Alica frei entschieden? Aus Ihrer Sicht hat sich Alica gemäß Ihren Erwartungen verhalten. Das wirkt auf Sie nicht so, als sei Alica frei in Ihrer Entscheidung gewesen. Sie hat sich genommen, was sie mag, und gemieden, was sie nicht mag. Sie hat sich vollkommen inneren Antrieben für Vorlieben und Abneigungen hingegeben. Eigentlich konnte Alica gar nicht anders!&lt;br /&gt;&lt;br /&gt;Alica hätte sich frei in der Entscheidung gezeigt, wenn sie z.B. zur Variante mit dem Parmesan-Käse gegriffen hätte. Das hätte Sie sehr überrascht -- und wäre eine echte Neuigkeit gewesen.&lt;br /&gt;&lt;br /&gt;Die Freiheit einer Entscheidung begründet sich für einen Außenstehenden also damit, wie sehr sich jemand gegen Erwartungen verhält. Der Erwartungswert drückt Ihre Kenntnis aus über Motive, Vorlieben, Wünsche, Sehnsüchte und bisherige Erfahrungen mit der Person, die Sie gemacht haben.&lt;br /&gt;&lt;br /&gt;Und wie kann sich Alica "frei" verhalten? Indem sie Ihre Erwartungshaltung durchbricht. Indem sich Alica gänzlich anders verhält als erwartet. Die Überraschung ist umso größer, je mehr Alicas Verhalten Neuigkeitswert hat.&lt;br /&gt;&lt;br /&gt;Da wir Menschen aber nur einen sehr schlechten Zugang zu unsere Innenwelten haben, können wir uns nicht sicher sein, wie wir eine Entscheidung gegen Erwartungen fällen sollen -- außer, man nimmt einen Würfel! Genauer, einen gezinkten Würfel, der seine Seiten genau gegenläufig zu den Erwartungen zufällig oben zum liegen kommen lässt.&lt;br /&gt;&lt;br /&gt;Das irritiert, nicht wahr? Aber es ist eine konsequente Sicht der Dinge mit den Augen der Informationstheorie.&lt;br /&gt;&lt;br /&gt;Freiheit ist der Moment, an dem wir uns willentlich gegen erwartete Verhaltensmuster entscheiden und einen Würfel zur Hand nehmen, der uns aus den Möglichkeiten der Optionen per Zufall eine raussucht. Sie haben richtig gelesen: Sie müssen würfeln! Freiheit wird dann gelebt, wenn diese zufällige Entscheidung ohne Leid, ohne Reue, ohne Bedauern genauso gelebt werden kann wie jede andere Wahl, die der Würfel getroffen hätte!&lt;br /&gt;&lt;br /&gt;Wie bitte, sich dem Zufall unterwerfen ist Freiheit? Das gelegentliche, willentliche "unterwerfen" ist Freiheit, denn sonst verhielten Sie sich nur zufällig. Wobei der Begriff "Unterwerfung" schon falsch ist. Ein freier Mensch unterwirft sich nicht, er lebt jede Option in gleicher Weise. Sonst ist er nicht frei, oder? Das höhrt sich schon sehr nach östlicher Philosophie an!&lt;br /&gt;&lt;br /&gt;Nichts gegen östliche Philosophien. Aber wenn Sie mich fragen, ich verzichte auf die Freiheit und esse lieber immer nur Spaghetti mit Tomatensauce!&lt;br /&gt;&lt;br /&gt;Und genau da sind wir an dem Punkt angelangt: Ich bin nicht wirklich frei zu essen, was man mir vorsetzt. Ich habe Vorlieben. Ich bin berechenbar. Nun kann man sich fragen, wie weit man das Spiel treiben möchte: Ist Ihr Hobby eine freie Wahl? Ist Ihr Partner bzw. Partnerin frei gewählt? Ist Ihre Ausbildung, Ihr Wohnort, Ihre Automarke, Ihr DVD-Player, ist das alles eine Wahl des freien Willens? Wie oft haben Sie gewürfelt bzw. würfeln lassen?&lt;br /&gt;&lt;br /&gt;Wenn man meiner Argumentation folgen mag (mir ist selbst nicht ganz wohl dabei), dann können wir Software-Programmen relativ leicht freien Willen einpflanzen. Wir lassen sie an einigen Stellen einfach gelegentlich würfeln und provozieren unerwartete Verhaltensweisen. Und schon wählt der Computer Spaghetti mit Parmesan -- und hat nicht einmal ein Problem damit!&lt;br /&gt;&lt;br /&gt;Ein Zufallssimulator aus Software verhält sich zwar nicht wirklich zufällig. Sein Verhalten ist vorhersehbar, wenn man den Wert zur Initialisierung des Simulators kennt -- auch &lt;i&gt;seed&lt;/i&gt; genannt. Man nennt es also nicht umsonst einen Simulator. Insofern ist der "freie Wille" in einer reinen Software-Maschine auch nur eine Simulation. Diese Simulation verhält sich aber freier als wir es sind.&lt;br /&gt;&lt;br /&gt;Laut &lt;a href="http://de.wikipedia.org/wiki/Gerhard_Roth_%28Biologe%29"&gt;Gerhard Roth&lt;/a&gt;, einem anerkannten Hirnforscher, ist unser "freier Wille" vermutlich mehr Illusion als uns lieb ist. So sollten wir froh sein, dass wir wenigstens Computer frei sein lassen können. Vielleicht sind Computer nicht willentlich frei, aber immerhin frei -- wenn wir ihnen die Freiheit gewähren.&lt;br /&gt;&lt;br /&gt;Gruseliger Schluss, was?!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-116706792994325618?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/116706792994325618/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=116706792994325618' title='9 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/116706792994325618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/116706792994325618'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/03/der-freie-wille.html' title='Der freie Wille'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_XJMaba79IKU/R801wdMrXaI/AAAAAAAAADQ/EBvEBZMXkg8/s72-c/hcm80.289504238.jpg' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-5510329074447738354</id><published>2008-02-25T21:01:00.010+01:00</published><updated>2008-02-26T23:20:38.463+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><title type='text'>Wie lerne ich eine Programmiersprache an einem Tag?</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_XJMaba79IKU/R8SPVOl_6PI/AAAAAAAAADI/08qoc0QD1ko/s1600-h/jbvkoos.416805640.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_XJMaba79IKU/R8SPVOl_6PI/AAAAAAAAADI/08qoc0QD1ko/s320/jbvkoos.416805640.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5171415866985670898" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;small&gt;(&lt;a href="http://www.flickr.com/photos/jbvkoos/416805640/"&gt;Foto&lt;/a&gt; von &lt;a href="http://www.flickr.com/photos/jbvkoos/"&gt;jbvkoos&lt;/a&gt;)&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;Lassen Sie sich mal an einem Tag für acht oder zehn Stunden, oder wenn es Sie so richtig gepackt hat, für 12 Stunden auf eine neue Programmiersprache ein! Sie werden sehen, dass Sie erstaunlich weit kommen. Weiter als Sie es vielleicht für möglich gehalten haben. Das geht, wenn Sie sich der Sache ein wenig mit System nähern. Hier ein paar Tipps und Vorschläge. Ich beziehe mich im Folgenden beispielhaft auf JavaScript.&lt;br /&gt;&lt;br /&gt;Bevor es los geht, ein kleiner Hinweis: Sie werden keine Sprache an einem Tag lernen können, wenn Sie nicht bereits mit mindestens einer modernen Programmiersprache gut vertraut sind. Die erste Hürde muss also schon genommen sein. Ab der ersten Hürde wird es immer leichter ;-)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Vorbereitung:&lt;/b&gt; Besorgen Sie sich ein Buch zu der Programmiersprache, die Sie interessiert. Am besten in Papierform -- mit Papier lässt sich sehr schnell und zügig arbeiten. Legen Sie sich für Ihre Streifzüge durch das Buch Stift und Textmarker bereit. Beschaffen Sie sich den Standard zu Ihrer neuen Programmiersprache. Meist finden sie ihn frei zugänglich im Web. Ein Standard ist ein technisches Dokument, das die Programmiersprache genau beschreibt und definiert. Manchmal gibt es keinen formalen Standard, sondern ein Buch oder Dokument, das die Sprache verbindlich definiert. Suchen Sie danach. Und zu guter letzt: Installieren Sie sich die neue Sprache auf Ihrem Rechner, damit Sie sofort damit herumspielen können. Ja, &lt;i&gt;spielen&lt;/i&gt; -- die Sache soll Spaß machen!&lt;br /&gt;&lt;br /&gt;Um all das kümmern Sie sich am besten ein paar Tage bevor Sie sich mit der Sprache dann für einen Tag beschäftigen wollen. Los geht's!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Syntax anschauen:&lt;/b&gt; Beginnen Sie mit einen Blick in die Syntax, also den Regeln, wie gültige Programme aussehen dürfen. Die Syntaxregeln werden Sie vermutlich im Standard finden, meist im Anhang. Viele Bücher zu Programmiersprachen verzichten bedauerlicherweise sogar auf eine klare Angabe der Syntaxregeln; jetzt wissen Sie, warum Sie ihn sich beschaffen sollten. Schauen Sie zum Beispiel in den Annex A des Standards zu JavaScript, ECMA-262, 3rd Edition. Auf wenigen Seiten erfahren Sie interessante Dinge über die Sprache, etwa eine Liste reservierter Schlüsselwörter (&lt;i&gt;keywords&lt;/i&gt;). Von "break", "case", "catch", ... bis hin zu "var", "void", "while", "with". Ganze 25 Schlüsselwörter gibt es zu erkunden. Damit gibt es ein erstes klares Arbeitsprogramm: Verstehen, wofür jedes dieser Schlüsselwörter da ist. Verbergen sich hier neue, interessante Konzepte?&lt;br /&gt;&lt;br /&gt;In der Syntaxbeschreibung werden Sie bei JavaScript zum Beispiel auch entdecken, dass reguläre Ausdrücke zur Sprache gehören. Wenn Ihnen das nichts sagt: unbedingt lernen!  Nicht jetzt, an diesem Tag -- sonst kommen wir nicht durch -- aber reguläre Ausdrücke sind ein mächtiges Werkzeug bei der Suche nach Mustern in Zeichenketten. Muss man können! Hat praktisch jede moderne Sprache mindestens als Bibliothek im Gepäck.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Welche Datentypen gibt es?&lt;/b&gt; Jetzt kann Ihr Buch zum Einsatz kommen. Blättern Sie durch das Inhaltsverzeichnis, verschaffen Sie sich einen Überblick über die Themen. Beschränken Sie sich rein auf Kapitel zu Ihrer neuen Sprache. Ignorieren Sie Bibliotheken, Erweiterungen oder Spezialanwendungen. Das ist jetzt alles uninteressant. Fangen Sie an mit den Datentypen: Welche Basistypen gibt es, welche "Sammeltypen" gibt es? JavaScript hat lediglich drei primitive Datentypen: Zahlen, Zeichenketten und Booleans. Dazu kommen noch zwei triviale Typen: &lt;i&gt;null&lt;/i&gt; und &lt;i&gt;undefined&lt;/i&gt;. Daneben gibt es noch den Datentyp des Objekts als Sammeltyp. Und das war es schon -- JavaScript präsentiert sich erstaunlich einfach. Hätten Sie's gedacht? Zwar redet man auch von Arrays, die jedoch ebenfalls Objekte sind; Funktionen, Zeitwerte, reguläre Ausdrücke und Fehler sind lediglich besondere Arten von Objekten.&lt;br /&gt;&lt;br /&gt;Ein wichtiger Punkt ist noch: Wie wird mit Typen umgegangen? Handelt es sich bei Ihrer neuen Programmiersprache um dynamische oder statische Typen? Sie wissen vielleicht, das dynamisch typisierte Sprache, wie Python, Ruby oder JavaScript, zunehmend an Boden gewinnen. Die Art mit solchen Sprachen zu arbeiten ist eine gänzlich andere als mit statisch typisierten Sprachen wie Java oder C#. Noch wichtiger jedoch ist: Wie werden Datenwerte manipuliert? Wie heißt es so schön im Informatik-Slang: &lt;i&gt;by value&lt;/i&gt; oder &lt;i&gt;by reference&lt;/i&gt;? Wie werden Daten zugewiesen, wie wird beim Aufruf von Methoden, Prozeduren, Funktionen mit ihnen umgegangen? In JavaScript ist die Welt einfach geregelt: Primitive Typen werden "by value" behandelt, Objekte "by reference". Nur Strings passen nicht so ganz in das Schema. Strings sind &lt;i&gt;immutable&lt;/i&gt;, nicht veränderbar, weshalb es keine Rolle spielt, wie sie behandelt werden.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Welche Anweisungen gibt es?&lt;/b&gt; Viele Anweisungen werden Ihnen bekannt vorkommen, wie z.B. "if", "switch", "while", "break", "return" etc. Suchen Sie nach Abweichungen, nach Anweisungen und/oder deren Verwendung, die Sie so aus Ihnen bekannten Sprachen nicht kennen. Den meisten ist die "for"-Schleife aus JavaScript bekannt, nicht jedem jedoch das "for/in". &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Wie wird mit Variablen umgegangen?&lt;/b&gt; Müssen Variablen deklariert werden? Muss der Typ einer Variablen mit angegeben werden? Wie ist der Scope einer Variablen? Wenn Sie noch nie etwas vom lexikalischen Scope gehört haben -- jetzt müssen Sie sich damit auseinander setzen, denn die meisten Programmiersprachen arbeiten mit &lt;i&gt;lexical scope&lt;/i&gt;, so auch JavaScript. Allerdings kennt JavaScript keinen Block-Scope, wie er sich zum Beispiel durch ein Schleifenkonstrukt wie "for" ergibt.&lt;br /&gt;&lt;br /&gt;Fundamental ist das Konzept der Variablen, wenn Sie sich als Kenner einer imperativen (anweisungsorientierten) Sprache plötzlich mit einer funktionalen Sprache, wie z.B. Haskell oder Scheme/Lisp, beschäftigen. Plötzlich halten Variablen ihre Werte nicht über die Lebensdauer eines Funktionsaufrufs hinaus. Dauerhafte Wertzustände werden nicht mehr durch Objekte gekapselt; überhaupt arbeitet man in der funktionalen Welt niemals mit impliziten Zuständen. Scheme und Lisp erlauben zwar Ausnahmen, aber Sprachen wie Haskell sind da sehr konsequent und bringen einen mit vollkommen neuen Dingen in Berührung wie zum Beispiel der Zustandsmonade.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Welche Operatoren gibt es?&lt;/b&gt; Plus "+", Minus "-", Objekt-Schöpfung "new" etc., all das sind Operatoren. Ohne Operatoren läuft nicht viel. Hier verstecken sich die eigentlichen Arbeitsknechte. Meist sind für Operatoren Vorrangsregeln definiert (wie "Punkt- vor Strich-Rechnung"), die man grob kennen sollte. Ganz wichtig ist es zu klären, was in Ihrer neuen Sprache Gleichheit (&lt;i&gt;equality&lt;/i&gt;) von Identität (&lt;i&gt;identity&lt;/i&gt;) unterscheidet -- hier spielen "by value" und "by reference" wieder eine wichtige Rolle. Ein anderer wichtiger Operator ist die Zuweisung.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Welche speziellen Konzepte gibt es, die wesentlich für die Sprache sind?&lt;/b&gt; Für diese Frage ist es sehr schwer, eine Richtschnurr vorzugeben. Sie müssen zum Kern der Sprache vordringen. Was ist hier anders? Welche Konzepte, welche Konstrukte gibt es, die wesentlich den Charakter und die Denke der Programmiersprache prägen? In JavaScript sind es Funktionen (JavaScript hat ein sehr funktionales Herz) und Objekte/Arrays. JavaScript ist nicht, wie Sie es vermutlich von den meisten OO-Sprachen her kennen, klassen-basiert, sondern prototyp-basiert -- und kennt auch eine Form der Vererbung. Wenn das neu für Sie ist, dann ist hier ein Einstieg gefunden in die Welt von JavaScript. In den Objekten und Funktionen liegt der andere Ansatz verborgen, der JavaScript auszeichnet. Sie beherrschen JavaScript nicht, wenn Sie an dieser Stelle auf einen Abstieg in die Tiefen von JavaScript verzichten. Wenn Sie sich danach noch mit Modulen und Namensräumen beschäftigen, dann haben Sie JavaScript erobert.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Spielen Sie herum -- aber bleiben Sie fokussiert!&lt;/b&gt; Tippen Sie kleine Programmschnipsel in einen Editor oder eine IDE, machen Sie Ihre ersten Gehversuche mit der neuen Sprache. Dann prägen sich mache Dinge schneller ein oder man kann sein Verständnis für das eine oder andere Feature austesten. Aber lassen Sie sich nicht ziellos treiben. Ihr Ziel ist, an diesem einen Tag eine neue Sprache so gut und systematisch zu erfassen, wie möglich. Wenn Ihnen etwas Interessantes über den Weg läuft, notieren Sie es sich für später.&lt;br /&gt;&lt;br /&gt;Wie geht es nach so einem Tag weiter? Das hängt ganz davon ab, warum Sie sich mit der neuen Sprache auseinander gesetzt haben. Wenn Sie sich weiter mit der Sprache beschäftigen wollen, nutzen Sie die Sprache für Ihr nächstes kleines Projekt oder Vorhaben. &lt;i&gt;Learning by doing&lt;/i&gt; ist noch immer der erfolgreichste Weg.&lt;br /&gt;&lt;br /&gt;Natürlich bedarf es einiger Wochen bis Monate, bis Sie sich in eine neue Sprache wirklich eingefunden haben; bis sie anfangen, in der Sprache zu denken und fließend in ihr zu sprechen. Mir sind schon des öfteren Talente über den Weg gelaufen, die in acht bis zwölf Wochen von Neulingen zu echten Experten in einer Sprache heranwuchsen. Das gelingt aber nur zusammen mit einem Projekt, das einem täglich die Auseinandersetzung mit der neuen Sprache abfordert.&lt;br /&gt;&lt;br /&gt;---&lt;br /&gt;&lt;br /&gt;Verraten Sie es mir: Hat Ihnen dieser Beitrag und seine Thematik gefallen? Haben Sie noch weitere Tipps für das Erlernen einer Programmiersprache?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-5510329074447738354?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/5510329074447738354/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=5510329074447738354' title='8 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5510329074447738354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5510329074447738354'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/02/wie-lerne-ich-eine-programmiersprache.html' title='Wie lerne ich eine Programmiersprache an einem Tag?'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_XJMaba79IKU/R8SPVOl_6PI/AAAAAAAAADI/08qoc0QD1ko/s72-c/jbvkoos.416805640.jpg' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-2674483313500315450</id><published>2008-02-13T12:42:00.004+01:00</published><updated>2008-02-13T12:52:08.552+01:00</updated><title type='text'>Vom Entwurf zum Programm</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_XJMaba79IKU/R7LX_Ol_6NI/AAAAAAAAAC4/DFHNwdr-rZ8/s1600-h/2008-02-13.EntwurfOOFramework.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_XJMaba79IKU/R7LX_Ol_6NI/AAAAAAAAAC4/DFHNwdr-rZ8/s400/2008-02-13.EntwurfOOFramework.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5166429203796584658" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_XJMaba79IKU/R7LYPul_6OI/AAAAAAAAADA/18V6as36Dmk/s1600-h/2008-02-13.ProgrammOOFramework.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_XJMaba79IKU/R7LYPul_6OI/AAAAAAAAADA/18V6as36Dmk/s400/2008-02-13.ProgrammOOFramework.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5166429487264426210" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Was lernt man nicht alles für feine Dinge als Softwaretechniker: Die Software-Entwürfe entstehen am Reißbrett, oftmals hart erarbeitet, und sie präsentieren sich als schicke Diagramme. Dabei bedienen wir uns einer "Geheimnotation" namens &lt;i&gt;&lt;a href="http://de.wikipedia.org/wiki/UML"&gt;Unified Modeling Language&lt;/a&gt;&lt;/i&gt; (UML), die für Laien kaum verständlich ist. Da gibt es Kästchen, Linien, Rauten, Zahlen, Benamungen, Textanmerkungen -- das wirkt alles sehr imposant. Es braucht einiges an Zeit, ehe man die hohe Kunst des Software-Entwurfs erlernt hat.&lt;br /&gt;&lt;br /&gt;Irgendwann findet man sich jedoch auf der Programmier-Baustelle wieder. Hier werden die Entwürfe in für einen Computer verständliche Anweisungen umgesetzt. Und, wenn man genau hinschaut, geht es hier schlimmer zu als auf jeder echten Baustelle. Der Programmcode hat nur lose Ähnlichkeiten mit den Entwürfen. Programmierer ziehen mal hier und mal dort eine Wand ein, halten an anderer Stelle einen Durchbruch für angemessen, und das Maßband scheint ihnen völlig abhanden gekommen zu sein. "Pi mal Daumen" -- ja, so ungefähr entspricht das dem Entwurf. Wer seine Aufgabe als Bauherr auf der Programmier-Baustelle ernst nimmt, der kann verzweifeln.&lt;br /&gt;&lt;br /&gt;Ein kleines Beispiel gefällig?&lt;br /&gt;&lt;br /&gt;Schauen Sie sich mal oben das Bild an. Ein UML-Diagramm, das ich in einer Vorlesung nutze. Es ist ein Entwurf für ein OO-Framework. Hübsch anzusehen, gell? Ich weiß, das Diagramm ist nicht perfekt -- aber darauf kommt es mir hier nicht an.&lt;br /&gt;&lt;br /&gt;Zu diesem OO-Framework gibt es eine einfache Implementierung in Python von mir. Auch die spreche ich mit den Studierenden durch. Vor wenigen Wochen, als ich versuchte, den Code zu erklären, griff ich zur Kreide. Ich begann, die Referenzbezüge, so wie sie im Python-Code aufgebaut sind, in einer informellen Notation an die Tafel zu malen, in der Hoffnung, so werde sich der Wald lichten. Tat er aber nicht. Das Ganze entwickelte sich zu einer wunderschönen Fallstudie, wie schwer sich Entwurf und Implementierung tun, aufeinander zu passen.&lt;br /&gt;&lt;br /&gt;Was haben die beiden Bilder gemeinsam? Man erkennt Ähnlichkeiten. Die großen Kästchen tragen die gleichen Namen. Aber sonst? An der Tafel sind verwirrend viele Linien hinzugekommen. Wie kommt's?&lt;br /&gt;&lt;br /&gt;Ein Kernproblem ist, dass die Ausdrucksmittel aus dem UML-Diagramm keine klare Entsprechung in meiner Zielsprache, der Programmiersprache Python haben. Ich muss also mit "Workarounds" arbeiten, die die Intentionen aus dem Entwurf umsetzen. Zum Beispiel die Kompositionen. In der UML baut eine Komposition besondere Zugriffsbezüge und Abhängigkeiten in den Lebensbezügen auf. In den gängigen OO-Sprachen, wie auch in Python, Java, C# oder Ruby gibt es jedoch keine Komposition. Die meisten OO-Sprachen basieren auf Objekt-Referenzen, die keine Zugriffsbezüge durch Namensräume regeln, jedoch auf den Lebenszyklus von Objekten einen erheblichen Einfluss haben. Also bildet man die Intention der Komposition auf anderen Wegen ab und sorgt sich um einen gesitteten Umgang mit Referenzen. Ähnliches gilt für das "instanceOf".&lt;br /&gt;&lt;br /&gt;Und hier gehen die Probleme los. Wer das intendierte Mapping von Code und Entwurf nicht kennt -- dieses Mapping wird nämlich selten, eher gar nicht dokumentiert --, der steht in der Gefahr, irgendwann einmal am Code Änderungen vorzunehmen, die den Entwurf verletzen und der austarierten Balance von Code und Entwurf radikal Schaden zufügt. So entstehen Fehler, die in aller Regel schwer zu entdecken, wenn, dann meist folgenreich sind und deren Beseitigung erhebliche Anstregungen kostet.&lt;br /&gt;&lt;br /&gt;Ein anderes Beispiel. In Python nutze ich gerne Dictionaries (sie kennen ähnliches vielleicht als HashMaps oder assoziatives Arrays) -- und zwar als Caches für einen schnellen Zugriff auf Objekte unter einem Schlüssel. Es sind die "Qualifier" (die kleinen Boxen an den großen Boxen) auf dem Tafelbild. Streng genommen, mit Blick auf den Entwurf, bräuchte ich sowas nicht. Doch der Einsatz von Dictionaries macht den Python-Code oft einfacher und übersichtlicher. Der Preis: Ich entferne mich vom Entwurf. Die Dictionaries beginnen ein Eigenleben zu führen.&lt;br /&gt;&lt;br /&gt;Wenn Sie Studentin oder Student der Informatik sind, dann haben sie wahrscheinlich zahllose, weitere solche Beispiele auf Lager, die einen erheblichen "Clash" aufzeigen zwischen Entwurf und Umsetzung. Bisweilen entsteht das UML-Diagramm zum Entwurf erst nachträglich, nach der Programmierung, und schönt und verhübscht die "Häßlichkeiten" des Codes erheblich.&lt;br /&gt;&lt;br /&gt;Sind Codegeneratoren ein Ausweg, die aus UML-Diagrammen direkt den Programm-Code (z.B. für Python) erzeugen? Jaein. Zum einen ist es gar nicht so einfach, gute schematische Code-Templates für die Code-Generation zu entwickeln. Der Versuch, Komposition sauber in einer rein referenz-basierten Sprache nachzubilden, ist nicht wenig aufwendig und versucht einer Sprache etwas überzustülpen, wofür sie nicht gemacht wurde. Das ist zumindest bei einem Blick auf das Laufzeitverhalten nicht ganz außer acht zu lassen. Allein die Nachbildung von Singletons, ein lapidarer Stereotyp in der UML, ist nicht trivial, besonders wenn Singletons thread-safe sein sollen.&lt;br /&gt;&lt;br /&gt;Doch das eigentliche Problem liegt in meinen Augen tiefer. Code-Generierung aus Entwürfen ist ok, sofern man einen ausführbaren &lt;i&gt;Entwurf&lt;/i&gt; haben möchte. Nicht immer ist das sinnvoll. Wichtig ist zu erkennen, dass es einen Unterschied gibt zwischen Entwurf (Design) und Umsetzung (Implementierung). Eine Umsetzung muss einen Entwurf erfüllen. Nicht mehr und nicht weniger. Das wird wenig verstanden. Ich habe versucht in meinen Posts zu &lt;a href="http://denkspuren.blogspot.com/2007/11/user-domain-and-realization-models.html"&gt;User, Domain und Realization Model&lt;/a&gt; darauf in einem anderen Kontext einzugehen. Denn häufig sehe ich nicht nur Studierende, sondern auch Profis einen Fehler machen: Es wird weniger über einen Entwurf nachgedacht! Es wird Programmcode mit Hilfe von UML-Diagrammen beschrieben, nicht ein Entwurf! Dann wird der Code-Generator nur zum Erfüllungsgehilfen von mit Diagrammen "gemaltem" Code.&lt;br /&gt;&lt;br /&gt;Glauben Sie nicht? Wann haben Sie das letzte Mal Mehrfachvererbung angewendet? Das wird Ihnen als Ausdrucksmittel in der UML für Ihre Entwürfe angeboten und kann ganz hilfreich sein. Was? Mehrfachvererbung nutzen Sie nicht? Warum? Weil Sie Java- oder C#-Programmierer sind? Erwischt! :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-2674483313500315450?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/2674483313500315450/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=2674483313500315450' title='4 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2674483313500315450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2674483313500315450'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/02/vom-entwurf-zum-programm.html' title='Vom Entwurf zum Programm'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_XJMaba79IKU/R7LX_Ol_6NI/AAAAAAAAAC4/DFHNwdr-rZ8/s72-c/2008-02-13.EntwurfOOFramework.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-677957971560715421</id><published>2008-01-07T15:04:00.000+01:00</published><updated>2008-01-07T15:34:01.233+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Verschlüsselung'/><title type='text'>TrueCrypt "entschlüsselt"</title><content type='html'>Sollten Sie Windows- oder Linux-User sein und &lt;a href="http://www.truecrypt.org/"&gt;TrueCrypt&lt;/a&gt; noch nicht kennen -- ich kann Ihnen dieses  OpenSource-Programm nur empfehlen. Es verschlüsselt eine Festplatte entweder vollständig oder einzelne Files darauf und hängt diese wie ganz gewöhnliche Plattenpartitionen in Ihr Filesystem ein. Komfortabler geht's fast nicht. Ich schütze mit Hilfe von TrueCrypt unter anderem meine Backups auf einer externen Festplatte gegen unberechtigten Zugriff. Wenn Sie eine Einstiegshilfe benötigen, so mag Ihnen vielleicht der Beitrag "&lt;a href="http://www.heise.de/mobil/artikel/58723"&gt;Sicher aufbewahrt&lt;/a&gt;" von Andreas Beier (heise mobil, 2005-04-25) dienlich sein.&lt;br /&gt;&lt;br /&gt;Vor wenigen Tagen hat Björn Edström auf seinem Blog die Arbeitsweise von TrueCrypt erklärt. "&lt;a href="http://blog.bjrn.se/2008/01/truecrypt-explained.html"&gt;TrueCrypt explained&lt;/a&gt;" ist ein sehr lesenswerter Beitrag, besonders für diejenigen unter Ihnen, die TrueCrypt etwas detaillierter verstehen wollen. Der Beitrag ist auch ein schönes Anschauungsbeispiel dafür, dass solche Software im Prinzip gar nicht so komplex und schwer zu entwickeln ist, wie man vielleicht vermuten mag.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-677957971560715421?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/677957971560715421/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=677957971560715421' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/677957971560715421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/677957971560715421'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2008/01/truecrypt-entschlsselt.html' title='TrueCrypt &quot;entschlüsselt&quot;'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-8739121928353451716</id><published>2007-12-12T21:02:00.000+01:00</published><updated>2007-12-12T21:05:52.695+01:00</updated><title type='text'>Das 2 Millionen-Studium</title><content type='html'>2 Millionen Minuten -- so lange dauert ein vierjähriges Studium. Das rechnet uns der Filmemacher Robert A. Compton in seinem Film "&lt;a href="http://www.2mminutes.com/"&gt;Two Million Minutes&lt;/a&gt;" 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.&lt;br /&gt;&lt;br /&gt;Wenn Sie mögen, hier der Trailer:&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/niU1E3SSTAM&amp;rel=1&amp;border=0"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/niU1E3SSTAM&amp;rel=1&amp;border=0" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Ist es wirklich so schlimm? Heute hat die &lt;a href="http://www.bertelsmann-stiftung.de"&gt;Bertelsmann-Stiftung&lt;/a&gt; die Ergebnisse einer Repräsentativbefragung &lt;a href="http://www.bertelsmann-stiftung.de/cps/rde/xchg/SID-0A000F14-161D41AE/bst/hs.xsl/nachrichten_84386.htm"&gt;vorgestellt&lt;/a&gt;: "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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-8739121928353451716?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/8739121928353451716/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=8739121928353451716' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/8739121928353451716'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/8739121928353451716'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/12/das-2-millionen-studium.html' title='Das 2 Millionen-Studium'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-5912814825786751259</id><published>2007-12-09T12:43:00.000+01:00</published><updated>2007-12-09T12:45:33.296+01:00</updated><title type='text'>Googles Chart-API  und seine Nachhaltigkeit</title><content type='html'>Am Nikolaustag hat Google das Web um ein weiteres API (&lt;a href="http://en.wikipedia.org/wiki/API"&gt;Application Programming Interface&lt;/a&gt;) bereichert: das &lt;a href="http://code.google.com/apis/chart/"&gt;Chart-API&lt;/a&gt;. Der Gebrauch des APIs ist einfach und das Resultat schön anzusehen. Kein Wunder also, dass sich die &lt;a href="http://google-code-updates.blogspot.com/2007/12/embed-charts-in-webpages-with-one-of.html"&gt;Ankündigung&lt;/a&gt; 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&lt;br /&gt;&lt;code&gt;&lt;br /&gt;http://chart.apis.google.com/chart?cht=p3&amp;amp;chd=s:Uf9a&amp;amp;chs=200x100&amp;amp;chl=A|B|C|D"&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;ergibt sich der folgende visuelle Effekt:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://chart.apis.google.com/chart?cht=p3&amp;amp;chd=s:Uf9a&amp;amp;chs=200x100&amp;amp;chl=A|B|C|D"/&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://microformats.org/"&gt;Microformaten&lt;/a&gt; und Meta-Daten (z.B. in Form von &lt;a href="http://en.wikipedia.org/wiki/Tag_%28metadata%29"&gt;Tags&lt;/a&gt;) das Web mehr und besser um semantische Information bereichern als es die ganzen bisherigen Standardisierungsversuche des W3C zum &lt;a href="http://www.w3.org/2001/sw/"&gt;semantischen Web&lt;/a&gt; geschafft haben. Zumindest dann, wenn &lt;i&gt;Menschen&lt;/i&gt; bei der Erstellung von webfähigen Inhalten zur Anreicherung um semantische Informationen verleiten werden sollen.&lt;br /&gt;&lt;br /&gt;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?&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://gears.google.com/"&gt;Google Gears&lt;/a&gt; sind dabei ein Teil möglicher, brauchbarer Lösungsansätze.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-5912814825786751259?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/5912814825786751259/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=5912814825786751259' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5912814825786751259'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5912814825786751259'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/12/googles-chart-api-und-seine.html' title='Googles Chart-API  und seine Nachhaltigkeit'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-6719393960667002768</id><published>2007-12-06T09:18:00.000+01:00</published><updated>2007-12-06T09:18:29.522+01:00</updated><title type='text'>Körpersprache für Informatiker?</title><content type='html'>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.&lt;br /&gt;&lt;br /&gt;Stimmt alles! ;-)&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://www.youtube.com/v/x9YTxff3pHU&amp;rel=1"&gt;&lt;/param&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/x9YTxff3pHU&amp;rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Amüsiert frage ich mich, welche Berufsgruppe oder Menschengruppe solche Videos wirklich braucht -- die schon fast wieder gut sind, so schlecht wie sie sind.&lt;br /&gt;&lt;br /&gt;[Video entdeckt im "Mixing Memory"-Blog: "&lt;a href="http://scienceblogs.com/mixingmemory/2007/12/who_does_this_remind_you_of.php"&gt;Who Does This Remind You Of?&lt;/a&gt;" posted on: December 2, 2007 8:23 PM, by Chris.]&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-6719393960667002768?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/6719393960667002768/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=6719393960667002768' title='4 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6719393960667002768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6719393960667002768'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/12/krpersprache-fr-informatiker.html' title='Körpersprache für Informatiker?'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-7628532084021285372</id><published>2007-12-04T00:29:00.000+01:00</published><updated>2007-12-04T00:33:44.368+01:00</updated><title type='text'>Ein neuer Markt: Von Wissenschaftsblogs und Kunstgalerien</title><content type='html'>Liebe Wissenschaftsblogger,&lt;br /&gt;&lt;br /&gt;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!&lt;br /&gt;&lt;br /&gt;Aber ach, was red ich. Wollte ich Ihnen nicht eine Geschichte erzählen von einem Freund im Geiste, einem Künstler?&lt;br /&gt;&lt;br /&gt;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."&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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."&lt;br /&gt;&lt;br /&gt;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?"&lt;br /&gt;&lt;br /&gt;Der Künstler unterschrieb den Vertrag nicht. Er war froh, sich einen Rechtsbeistand geholt zu haben. Und so malte er weiter: frei!&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://www.wissenschafts-cafe.net/"&gt;Wissenschafts-Cafe&lt;/a&gt;! Man sieht sich ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-7628532084021285372?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/7628532084021285372/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=7628532084021285372' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/7628532084021285372'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/7628532084021285372'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/12/ein-neuer-markt-von-wissenschaftsblogs.html' title='Ein neuer Markt: Von Wissenschaftsblogs und Kunstgalerien'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-2206183266182843889</id><published>2007-11-28T16:39:00.000+01:00</published><updated>2007-11-28T20:08:18.736+01:00</updated><title type='text'>"Dienst oder Dienstmerkmal nicht möglich."</title><content type='html'>Letzte Woche war ich auf der &lt;a href="http://www.meduni-graz.at/imi/usab-symposium/"&gt;USAB 2007&lt;/a&gt; (Usability &amp; HCI for Medicine and Health Care; HCI steht für &lt;i&gt;Human Computer Interaction&lt;/i&gt;) und begeisterte mich an der Keynote von &lt;a href="http://www.cs.swan.ac.uk/~csharold/"&gt;Harold Thimbleby&lt;/a&gt;, der an der &lt;a href="http://www.swan.ac.uk/"&gt;Swansea University&lt;/a&gt; (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:&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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?&lt;br /&gt;&lt;br /&gt;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."&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Haben Sie ähnliche Erfahrungen gemacht? Wenn Sie mögen, berichten Sie mir davon!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-2206183266182843889?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/2206183266182843889/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=2206183266182843889' title='9 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2206183266182843889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2206183266182843889'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/11/dienst-oder-dienstmerkmal-nicht-mglich.html' title='&quot;Dienst oder Dienstmerkmal nicht möglich.&quot;'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-8008741023097652231</id><published>2007-11-24T02:12:00.000+01:00</published><updated>2007-11-24T02:12:50.091+01:00</updated><title type='text'>User, Domain and Realization Models</title><content type='html'>In my previous post on "&lt;a href="http://denkspuren.blogspot.com/2007/11/modeling-illusions.html"&gt;Modeling Illusions&lt;/a&gt;" I distinguished between the illusion, manifested by a &lt;i&gt;domain model&lt;/i&gt;, and the model that does the trick, the &lt;i&gt;realization model&lt;/i&gt;. The interesting question is: How do these two models relate to each other?&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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 &lt;i&gt;user model&lt;/i&gt; of the interface.&lt;br /&gt;&lt;br /&gt;So we are having three models: From an external viewpoint, we have a &lt;i&gt;user model&lt;/i&gt; 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 &lt;i&gt;domain model&lt;/i&gt;, describing the illusion from an inner perspective, or by a &lt;i&gt;realization model&lt;/i&gt;, an alternative description for the illusion.&lt;br /&gt;&lt;br /&gt;The relation between the models is as follows: In terms of size, better: information content, the following formula holds:&lt;br /&gt;&lt;br /&gt;user model &lt;= domain model &lt; realization model&lt;br /&gt;&lt;br /&gt;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 &lt;i&gt;by definition&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;By the way: User models are crucial in (User) Interface Design!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-8008741023097652231?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/8008741023097652231/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=8008741023097652231' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/8008741023097652231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/8008741023097652231'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/11/user-domain-and-realization-models.html' title='User, Domain and Realization Models'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-2898954750453356908</id><published>2007-11-19T12:17:00.000+01:00</published><updated>2007-11-19T12:56:12.493+01:00</updated><title type='text'>Modeling Illusions</title><content type='html'>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.&lt;br /&gt;&lt;br /&gt;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 "&lt;a href="http://computer.howstuffworks.com/hard-disk.htm"&gt;How Hard Disks Work&lt;/a&gt;"). 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 &lt;a href="http://en.wikipedia.org/wiki/B-tree"&gt;B-trees&lt;/a&gt; and similar stuff.&lt;br /&gt;&lt;br /&gt;The essence is: You have to distinguish an &lt;i&gt;illusion&lt;/i&gt; from it's &lt;i&gt;realization&lt;/i&gt;. What they share and have in common is the (user) &lt;i&gt;interface&lt;/i&gt;. It's the interface that creates an illusion!&lt;br /&gt;&lt;br /&gt;You got it? What I'm after is the following:&lt;br /&gt;&lt;br /&gt;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 &lt;i&gt;domain model&lt;/i&gt; of the illusion. The other model describes how the illusion was done; it unveals the trick of the "magician". It's a &lt;i&gt;realization model&lt;/i&gt; of the illusion. Others might also call it an "implementation model".&lt;br /&gt;&lt;br /&gt;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 &lt;i&gt;or&lt;/i&gt; 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.&lt;br /&gt;&lt;br /&gt;Let me give you a final example -- it also complements my criticism on "&lt;a href="http://denkspuren.blogspot.com/2007/10/sloppy-abstractions.html"&gt;The law of leaky abstractions&lt;/a&gt;": &lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-2898954750453356908?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/2898954750453356908/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=2898954750453356908' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2898954750453356908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2898954750453356908'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/11/modeling-illusions.html' title='Modeling Illusions'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-3549285938917265299</id><published>2007-11-15T21:44:00.000+01:00</published><updated>2007-11-15T22:15:18.602+01:00</updated><title type='text'>E8 und die "Theory of Everything"</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_XJMaba79IKU/Rzyx8upt7mI/AAAAAAAAACw/KCBugjhVAvQ/s1600-h/400px-E8_graph.svg.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_XJMaba79IKU/Rzyx8upt7mI/AAAAAAAAACw/KCBugjhVAvQ/s400/400px-E8_graph.svg.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5133173332168797794" /&gt;&lt;/a&gt;&lt;br /&gt;Das lässt Sie sicher auch stutzig werden, wenn Sie hören, jemand habe die "&lt;a href="http://en.wikipedia.org/wiki/Theory_of_Everything"&gt;Theory of Everything&lt;/a&gt;" 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.&lt;br /&gt;&lt;br /&gt;Nun will ein Surfer (nein, so ein Wasser-Surfer, der in Hawaii surft) genau diese Theorie gefunden haben, so berichtet der Telegraph in "&lt;a href="http://www.telegraph.co.uk/earth/main.jhtml?xml=/earth/2007/11/14/scisurf114.xml"&gt;Surfer dude stuns physicists with theory of everything&lt;/a&gt;" (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.&lt;br /&gt;&lt;br /&gt;Lisis Artikel hat den schlichten, anspruchsvollen Titel "&lt;a href="http://arxiv.org/abs/0711.0770"&gt;An Exceptionally Simple Theory of Everything&lt;/a&gt;", 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 &lt;a href="http://en.wikipedia.org/wiki/E8_%28mathematics%29"&gt;E8&lt;/a&gt; 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 &lt;i&gt;ad absurdum&lt;/i&gt; geführt werden kann.&lt;br /&gt;&lt;br /&gt;Jetzt bin ich doch gespannt, was die anderen "Surfer" (genau, die Physiker) dieser Welt dazu zu sagen haben. Ist unser Universum wirklich E8?&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://de.wikipedia.org/wiki/42_%28Antwort%29"&gt;42&lt;/a&gt;. Ich fürchte, Lisi muss nachbessern ;-)&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Update: Ich scheine mit "E" * 8 = 40 &lt;&gt; 42 nicht allein zu sein, wie ich gerade in einem &lt;a href="http://motls.blogspot.com/2007/11/exceptionally-simple-theory-of.html"&gt;anderen Blog&lt;/a&gt; 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.&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-3549285938917265299?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/3549285938917265299/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=3549285938917265299' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3549285938917265299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3549285938917265299'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/11/e8-und-die-theory-of-everything.html' title='E8 und die &quot;Theory of Everything&quot;'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_XJMaba79IKU/Rzyx8upt7mI/AAAAAAAAACw/KCBugjhVAvQ/s72-c/400px-E8_graph.svg.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-2025106718595273828</id><published>2007-11-08T16:10:00.000+01:00</published><updated>2007-11-19T13:01:08.800+01:00</updated><title type='text'>Mini-Laptops</title><content type='html'>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.&lt;br /&gt;&lt;br /&gt;Allmählich erinnern auch die PC-Hersteller an das große Fest. Heute schon gewünscht? Ich bin vor zwei, drei Tagen auf den &lt;a href="http://eeepc.asus.com"&gt;Eee PC&lt;/a&gt; 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 &lt;a href="http://www.heise.de/mobil/artikel/98366"&gt;heise mobil&lt;/a&gt;. Lieber noch hätte ich einen &lt;a href="http://laptop.org/"&gt;XO Laptop&lt;/a&gt;, 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 &lt;a href="http://www.laptopgiving.org/"&gt;an solch ein Gerät zu kommen&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Update 19. Nov.: Wie spannend, die Preise für ähnliche Produke beginnen zu purzeln, siehe "&lt;a href="http://www.heise.de/newsticker/meldung/99176"&gt;VIA und FIC wollen beim EeePC-Preis mithalten&lt;/a&gt;" (heise news, 2007-11-18).&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-2025106718595273828?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/2025106718595273828/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=2025106718595273828' title='3 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2025106718595273828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2025106718595273828'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/11/mini-laptops.html' title='Mini-Laptops'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-6358042685898227024</id><published>2007-11-01T19:06:00.000+01:00</published><updated>2007-11-01T19:21:35.454+01:00</updated><title type='text'>Hey Django!</title><content type='html'>Wie lässt sich zügig eine webbasierte Anwendung entwickeln, die auf einer relationalen Datenbank aufsetzt?&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://zoho.com"&gt;Zoho&lt;/a&gt; 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 &lt;a href="http://creator.zoho.com/"&gt;ZOHO Creator&lt;/a&gt;, eine vollständig browserbasierte Entwicklungsumgebung zum Bau von Datenbank-Anwendungen. Zoho wirbt mit einer kinderleichten Programmierung, die selbst Amateuren Erfolge bescheren soll.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.djangoproject.com"&gt;Django&lt;/a&gt; reiht sich ein in die Schlange der Frameworks, die "&lt;a href="http://www.rubyonrails.org/"&gt;Ruby on Rails&lt;/a&gt;" 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 &lt;a href="http://www.python.org"&gt;Python&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-6358042685898227024?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/6358042685898227024/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=6358042685898227024' title='5 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6358042685898227024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6358042685898227024'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/11/hey-django.html' title='Hey Django!'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-1010103971842885398</id><published>2007-10-29T10:58:00.000+01:00</published><updated>2007-10-29T11:17:47.132+01:00</updated><title type='text'>Billigflug: Gun Fighter</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_XJMaba79IKU/RyWyyWbiCsI/AAAAAAAAACo/mmWwYJ-fKyU/s1600-h/GunFighter.6.49Euro.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_XJMaba79IKU/RyWyyWbiCsI/AAAAAAAAACo/mmWwYJ-fKyU/s400/GunFighter.6.49Euro.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5126700328915438274" /&gt;&lt;/a&gt;&lt;br /&gt;Erinnern Sie sich noch an &lt;a href="http://de.wikipedia.org/wiki/Tetris"&gt;Tetris&lt;/a&gt;? 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 &lt;a href="http://en.wikipedia.org/wiki/Tetris_effect"&gt;Tetris-Effekt&lt;/a&gt;. 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: &lt;a href="http://www.sciam.com/article.cfm?articleID=0001F172-55DA-1C75-9B81809EC588EF21"&gt;Tetris Dreams&lt;/a&gt;, October 16, 2000.)&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Die Nacht schlief ich dann ganz normal. Keine Träume in Pixelgraphik. Schade.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-1010103971842885398?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/1010103971842885398/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=1010103971842885398' title='4 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1010103971842885398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1010103971842885398'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/10/billigflug-gun-fighter.html' title='Billigflug: Gun Fighter'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_XJMaba79IKU/RyWyyWbiCsI/AAAAAAAAACo/mmWwYJ-fKyU/s72-c/GunFighter.6.49Euro.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-3932113620910603729</id><published>2007-10-26T20:18:00.000+02:00</published><updated>2007-10-26T20:24:06.266+02:00</updated><title type='text'>Sloppy Abstractions</title><content type='html'>There is a very powerful engineering technique, computer scientists make also use of: abstraction. But did you know that abstractions can be leaky?&lt;br /&gt;&lt;br /&gt;I had heard about "The Law of Leaky Abstractions" some time ago; now, it again caught my attention, because Philip Wadler mentioned it &lt;a href="http://wadler.blogspot.com/"&gt;on his blog&lt;/a&gt;. Reason enough to read Joel Spolsky's post (written November 2002) more carefully.&lt;br /&gt;&lt;br /&gt;Spolsky's "&lt;a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html"&gt;Law of Leaky Abstractions&lt;/a&gt;" says&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;All non-trivial abstractions, to some degree, are leaky.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;He explains his "law" mainly on the example of the TCP protocol (his actor analogy is brilliant and funny) and concludes:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;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.&lt;br /&gt;[...]&lt;br /&gt;This is what I call a &lt;i&gt;leaky abstraction&lt;/i&gt;. 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.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;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?!&lt;br /&gt;&lt;br /&gt;If you forget that TCP might fail completely, you weren't that pedantic on understanding TCP. You were quite &lt;i&gt;sloppy&lt;/i&gt; with your abstraction -- that's all.&lt;br /&gt;&lt;br /&gt;The difference between a junior and a senior developer is that a senior doesn't have that many sloppy abstractions a junior has.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-3932113620910603729?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/3932113620910603729/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=3932113620910603729' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3932113620910603729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3932113620910603729'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/10/sloppy-abstractions.html' title='Sloppy Abstractions'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-5696449456267301659</id><published>2007-10-16T15:27:00.000+02:00</published><updated>2007-10-16T16:51:39.254+02:00</updated><title type='text'>Merk Dir mal ein Bit!</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_XJMaba79IKU/RxS7jdxdonI/AAAAAAAAACg/0Y9nw3ZnmFI/s1600-h/Kaffee2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_XJMaba79IKU/RxS7jdxdonI/AAAAAAAAACg/0Y9nw3ZnmFI/s400/Kaffee2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5121924894189003378" /&gt;&lt;/a&gt;&lt;br /&gt;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?&lt;br /&gt;&lt;br /&gt;Es gibt zwei Arten der Speicherung von Information. Ich möchte Ihnen das anschaulich an zwei Beispielen erläutern:&lt;br /&gt;&lt;br /&gt;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. &lt;br /&gt;&lt;br /&gt;Das ist das wohl am weitesten verbreitete Verständnis eines Informationsspeichers: in einem Gedächtnis (einer Art Riesenschatulle) kann Wissen "abgelegt" werden.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Wir haben also zwei Fälle vorliegen:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;Informationsträger ist Materie und örtlich gebunden (Raum)&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Informationsträger ist Energie und zeitlich gebunden (Fluß)&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Also: Legen Sie lieber ein Bit ins Gefrierfach! Auch dumme Hefe löscht den Durst!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-5696449456267301659?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/5696449456267301659/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=5696449456267301659' title='9 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5696449456267301659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5696449456267301659'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/10/merk-dir-mal-ein-bit.html' title='Merk Dir mal ein Bit!'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_XJMaba79IKU/RxS7jdxdonI/AAAAAAAAACg/0Y9nw3ZnmFI/s72-c/Kaffee2.jpg' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-1495399576148995383</id><published>2007-10-06T13:25:00.000+02:00</published><updated>2007-10-06T13:25:46.887+02:00</updated><title type='text'>Get Lively</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_XJMaba79IKU/RwdvwnC6tZI/AAAAAAAAACY/UFtL17fiqg0/s1600-h/livelykernelrl9.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_XJMaba79IKU/RwdvwnC6tZI/AAAAAAAAACY/UFtL17fiqg0/s320/livelykernelrl9.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5118182382435480978" /&gt;&lt;/a&gt;&lt;br /&gt;Yesterday (Friday, Oct 5, 2007), Dan Ingalls &lt;a href="http://lists.squeakfoundation.org/pipermail/squeak-dev/2007-October/121176.html"&gt;announced&lt;/a&gt; the &lt;a href="http://research.sun.com/projects/lively/"&gt;Sun Labs Lively Kernel&lt;/a&gt; on the squeak-dev mailing list. &lt;a href="http://www.squeak.org/"&gt;Squeak&lt;/a&gt; is an implementation of the &lt;a href="http://en.wikipedia.org/wiki/Smalltalk"&gt;Smalltalk&lt;/a&gt; programming language and &lt;a href="http://www.squeakland.org/community/biography/ingalls.html"&gt;Dan Ingalls&lt;/a&gt; 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.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;[...]&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;(http://research.sun.com/projects/lively/, 2007-10-06)&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;If you are interested in Dan Ingalls way of reasoning, read "&lt;a href="http://users.ipa.net/~dwighth/smalltalk/byte_aug81/design_principles_behind_smalltalk.html"&gt;The Design Principles Behind Smalltalk&lt;/a&gt;" -- 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: "&lt;a href="http://research.sun.com/techrep/2007/abstract-166.html"&gt;Web Applications - Spaghetti Code for the 21st Century&lt;/a&gt;".&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-1495399576148995383?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/1495399576148995383/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=1495399576148995383' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1495399576148995383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1495399576148995383'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/10/get-lively.html' title='Get Lively'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_XJMaba79IKU/RwdvwnC6tZI/AAAAAAAAACY/UFtL17fiqg0/s72-c/livelykernelrl9.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-6399825082718227504</id><published>2007-09-28T12:11:00.000+02:00</published><updated>2007-09-28T12:16:59.187+02:00</updated><title type='text'>Ur-Taschenrechner</title><content type='html'>Mögen Sie einen Blick in die Urzeit des Computerbaus werfen? Bei Spiegel-Online gibt es einen netten Beitrag dazu: "&lt;a href="http://www.spiegel.de/netzwelt/web/0,1518,508205,00.html"&gt;Der erste Taschenrechner wog 1,5 Kilo&lt;/a&gt;" (Konrad Lischka, 27. Sep. 2007). Schauen Sie sich mal die Bilder zu den alten Taschenrechnern an! Schaurig schön.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-6399825082718227504?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/6399825082718227504/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=6399825082718227504' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6399825082718227504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6399825082718227504'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/09/ur-taschenrechner.html' title='Ur-Taschenrechner'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-8702389019638763904</id><published>2007-09-26T23:38:00.000+02:00</published><updated>2007-09-26T23:44:51.274+02:00</updated><title type='text'>Vom Zählen und vom Sehen</title><content type='html'>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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-8702389019638763904?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/8702389019638763904/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=8702389019638763904' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/8702389019638763904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/8702389019638763904'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/09/vom-zhlen-und-vom-sehen.html' title='Vom Zählen und vom Sehen'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-8650935292675526548</id><published>2007-09-21T09:39:00.000+02:00</published><updated>2007-09-21T11:03:55.879+02:00</updated><title type='text'>Computer-basierte Beratung in der Medizin</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_XJMaba79IKU/RvOIyiqdRTI/AAAAAAAAACQ/3VBCHqSue3I/s1600-h/Beratungssystem.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_XJMaba79IKU/RvOIyiqdRTI/AAAAAAAAACQ/3VBCHqSue3I/s320/Beratungssystem.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5112580403875366194" /&gt;&lt;/a&gt;&lt;br /&gt;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. &lt;br /&gt;&lt;br /&gt;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 :-)&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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 &lt;i&gt;diabetes mellitus&lt;/i&gt; (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.&lt;br /&gt;&lt;br /&gt;Wir haben das System diese Woche (Ende September 2007) auf dem &lt;a href="http://www.ph-gmuend.de/gesundheit/"&gt;8. Kongress für Gesundheitspsychologie&lt;/a&gt; und dem 41. Kongress der &lt;a href="http://www.degam.de"&gt;Deutschen Gesellschaft für Allgemeinmedizin und Familienmedizin&lt;/a&gt; (DEGAM) vorgestellt und positives Feedback erhalten. Eine weitere Vorstellung wird es im November auf der &lt;a href="http://www.meduni-graz.at/imi/usab-symposium/"&gt;USAB 2007&lt;/a&gt; (Usability &amp; HCI for Medicine and Health Care) geben.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Für die Software-Techniker unter Ihnen: Über die software-technische Aspekte werde ich in einem späteren Blogeintrag berichten.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-8650935292675526548?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/8650935292675526548/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=8650935292675526548' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/8650935292675526548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/8650935292675526548'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/09/computer-basierte-beratung-in-der.html' title='Computer-basierte Beratung in der Medizin'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_XJMaba79IKU/RvOIyiqdRTI/AAAAAAAAACQ/3VBCHqSue3I/s72-c/Beratungssystem.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-4360645732031617981</id><published>2007-07-13T00:54:00.000+02:00</published><updated>2007-07-13T00:56:52.778+02:00</updated><title type='text'>Blogpause</title><content type='html'>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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-4360645732031617981?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/4360645732031617981/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=4360645732031617981' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/4360645732031617981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/4360645732031617981'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/07/blogpause.html' title='Blogpause'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-4589896111511293391</id><published>2007-07-02T09:49:00.001+02:00</published><updated>2008-04-15T20:17:27.136+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Object Model'/><category scheme='http://www.blogger.com/atom/ns#' term='Syntax'/><category scheme='http://www.blogger.com/atom/ns#' term='DOM'/><category scheme='http://www.blogger.com/atom/ns#' term='HTML'/><title type='text'>Editing and Persistence</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_XJMaba79IKU/RoQwDXriOrI/AAAAAAAAACA/J_5B3tgnGfI/s1600-h/LanguageEngineering.EditingAndPersistence.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_XJMaba79IKU/RoQwDXriOrI/AAAAAAAAACA/J_5B3tgnGfI/s400/LanguageEngineering.EditingAndPersistence.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5081239114035116722" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;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 &lt;i&gt;editing&lt;/i&gt; und &lt;i&gt;persistence&lt;/i&gt; in the context of an object model.&lt;br /&gt;&lt;br /&gt;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. &lt;a href="http://de.wikipedia.org/wiki/HTML"&gt;Wikipedia on HTML&lt;/a&gt; or any other of the hundreds of resource about HTML.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://www.csszengarden.com/"&gt;CSS Zen Garden&lt;/a&gt; -- the same content is presented in astonishingly different ways, just the CSS is exchanged.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;JavaScript is a programming language all browsers understand. With JavaScript you can manipulate HTML &lt;i&gt;and&lt;/i&gt; 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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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 &lt;i&gt;object model&lt;/i&gt; captures three aspects: form, style and syntax.&lt;br /&gt;&lt;br /&gt;We call the logical model of a language (like HTML) its &lt;i&gt;form&lt;/i&gt;. The form contains language conceptions and their relations. Together with a &lt;i&gt;syntax&lt;/i&gt; 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.&lt;br /&gt;&lt;br /&gt;To produce a projection, a visual representation of the form, the rendering engine processes the form and a &lt;i&gt;style&lt;/i&gt; definition -- something like CSS, for example. That's the way, how something appears on the screen.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;The upper part of our figures makes up what can be called &lt;i&gt;editing&lt;/i&gt;, the lower part realizes &lt;i&gt;persistence&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;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 &lt;i&gt;form&lt;/i&gt; and its textual notation its &lt;i&gt;syntax&lt;/i&gt;, 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.&lt;br /&gt;&lt;br /&gt;To summarize, what we discussed here:&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-4589896111511293391?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/4589896111511293391/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=4589896111511293391' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/4589896111511293391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/4589896111511293391'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/07/editing-and-persistence.html' title='Editing and Persistence'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_XJMaba79IKU/RoQwDXriOrI/AAAAAAAAACA/J_5B3tgnGfI/s72-c/LanguageEngineering.EditingAndPersistence.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-4954785329888072658</id><published>2007-06-26T01:00:00.000+02:00</published><updated>2007-06-26T01:04:13.413+02:00</updated><title type='text'>Kann man Programmieren lernen?</title><content type='html'>Kann man das Programmieren erlernen? Sicher! Aber kann es jeder erlernen?&lt;br /&gt;&lt;br /&gt;Ich bin über einen Blog auf einen interessanten Artikel gestossen ("&lt;a href="http://www.cs.mdx.ac.uk/research/PhDArea/saeed/paper1.pdf"&gt;The camel has two humps (working title)&lt;/a&gt;" von &lt;a href="http://www.cs.mdx.ac.uk/research/PhDArea/saeed/"&gt;Saeed Dehnadi&lt;/a&gt; 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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Zuweisungen und Zuweisungsfolgen&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Rekursion und Iteration&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Nebenläufigkeit&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;In einem Test stellen Dehnadi und Bornat den Studierenden &lt;i&gt;vor&lt;/i&gt; 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.&lt;br /&gt;&lt;br /&gt;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 &lt;i&gt;Konsistenten&lt;/i&gt;, beantwortet die meisten bis alle Fragen mit dem gleichen mentalen Modell; das sind die, die sich einer Maschine gleich an ein Regelwerk halten. Die &lt;i&gt;Inkonsistenten&lt;/i&gt; 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 &lt;i&gt;Blanken&lt;/i&gt; 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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;[...] it is extremely difficult to teach programming to the inconsistent and blank groups. It &lt;i&gt;might&lt;/i&gt; be possible to teach them, if we concentrated on trying to persuade them to see a programming language as a system of rules ([...]).&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-4954785329888072658?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/4954785329888072658/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=4954785329888072658' title='14 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/4954785329888072658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/4954785329888072658'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/06/kann-man-programmieren-lernen.html' title='Kann man Programmieren lernen?'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-5617767042070798748</id><published>2007-06-18T15:21:00.000+02:00</published><updated>2007-06-18T17:17:41.168+02:00</updated><title type='text'>Suchen mit Strategie</title><content type='html'>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 (&lt;i&gt;parent&lt;/i&gt;) und keinen oder mehr Nachfolger (&lt;i&gt;childs&lt;/i&gt;). Das ist sehr ähnlich zu DOM.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def query(criteria):&lt;br /&gt;    assert callable(criteria)&lt;br /&gt;    result = []&lt;br /&gt;    for element in allElements():&lt;br /&gt;        try:&lt;br /&gt;            if criteria(element) == True:&lt;br /&gt;                result.append(element)&lt;br /&gt;        except: pass&lt;br /&gt;    return result&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;query(lambda e: e.tag == "page")&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Dieser Aufruf sucht aus dem Objektmodell alle Objekte raus, die in der XML-Darstellung das Tag "page" tragen.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def query(criteria,strategy=yieldElements):&lt;br /&gt;    assert callable(criteria) and callable(strategy)&lt;br /&gt;    result = []&lt;br /&gt;    for element in strategy():&lt;br /&gt;        try:&lt;br /&gt;            if criteria(element) == True:&lt;br /&gt;                result.append(element)&lt;br /&gt;        except: pass&lt;br /&gt;    return result&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def yieldElements():&lt;br /&gt;    for klass in elementClasses:&lt;br /&gt;        for element in klass.instances:&lt;br /&gt;            yield element&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def yieldInnerElements(element):&lt;br /&gt;    def _yieldInnerElements():&lt;br /&gt;        def yieldInnerNodes(node):&lt;br /&gt;            for n in node.childs:&lt;br /&gt;                yield n&lt;br /&gt;                for child in yieldInnerNodes(n):&lt;br /&gt;                    yield child&lt;br /&gt;        return yieldInnerNodes(element)&lt;br /&gt;    return _yieldInnerElements&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Wieder ein Beispiel für eine Abfrage:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;query(lambda e: e.tag == "page",yieldInnerElements(chapterOne))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Eine interessante Einsicht ist, dass jede Strategie auch als Teil eines Kriteriums in &lt;i&gt;criteria&lt;/i&gt; 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 &lt;a href="http://denkspuren.blogspot.com/2006/12/constraint-programming.html"&gt;Constraint Programming&lt;/a&gt; sind kein Zufall!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-5617767042070798748?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/5617767042070798748/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=5617767042070798748' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5617767042070798748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5617767042070798748'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/06/suchen-mit-strategie.html' title='Suchen mit Strategie'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-2877081775026111605</id><published>2007-06-07T12:58:00.000+02:00</published><updated>2007-06-11T08:37:43.797+02:00</updated><title type='text'>Maschinelles 3D-Sehen</title><content type='html'>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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://www.3d-view.org"&gt;neue Technik des 3D-Sehens&lt;/a&gt;, 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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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. &lt;a href="http://www.mindhacks.com/blog/2007/06/learning_field_sense.html"&gt;Was unterscheidet einen Profi-Tennisspieler von einem normalen Tennisspieler?&lt;/a&gt; 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, &lt;i&gt;bevor&lt;/i&gt; der Ball den Schläger des Gegners verlässt und die Flugbahn berechnet werden kann.&lt;br /&gt;&lt;br /&gt;Ä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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-2877081775026111605?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/2877081775026111605/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=2877081775026111605' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2877081775026111605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/2877081775026111605'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/06/maschinelles-3d-sehen.html' title='Maschinelles 3D-Sehen'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-3952869135678144795</id><published>2007-05-02T01:18:00.000+02:00</published><updated>2007-05-02T01:19:07.243+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Zahlenspielerei</title><content type='html'>In meinem Blogeintrag "&lt;a href="http://denkspuren.blogspot.com/2007/04/hochstapelei.html"&gt;Hochstapelei&lt;/a&gt;" habe ich Ihnen gezeigt, wie sich rein mit den Mitteln der Objekt-Orientierung ein &lt;i&gt;Stack&lt;/i&gt; 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.&lt;br /&gt;&lt;br /&gt;Auf die gleiche Weise lassen sich auch die &lt;i&gt;natürlichen Zahlen&lt;/i&gt; 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.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Number(object):&lt;br /&gt;    def __init__(self,predecessor=None):&lt;br /&gt;        assert isinstance(predecessor,type(None)) or \&lt;br /&gt;               isinstance(predecessor,type(self))&lt;br /&gt;        self.predecessor = predecessor&lt;br /&gt;    def is_zero(self):&lt;br /&gt;        return isinstance(self.predecessor,type(None))&lt;br /&gt;    def inc(self):&lt;br /&gt;        return Number(self)&lt;br /&gt;    def dec(self):&lt;br /&gt;        assert not isinstance(self.predecessor,type(None)),\&lt;br /&gt;               "Number is not zero"&lt;br /&gt;        return self.predecessor&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Aus praktischen Gründen überschreiben wir die Gleichheitsmethode "__eq__" von Python, um den Vergleichsoperator "==" einsetzen zu können.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    def __eq__(self,number):&lt;br /&gt;        assert isinstance(number,type(self))&lt;br /&gt;        if self.is_zero() and number.is_zero(): return True&lt;br /&gt;        if self.is_zero() or  number.is_zero(): return False&lt;br /&gt;        return self.dec().__eq__(number.dec())&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Eine weitere Methode setzt den plus-Operator um. Die "__repr__"-Methode gibt eine geeignete Repräsentation eines Number-Objekts aus.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    def plus(self,number):&lt;br /&gt;        assert isinstance(number,type(self))&lt;br /&gt;        if number.is_zero(): return self&lt;br /&gt;        return self.inc().plus(number.dec())&lt;br /&gt;    def __repr__(self):&lt;br /&gt;        if self.is_zero(): return "0"&lt;br /&gt;        return "1+%s" % self.predecessor&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Wenn Sie ein wenig Zahlenspielerei mögen, dann tippern Sie doch auf der Console zum Beispiel Folgendes ein:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&gt;&gt;&gt; zero = Number()&lt;br /&gt;&gt;&gt;&gt; zero&lt;br /&gt;0&lt;br /&gt;&gt;&gt;&gt; one = zero.inc()&lt;br /&gt;&gt;&gt;&gt; one&lt;br /&gt;1+0&lt;br /&gt;&gt;&gt;&gt; two = one.inc()&lt;br /&gt;&gt;&gt;&gt; one == Number(Number())&lt;br /&gt;True&lt;br /&gt;&gt;&gt;&gt; one == Number().inc()&lt;br /&gt;True&lt;br /&gt;&gt;&gt;&gt; three = one.plus(two)&lt;br /&gt;&gt;&gt;&gt; three&lt;br /&gt;1+1+1+0&lt;br /&gt;&gt;&gt;&gt; five = three.plus(Number().inc().inc())&lt;br /&gt;&gt;&gt;&gt; five&lt;br /&gt;1+1+1+1+1+0&lt;br /&gt;&gt;&gt;&gt; five.dec()&lt;br /&gt;1+1+1+1+0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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?&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-3952869135678144795?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/3952869135678144795/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=3952869135678144795' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3952869135678144795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3952869135678144795'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/05/zahlenspielerei.html' title='Zahlenspielerei'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-5093596039139982657</id><published>2007-04-27T16:12:00.000+02:00</published><updated>2007-04-27T16:17:23.767+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Interfaces'/><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Hochstapelei</title><content type='html'>Wissen Sie, was ein &lt;i&gt;Stack&lt;/i&gt; 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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;LAST = -1&lt;br /&gt;&lt;br /&gt;class Stack1(object):&lt;br /&gt;    def __init__(self):&lt;br /&gt;        self.elements = []&lt;br /&gt;    def push(self,element):&lt;br /&gt;        self.elements.append(element)&lt;br /&gt;    def top(self):&lt;br /&gt;        assert not self.is_empty()&lt;br /&gt;        return self.elements[LAST]&lt;br /&gt;    def pop(self):&lt;br /&gt;        assert not self.is_empty()&lt;br /&gt;        self.elements.pop()&lt;br /&gt;    def is_empty(self):&lt;br /&gt;        return self.elements == []&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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 "&lt;a href="http://denkspuren.blogspot.com/2007/04/design-by-contract-in-practice.html"&gt;Design by Contract in Practice&lt;/a&gt;".&lt;br /&gt;&lt;br /&gt;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?&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Stack2(object):&lt;br /&gt;    def __init__(self,top=None,bottom=None):&lt;br /&gt;        assert (top,bottom) == (None,None) or \&lt;br /&gt;               isinstance(bottom,Stack2)&lt;br /&gt;        self.ontop, self.bottom = top, bottom&lt;br /&gt;    def push(self,element):&lt;br /&gt;        return Stack2(element,self)&lt;br /&gt;    def top(self):&lt;br /&gt;        assert not self.is_empty()&lt;br /&gt;        return self.ontop&lt;br /&gt;    def pop(self):&lt;br /&gt;        assert not self.is_empty()&lt;br /&gt;        return self.bottom&lt;br /&gt;    def is_empty(self):&lt;br /&gt;        return self.bottom == None&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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".&lt;br /&gt;&lt;br /&gt;Dieses Beispiel zeigt zwei Dinge schön auf:&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-5093596039139982657?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/5093596039139982657/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=5093596039139982657' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5093596039139982657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/5093596039139982657'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/04/hochstapelei.html' title='Hochstapelei'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-1882201455924874031</id><published>2007-04-13T00:16:00.000+02:00</published><updated>2007-04-13T00:18:37.601+02:00</updated><title type='text'>Breakpoint mit Farbrausch</title><content type='html'>Haben Sie auch schon von "Breakpoint 2007" gehört? Vorgestern machte mich Herr Arz auf die Meldung bei golem aufmerksam ("&lt;a href="http://www.golem.de/0704/51616.html"&gt;Breakpoint 2007 - Gewinner der Demo-Party stehen fest&lt;/a&gt;", 11. April 2007). Das Team "&lt;a href="http://www.farbrausch.de"&gt;Farbrausch&lt;/a&gt;" 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!&lt;br /&gt;&lt;br /&gt;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!&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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 &lt;em&gt;generellen&lt;/em&gt; Techniken zur Kompression von Bildflächen. Was die Hacker da treiben, ist nur zu erreichen mit einer &lt;em&gt;domänenspezifischen&lt;/em&gt; 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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-1882201455924874031?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/1882201455924874031/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=1882201455924874031' title='5 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1882201455924874031'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/1882201455924874031'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/04/breakpoint-mit-farbrausch.html' title='Breakpoint mit Farbrausch'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-7665485465488932598</id><published>2007-04-10T23:57:00.000+02:00</published><updated>2007-04-11T00:13:17.156+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Design by Contract'/><title type='text'>Design by Contract in Practice</title><content type='html'>Design by Contract (DbC) is a very valuable specification technique -- I already posted about it in German (&lt;a href="http://denkspuren.blogspot.com/2006/08/netze-spannen-mit-design-by-contract.html"&gt;Netze spannen mit Design by Contract&lt;/a&gt;). However, you should be aware that DbC also tends to complicate matters if state is involved. In this case, we need a complementing approach.&lt;br /&gt;&lt;br /&gt;To give you a simple example, have a look at a thing called "Account". The "Account" is purely specified via pre- and post-conditions (&lt;em&gt;require&lt;/em&gt; and &lt;em&gt;ensure&lt;/em&gt;); "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.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Account(object):&lt;br /&gt;    ensure: self.balance == 0&lt;br /&gt;    def __init__(self)&lt;br /&gt;&lt;br /&gt;    require: 0 &lt; amount &lt;= self.balance&lt;br /&gt;    context: balance = self.balance&lt;br /&gt;    ensure: self.balance == balance - amount&lt;br /&gt;    def withdraw(self,amount)&lt;br /&gt;&lt;br /&gt;    require: amount &gt; 0&lt;br /&gt;    context: balance = self.balance&lt;br /&gt;    ensure: self.balance == balance + amount&lt;br /&gt;    def deposit(self,amount)&lt;br /&gt;        &lt;br /&gt;    context: balance = self.balance&lt;br /&gt;    ensure: res == balance&lt;br /&gt;    def query(self)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Now let us add an implementation fulfilling the contracts. It's quite straight forward.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Account(object):&lt;br /&gt;    ensure: self.balance == 0&lt;br /&gt;    def __init__(self):&lt;br /&gt;        self.balance = 0&lt;br /&gt;&lt;br /&gt;    require: 0 &lt; amount &lt;= self.balance&lt;br /&gt;    context: balance = self.balance&lt;br /&gt;    ensure: self.balance == balance - amount&lt;br /&gt;    def withdraw(self,amount):&lt;br /&gt;        self.balance -= amount&lt;br /&gt;        &lt;br /&gt;    require: amount &gt; 0&lt;br /&gt;    context: balance = self.balance&lt;br /&gt;    ensure: self.balance == balance + amount&lt;br /&gt;    def deposit(self,amount):&lt;br /&gt;        self.balance += amount&lt;br /&gt;        &lt;br /&gt;    context: balance = self.balance&lt;br /&gt;    ensure: res == balance&lt;br /&gt;    def query(self):&lt;br /&gt;        return self.balance&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Account(object):&lt;br /&gt;    def __init__(self):&lt;br /&gt;        self.balance = 0&lt;br /&gt;&lt;br /&gt;    require: 0 &lt; amount &lt;= self.balance&lt;br /&gt;    def withdraw(self,amount):&lt;br /&gt;        self.balance -= amount&lt;br /&gt;&lt;br /&gt;    require: amount &gt; 0&lt;br /&gt;    def deposit(self,amount):&lt;br /&gt;        self.balance += amount&lt;br /&gt;&lt;br /&gt;    def query(self):&lt;br /&gt;        return self.balance&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That's easy and lightweight, isn't it?&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-7665485465488932598?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/7665485465488932598/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=7665485465488932598' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/7665485465488932598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/7665485465488932598'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/04/design-by-contract-in-practice.html' title='Design by Contract in Practice'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-6383719484735520189</id><published>2007-04-05T00:32:00.000+02:00</published><updated>2007-04-05T00:33:38.645+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Von Beruf Software Engineer</title><content type='html'>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:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;mehr Konzeption von Software: Anforderungen, Modellierung&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Software aus Komponenten “zusammenstecken”, Code-Generierung&lt;/li&gt;&lt;br /&gt;&lt;li&gt;mehr Planung und Organisation von Software-Projekten&lt;/li&gt;&lt;br /&gt;&lt;li&gt;viel Planung und Kommunikation mit Kunden&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Hohe Qualitätssicherung bei Outsourcing der Programmierung&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Teamarbeit: internationale, verteilte Arbeit und Kommunikation&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Pflege, Weiterentwicklung, Optimierung von Altsystemen&lt;/li&gt;&lt;br /&gt;&lt;li&gt;sicherer Arbeitsplatz: es entsteht immer mehr Software =&gt; Wartung&lt;/li&gt;&lt;br /&gt;&lt;li&gt;neue Technologien, da HW immer leistungsfähiger wird&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Entwicklung mit leistungsfähigen CASE-Werkzeugen und IDEs&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Fortschritte in HMI, Webtechnologie, KI, Virtual Reality, …&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Notwendigkeit ständiger Weiterbildung&lt;/li&gt;&lt;br /&gt;&lt;li&gt;es wird eine neue Programmiersprache geben =&gt; weniger Fehler&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Agile Softwareentwicklung als Standard&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;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 ("&lt;a href="http://www.heise.de/tp/r4/artikel/24/24888/1.html"&gt;Von der Notwendigkeit, sich in abstrakten Welten bewegen zu können&lt;/a&gt;", 28. März 2007). Ein, wie ich glaube, lesenswerter Artikel.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;--&lt;br /&gt;&lt;span style="font-style:italic;"&gt;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)&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-6383719484735520189?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/6383719484735520189/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=6383719484735520189' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6383719484735520189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/6383719484735520189'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/04/von-beruf-software-engineer.html' title='Von Beruf Software Engineer'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-3367939451699614781</id><published>2007-03-28T00:44:00.000+02:00</published><updated>2007-03-28T00:50:12.277+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Softwarearchitektur'/><title type='text'>Was ist Software-Architektur?</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_XJMaba79IKU/Rgme2IyXwRI/AAAAAAAAABg/3acanOzN3xY/s1600-h/WasIstSWA.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_XJMaba79IKU/Rgme2IyXwRI/AAAAAAAAABg/3acanOzN3xY/s400/WasIstSWA.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5046739510354231570" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Die Architektur ist die ökonomischste Form der Beschreibung "innerer" Anforderungen, die nicht mit der Implementierung des Systems identisch ist.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Architektur ist Ausdruck der "internen" Anforderungen&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Architektur unterliegt ökonomischen Antriebskräften&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Komponenten-Orientierung und Sichtkonzepte greifen als Modellierungsparadigmen für Architekturen zu kurz&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Modellierungsansätze müssen Domänen-Modelle integrieren&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Es fehlt eine Methodik zur Architekturmodellierung&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5556918437810598389-3367939451699614781?l=denkspuren.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://denkspuren.blogspot.com/feeds/3367939451699614781/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5556918437810598389&amp;postID=3367939451699614781' title='3 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3367939451699614781'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5556918437810598389/posts/default/3367939451699614781'/><link rel='alternate' type='text/html' href='http://denkspuren.blogspot.com/2007/03/was-ist-software-architektur.html' title='Was ist Software-Architektur?'/><author><name>dh</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_XJMaba79IKU/Rgme2IyXwRI/AAAAAAAAABg/3acanOzN3xY/s72-c/WasIstSWA.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5556918437810598389.post-5681364985383985157</id><published>2007-03-26T12:21:00.000+02:00</published><updated>2007-03-26T12:23:23.433+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Object Model'/><category scheme='http://www.blogger.com/atom/ns#' term='Alan Kay'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>"Open, reusable object models" in Python</title><content type='html'>It's roughly three or four weeks ago that I read an interview with &lt;a href="http://en.wikipedia.org/wiki/Alan_Kay"&gt;Alan Kay&lt;/a&gt; ("&lt;a href="http://www.cioinsight.com/print_article2/0,1217,a=200162,00.asp"&gt;Alan Kay: The PC Must Be Revamped—Now&lt;/a&gt;", CIO Insight, Feb 14, 2007). I found it quite inspiring, began
