Follow my new blog

Dienstag, 24. September 2013

Bye, bye, function. Hello, transformer!

Funktionen sollten nicht länger die kleinsten Bausteine unseres Codes sein. Sie vermengen nämlich zwei Aspekte: Kontrollfluss und Datenfluss.

Wenn eine Funktion die Kontrolle aufgibt, dann fließen Daten aus ihr heraus. Sie kann danach die Kontrolle nicht zurückbekommen. Erst ein erneuter Aufruf überträgt Kontrolle wieder an sie.

Wenn Daten aus einer Funktion fließen sollen, dann muss sie die Kontrolle aufgeben. Sie kann keine Zwischenergebnisse zur Weiterverarbeitung liefern.

Kontrolle und Daten fließen mit Funktionen also immer gleichzeitig. Das ist oft ok – aber eben nicht immer. Indem wir diese Aspektkopplung jedoch so tief in unseren Sprachen verankert haben, fällt es uns schwer, anders zu denken. Das halte ich aber für nötig, wenn wir evolvierbarere Software herstellen wollen.

Funktionen sind ein Relikt aus der Anfangszeit der Programmierung. Sie sind syntactic sugar für Maschinencodebefehle, die nicht nur ein Unterprogramm aufrufen (CALL), sondern auch noch anschließen ein Resultat für den Aufrufer bereitstellen. Dabei gibt es immer nur einen Punkt, an dem die Kontrolle ist: den Befehl, auf den der eine Befehlszeiger weist. Daten sind in diesem Paradigma wie Hunde, die ihrem Herrchen an der Leine folgen müssen. Sie können immer nur am selben Ort in Verarbeitung gedacht werden, wo auch gerade die eine Kontrolle ist.

Das ist alles wunderbar und verständlich. Das hatte seine lange Zeit. Doch ich glaube, wir sollten jetzt darüber hinaus gehen. Dadurch wird dieses Paradigma nicht überflüssig. Die Newtonsche Physik gilt ja auch weiterhin. Aber wir denken dann nicht mehr, dass alles nur mit diesen Mitteln erklärt und beschrieben werden muss. Die relativistische Physik umfasst die Newtonsche. So sollte auch ein neues Paradigma das bisherige umschließen.

Ist da schon alles mit der Funktionalen Programmierung gesagt? Hm… Nein, ich glaube, nicht. In der steckt ja schon im Namen die Funktion, also das, was wir überwinden sollten.

Aber wie können Kontrollfluss und Datenfluss entkoppelt werden? Mit Continuations bzw. Observern.

Aus einer Funktion

R f(P p) {
  …
  return r;
}

würde z.B. eine Prozedur wie

void f(P p, Action<R> continueWith) {
  …
  continueWith(r);
}

Diese Prozedur hat alle Freiheiten, Kontroll- und Datenfluss zu entkoppeln:

  • Sie kann ein Resultat via continueWith() liefern und dann die Kontrolle aufgeben – oder auch nicht.
  • Sie kann entscheiden, überhaupt ein Resultat zu liefern.
  • Sie kann sogar entscheiden, mehrfach ein Resultat zu liefern.
  • Und schließlich ist eine solche Prozedur auch nicht darauf festgelegt, nur über einen “Kanal” Daten zu liefern.

void f(P p, Action<R> onR, Action<T> onT) {
  …
  onR(r);
  …
  onT(t);
  …
}

Solange der Name der Continuation auf die Prozedur bezogen ist, erhält sie keine Information über den Kontext der Weiterverarbeitung ihres Output. Wie eine Funktion erfüllt sie damit das Principle of Mutual Oblivion (PoMO).

Ich nenne so ein Unterprogramm Transformator. Funktion impliziert gleichzeitigen Kontroll- und Datenfluss. Transformator ist als Begriff hingegen noch nicht verbrannt. Und irgendetwas gibt es ja immer zu transformieren, oder? Zahlen in andere Zahlen, Zeichenketten in andere Zeichenketten oder Zahlen in Zeichenketten oder Zeichenketten in Wahrheitswerte oder in-memory Daten in persistente Daten usw. usf.

Unsere Programmiersprachen sind natürlich für den Umgang mit Funktionen optimiert:

var y = f(x);
var z = g(y);
h(z);

Das lässt sich leicht hinschreiben und lesen. Aber leider ist es begrenzt in seiner Ausdrucksfähigkeit, weil eben Kontrolle und Daten immer gleichzeitig fließen müssen.

Die Alternative mit Transformatoren ist nicht so schön, ich weiß:

f(x, y =>
g(y,
h));

Mit ein wenig Übung kann man das allerdings auch flüssig lesen und hinschreiben. Aber es ist zumindest ungewohnt. Schöner wäre es, wenn man z.B. schreiben könnte:

f –> g –> h

In F# geht das ähnlich – allerdings nur für Funktionen. Bei aller Fortschrittlichkeit ist man auch dort dem alten Paradigma verhaftet. Es sitzt tief in uns.

Wie eine Lösung aussehen kann, weiß ich auch nicht. In meiner Entwicklung von Funktionen hin zu Transformatoren möchte ich mich dadurch aber nicht beschränken lassen. Denken kann ich Transformatoren, visuell darstellen kann ich Transformatoren, codieren kann ich Transformatoren. Da wird sich doch auch eine textuelle Notation finden lassen, oder?

Der Pfeil scheint mir ein passender Operator, wenn mit Transformatoren nun Datenflüsse in den Blick kommen. Vielleicht könnten dann mehrere Flüsse so notiert werden:

f.onR –> g.onY –> h,
f.onT –> m,
g.onZ –> n;

Das Diagramm dazu wäre:

image

Das ist wunderbar übersichtlich. Der heutige C#-Code hinkt leider hinterher:

f(x, r =>
  g(r,
    h,
    n),
  m);

Aber ich bin unverdrossen. Den Übergang von Funktionen zu Transformatoren halte ich für wichtig. Wir lösen uns damit aus der Umklammerung der von-Neumann-Maschinen. Nicht Kontrolle ist wichtig, sondern Resultate, d.h. der Fluss von Daten.

Kontrolle kann in mehreren Transformatoren gleichzeitig sein. Oder Kontrolle kann vor uns zurück springen, wenn sie denn nur an einem Ort zur Zeit sein kann.

Die Funktion als Werkzeug wird damit nicht überflüssig, sondern nur als Sonderfall neu positioniert. Transformatoren können sich wie Funktionen verhalten, wenn es sein muss. Können, müssen aber nicht. Und das find ich so wichtig. Mit Transformatoren ist entkoppelt, was nicht zwangsläufig zusammengehört. Freiheit für die Daten!

Sonntag, 22. September 2013

Nie mehr ohne – Das Kondom fürs iPhone

Einer der letzten Smartphone-freien Orte war bisher die Dusche. Das ist nun vorbei. Denn jetzt gibt es das Kondom fürs iPhone, genannt SmartSkin.

image

Ich habe es von meiner Freundin und Kollegin Andrea Kaden geschenkt bekommen, die als Anhängerin der Papierlosigkeit keinen Bereich auslässt. (Als hätte ich sonst mit Papierbergen im Bad zu kämpfen… ;-) Und so habe ich denn heute das erste Mal mit Musik geduscht:

image

Der Überzieher hält dicht. Soweit die gute Nachricht. Für die Dusche reicht das. Auch fürs Lesen in der Badewanne. Wahrscheinlich kann das iPhone auch ins Wasser fallen, ohne Schaden zu nehmen. Ausprobiert habe ich das aber nicht.

Wie bei sonstigen Kondomen ist dieser Überzieher wahrscheinlich eher für den einmaligen Gebrauch gedacht. Man kann ihn solange aufgezogen lassen, bis das iPhone wieder geladen werden muss. Dann muss er runter, denn eine Öffnung für den Ladestecker ist natürlich nicht vorgesehen.

Aber wenn man vorsichtig ist, leiert die Kunststoffhülle nicht zu sehr aus. Dann kann das iPhone Kondom auch mehrfach zum Einsatz kommen. Ob das jedoch im Sinne des Erfinders ist…? Ich weiß nicht.

Das Aufziehen ist einfach. Üben an einem “Surrogat” wie bei anderen Kondomen entfällt:

imageimageimage

imageimage

Am Schluss wird die Öffnung auf der Rückseite des iPhones mit einem Klebestreifen verschlossen. Dessen Klebefähigkeit scheint mir der Schwachpunkt für mehrfachen Gebrauch.

Nun wünsche ich allen iPhone-Freunden eine gute Zeit unter der Dusche mit ihrem Liebling :-) War das nicht immer euer Traum? Es unter der Dusche tun… Lesen, Musik hören oder ein Hörbuch oder eine Diashow ablaufen lassen…? Es tun sich ungeahnte Erlebnisse auf!