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!

Donnerstag, 22. August 2013

Kinderleicht eine Programmiersprache lernen – Das Nostalgie-eBook

imageIch hatte das Buch echt vergessen, das ich 1985 geschrieben hatte. Jetzt ist es mir beim Ausmisten meiner Regale in die Hand gefallen. 220 Manuskriptseiten ausgedruckt auf einem Nadeldrucker. Wahnsinn!

Damals war ich noch beseelt vom Informatikunterricht in der Schule, den ich zwei Jahre zuvor mit dem Abi hinter mir gelassen hatte. Und seitdem war ich mächtig auf einem Apple II mit Z-80 Karte und CP/M zugange. Dort konnte ich mit Turbo Pascal fortsetzen, was wir auf einer Dietz Mehrplatzanlage mit Bernsteinmonitoren angefangen hatten. Seufz… Sweet memories…

imageSo hatte ich begonnen – zunächst mit meinem Schulfreund Helge Baumann –, eine Anleitung zum Programmieren für Pascal zu schreiben. Die trockenen, eher akademischen Bücher, die ansonsten verfügbar waren, schienen ungeeignet für den Schulgebrauch. Wenn ich mich recht erinnere, hatten wir im Unterricht auch kein Lehrbuch.

1983 oder so begonnen, dauerte es allerdings bis 1985, um das Werk fertigzustellen. Abitur, Bundeswehr, Studiumsbeginn in Hamburg und Liebeskummer hielten die Arbeit am Manuskript immer wieder auf.

Irgendwie habe ich es dann aber doch geschafft. Nur gelangte der Text dann weder an meine alte Schule, noch zu einem Verlag, der ihn hätte veröffentlichen wollen. Teubner war zwar grundsätzlich interessiert an mir als Autor, nur nicht mit dem Thema und der Form. Und so ist das Manuskript in einem Ordner geblieben und mehrfach umgezogen.

image

Das Ziel damals war, eine Einführung in die Programmierung für eine populäre, nicht akademische Programmiersprache zu liefern, die auch den Laien anspricht. Alles sollte ganz einfach und konkret beschrieben werden. In kleinen Schritten.

imageDie Beispielprogramme sollten durchaus ganze Anwendungen sein, nicht nur Algorithmen. Und auch der Entwurf und die Lesbarkeit von Software waren wichtig. Deshalb gibt es viele Struktogramme. Niedlich, oder? Aber das war damals state-of-the-art.

Vor allem aber sollte die Sprache entspannt sein und der Text durch Bilder aufgelockert werden. So finden sich im Manuskript denn auch mehr als 60 liebevoll von Hand gezeichnete Illustrationen.

Die in den Text zu bringen, war 1985 nicht einfach. Da gab es keine Textverarbeitungsprogramme wie Word, auch keinen Scanner, keine Grafiksoftware. Also habe ich im Text beim Schreiben Platz für die Zeichnungen gelassen und sie nach dem Ausdruck direkt aufs Blatt gezeichnet. Wenn ich mir überlege, wieviel Mühe das gemacht haben muss… Aber ich kann mich nicht mehr daran erinnern.

image

Und nun liegt es nach 28 Jahren wieder vor mir. Fühlt sich ein Stück wie ein fremdes Buch an. Aber wenn ich dann drin lese, merke ich natürlich schon, dass das von mir ist ;-) Vieles hat sich seitdem verändert an mir, aber eben nicht alles.

imageSpannend finde ich, dass mir das Manuskript wirklich entfallen ist. Anfang der 2000er, als ich einige Bücher zu .NET und Datenbankprogrammierung geschrieben habe, war mir, als hätte ich noch nie so lange Texte entwickelt.

Heute schaue ich sogar ein wenig neidisch auf mein früheres Selbst. Wie hat der das geschafft, der damalige Ralf, diese Ausdauer aufzubringen? Mir macht es heute große Schwierigkeiten, Texte von mehr als 50-60 Seiten zu schreiben. Dabei wäre das sehr nötig, um mal eine kompakte und kohärente Darstellung von Flow-Design anbieten zu können.

Durch das Schreiben von Artikeln und Blogpostings bin ich aber so auf kurze Texte getrimmt, dass mir immer wieder der Atem für Längeres fehlt. Ich muss mich wohl noch ein bisschen mehr anstrengen. Vielleicht macht mir der Manuskriptfund in einem Regal ja Mut. Oder ich finde eine Form für die Darstellung, die zu meiner Ausdauer passt.

image

Nach soviel Schwelgen in Erinnerungen hier nun aber meine ambitionierte Einführung in die Programmierung mit Turbo Pascal. Zum Schmunzeln und als Anregung für Ausflüge in die eigene Vergangenheit.

Mit den heutigen Möglichkeiten ist es nun kein Problem mehr, so ein Manuskript zu veröffentlichen. Ich könnte mittels lulu.com auch in wenigen Stunden ein Papierbuch machen, das “der geneigte Leser” dann online erstehen kann. Wahnsinn, wie weit wir in den letzten 28 Jahren gekommen sind.

imageUnd andererseits… Wahnsinn, wieviel dann doch bei der Programmierung gleich geblieben ist. Die Syntax hat sich verändert - Java, C#, JS statt Pascal –, auch das Programmierparadigma ist anders – objektorientiert statt prozedural – dennoch stehen Menschen, die ins Programmieren einsteigen wollen, vor denselben Problemen. Mit einer Programmiersprache statt mit Hammer oder Pinsel umzugehen, ist eine ganz eigene Herausforderung.

Und da unter den aktuellen Sprachen immer noch grundsätzlich dieselben Konzepte liegen wie damals… Vielleicht könnte der Text dem einen oder anderen Programmieranfänger auch heute noch mit seiner Anschaulichkeit helfen.

Viel Spaß beim Durchblättern!

Pascal - Eine kinderleichte Einführung by Ralf Westphal

P.S. Wer mag, kann übrigens die Einführung online mitprogrammieren. Hier ein Beispiel aus dem Text ausgeführt in der online IDE http://www.compileonline.com/compile_pascal_online.php:

image

P.P.S. Natürlich ist mir aufgefallen, dass die Sprache bzw. der Dialekt, mit dem ich damals programmiert habe vom selben Erfinder stammt wie die Sprache, mit der ich heute arbeite. Turbo Pascal wie C# sind von Anders Hejlsberg.

Ob das aber auch für die Sprache gelten wird, mit der ich in 28 Jahren arbeite…? Ich bezweifle es. Abe wer weiß… ;-)

Mittwoch, 14. August 2013

Vom Nutzen und Nachteil (technischer) Schulden

Gerade habe ich einen Beitrag von Norbert Eder zum Thema “Technische Schulden” (technical debt) gelesen. Er fragt, wer denn schuld sei an den Schulden.

Sich darüber Gedanken zu machen, finde ich nicht falsch. Aber wie bei anderen Artikeln zum Thema erscheint mir die Darstellung leider einseitig. Vielleicht entspricht das der aktuellen Stimmung im Land, die vieles was mit (Geld-)Schulden zu tun hat, sehr skeptisch sieht?

Doch wir sollten uns von diesen großen Problemen mit Schulden nicht ins Bockhorn jagen lassen.

Schulden sind nicht per se schlecht.

Die Möglichkeit, Schulden machen zu können, ist vielmehr die Grundlage für eine entwicklungsfähige Zivilisation.

Was sind Schulden?

Schulden sind eine Vorwegnahme von Möglichkeiten. Eigentlich habe ich heute eine gewisse Möglichkeit nicht - aber indem ich Schulden mache, habe ich sie dann doch.

Beispiele:

Ich kann mir heute kein Auto kaufen, weil ich nicht genug Geld habe? Dann leihe ich mir Geld - ich mache Schulden - und kann mir doch ein Auto kaufen. Später zahle ich das Geld zurück.

Oder: Eigentlich habe ich keine Zeit, spät nachts einen Film zu schauen. Ich müsste schlafen, um morgen fit zu sein. Aber ich schaue doch den Film, nehme also “Zeitschulden” auf, die ich morgen zurückzahle. Entweder Zahle ich sie morgen durch längeren Schlaf zurück. Oder ich zahle sie in Form von weniger Fitness zurück.

Oder: Wenn ich lange gesund leben will, sollte ich z.B. nicht rauchen. Wenn ich es doch tue, dann habe ich jetzt vielleicht mehr Lebensqualität - die ich später aber mit weniger oder gar keinem Leben bezahle.

Solche Ermöglichungen im hier und jetzt haben natürlich ihren Preis. Jetzt Geld, Aufmerksamkeit, Lebensqualität zu haben, kostet in der Zukunft Geld, Aufmerksamkeit, Lebensqualität. Und zwar mehr als ich jetzt bekomme.

Aber das mag es mir ja wert sein. Aus welchen Gründen auch immer.

Wer Schulden macht, handelt ökonomisch.

Schulden eröffnen Chancen

Viele Chancen im Leben erfordern mehr Möglichkeiten als wir gerade haben. Wenn wir sie wahrnehmen wollen, müssen wir Schulden machen.

Beispiele:

Nur wenn ich jetzt ein Auto habe, kann ich einen bestimmten Job bekommen, der mir die Chance auf eine Karriere bietet. Wenn ich keine Schulden machen kann, geht mir die Chance durch die Lappen.

Eigentlich will ich nach Hause gehen, um zu schlafen, damit ich morgen Fit bin im neuen Job. Aber da begegnet mir eine tolle Frau: das ist eine Chance auf schöne weitere Stunden oder gar eine glückliche Partnerschaft. Wenn ich jetzt keine Schulden bei meiner Energie und Aufmerksamkeit machen kann, geht mir diese Chance durch die Lappen.

Während die Rückzahlung von Schulden meist in derselben Währung stattfindet, liegen die Chancen eher in anderen Bereichen. Aus Geld-Schulden wird eine Karriere, aus Energieschulden wird Verliebtheit, aus Nikotinabhängigkeit wird Gemeinschaftsgefühl.

Wer Schulden macht, der sucht sein Glück.

Auf das Maß kommt es an

Alles hat sein bekömmliches Maß, auch Schulden.

Schulden machen zu können, also ökonomische Entscheidungen durch die Verschiebung von Möglichkeiten in Bezug auf sein Glück treffen zu können, das ist grundsätzlich eine gute Sache.

Doch wenn man das unbedacht tut, dann kann man sich auch ins Unglück stürzen. Das passiert, wenn man seine Kapazität zur Rückzahlung von Schulden überschätzt. Nicht bei jeder Schuld ist auch klar, wie hoch ihr Preis ist.

Bei einem Kredit für´s Auto ist der Preis klar, aber die Entwicklung der Karriere vielleicht nicht. Beim Zigarettengenuss ist weder der genaue Preis, noch die Entwicklung der “Rückzahlungsfähigkeit” klar.

Man tut also gut daran, genau hinzuschauen, welche Schulden man wann zu welchem Preis aufnimmt.

Und man tut gut daran, die Rückzahlung zu planen, damit sie einen nicht zur Unzeit erwischt. Gewöhnlich steigt auch der Preis der Schulden, je länger die Rückzahlung aufgeschoben ist. Der Schuldiger fordert sein Recht; die Schuld, die Ermöglichung heute geht auf seine Kosten. Sei das eine Bank oder der eigene Körper.

Schulden erfordern Bewusstsein und Maßhaltung

Technische Schulden

Für technische Schulden gilt natürlich dasselbe wie für alle anderen Schulden auch.

Technische Schulden sind nicht schlecht. Sie machen vielmehr eine Werteabwägung zum Wohle eines größeren Ganzen möglich; sie gehören in den ökonomischen Werkzeugkasten jedes Entscheiders in der Softwareentwicklung.

Wie alle Schulden, sollten auch technische allerdings nur bewusst und in Maßen aufgenommen werden. Der Rückzahlungsplan sollte von Anfang an klar sein.

Wer heute sich durch Entscheidungen für suboptimale technische Qualität die Möglichkeit zu einer früheren Präsentation oder geringen Kosten erkauft - der muss gewahr sein, dass diese Schuld zurückgezahlt werden muss. Wieviel, wann und an wen soll gezahlt werden?

Wer daran nicht denkt, der bekommt immer zum ungünstigsten Zeitpunkt Besuch vom Schuldeneintreiber. Sie kennen das aus vielen Krimis. Und dann ist die Panik groß. Dann beginnt das Bitten und Betteln. Doch der Schuldeneintreiber ist immer gnadenlos. Er mag etwas Aufschub gewähren - doch am Ende muss gezahlt werden. Und zwar niemals weniger als ursprünglich geschuldet.

Also:

Technische Schulden sind nicht böse - solange Sie damit sinnig umgehen.

Aber kennen Sie Ihr Maß. Lassen Sie sich nicht verleiten. Denken Sie vom ersten Tag an die Rückzahlung.

Und vermeiden Sie wie auch sonst im Leben, alte Schulden mit neuen Schulden zu begleichen.

Dienstag, 6. August 2013

30 day challenge – Dem Neuen eine Chance

Lohnt sich eine Veränderung? Funktioniert ein Ansatz wirklich? Das können wir oft nicht durch bloßes Nachdenken herausfinden. Attraktivität und Plausibilität sind nett, gar notwendig - aber hinreichend sind sie nicht, damit wir Aufwand für etwas Neues treiben. Deshalb bleibt so manches eine interessante Idee und der Rest einfach beim Alten.

Das ist schade, oder? Denn damit verschenken wir ja Chancen, dass “es” besser wird. Schneller, leichter, angenehmer… das kriegen wir nur, wenn wir uns auf Neues einlassen.

Solchen Verbesserungswünschen steht aber natürlich der Wunsch nach Sicherheit gegenüber. Wir wollen ja durch Neues nichts verlieren, das wir schon haben. Sonst wird es nicht besser, sondern nur anders - und wir haben Aufwand getrieben. Das wäre auch schade, oder?

Verbesserung und Erhalt des Ist-Zustands stehen sich gegenüber. Aber nicht nur im Patt. Denn der Erhalt gewinnt, weil sich durch Inaktivität ja nichts verändert.

Angesichts der Ungewissheit, ob die Implementierung einer Idee wirklich zu Verbesserungen führen würde, und der Verständlichkeit des Erhaltungswunsches, stellt sich die Frage, wie denn aber doch dem Verbesserungspotenzial eine Chance gegeben werden könnte.

Ich denke, da helfen Experimente. Genau wie in der Wissenschaft geht es ja darum, eine Hypothese zu überprüfen. Mehr ist eine Idee, ein Veränderungsvorschlag, ein neuer Ansatz ja zunächst nicht. Selbst nicht, wenn die Idee woanders schon tausendfach ihr Versprechen eingelöst hat.

Nachdenken kann nicht helfen und muss nicht helfen. Ob Agilität, reactive programming, NoSql, Flow-Design, Continuous Build, TDD as if you meant it usw. usf. etwas für Sie sind, stellen Sie nur fest, indem Sie es ausprobieren.

Ausprobieren klingt für mich allerdings ein bisschen unverbindlich. Deshalb sage ich Experiment. Der Unterschied liegt in der Ernsthaftigkeit. Beim Ausprobieren tun Sie nicht mehr, als dass Sie an einer Sache in eng begrenztem und geschütztem Umfeld herumspielen. Das ist nicht schlecht und steht immer am Anfang. Doch der Erkenntnisgewinn ist begrenzt.

Bei einem Experiment hingegen, geht´s ans Eingemachte. Das findet für mich in vivo statt. Da wird nicht ausprobiert, sondern real eingesetzt. Man nimmt die Idee ernst und implementiert sie. Allerdings nur für einen überschaubaren Zeitraum.

Insofern fordert man sich selbst heraus. Schafft man es, sich auf die Idee einzulassen?

Und die Idee wird auch wirklich herausgefordert. Schafft sie es, ihre Versprechen einzuhalten?

Ideen kommen oft “absolut” daher, mit großem Anspruch und der Suggestion, es ginge nur ganz oder gar nicht. Davon sollten wir uns aber nicht beeindrucken lassen. Jedenfalls heute nicht mehr. Ideen stehen in einem Wettbewerb. Und da gilt: Die bessere mögen gewinnen. Dafür jedoch müssen wir ihnen eine Chance geben. Aber nicht nur nebenbei, von ernsthaft.

Matt Cutts hat dafür ein leidenschaftliches Plädoyer bei TED gehalten:

Damit geht der Druck raus aus den Entscheidungen für oder gegen Ideen. Wir müssen nicht einmalig den Kurs auf Gedeih und Verderb ändern. Nein, wir können es für einen begrenzten Zeitraum tun. “Nur” 30 Tage reichen für vieles aus.

30 Tage TDD, 30 Tage daily standups, 30 Tage ein Entwicklertagebuch, 30 Tage 10 Seiten in einem Fachbuch lesen, 30 Tage im Team ein Code Review, 30 Tage eine neue Codierungsrichtlinie… und währenddessen, aber vor allem anschließend reflektieren. Wie fühlt es sich an, eine Idee ernsthaft 30 Tage lang zu implementieren?

Bei www.my30dc.com gibt es dafür sogar ein Tool. Wenn da das Geek-Herz nicht höher schlägt ;-)

Ich habe da auch gerade eine “30 day challenge” laufen. Mein Experiment ist, nur während 8 Stunden pro Tag zu essen. Das soll sich positiv auf Wohlgefühl und Gewicht auswirken. Ob das stimmt? Keine Ahnung. Ich werde es nach 30 Tagen wissen. Durch Nachdenken könnte ich das nicht herausbekommen.

Also: Lassen Sie sich von Ideen nicht ins Bockshorn jagen. Fühlen Sie sich nicht belastet durch Zweifel und endgültigen umfassenden Adoptionsaufwand.

Wenn sie Ihnen halbwegs interessant erscheinen, machen Sie “nur” ein Experiment. Möglichst unverzüglich, solange die Motivationsenergie noch hoch ist. Das geht persönlich oder im Team. Nutzen Sie die “30 day challenge” Plattform oder schreiben Sie ein bisschen Experimentiertagebuch ein einem Notizbuch. Egal. Tun und reflektieren sind das Wichtigste. Taten statt Warten.

Ich habe auch noch eines zum Thema Programmierung gestartet. Im Verlauf von 30 Tagen will ich einen Web-Dienst realisieren. Sie können meinen Fortschritt im github Repository verfolgen. Dort sammle ich nicht nur Code, sondern auch Tagebucheinträge.

Donnerstag, 1. August 2013

Was ist eine Entität?

Im Zuge meiner Beschäftigung mit CQRS und Event Sourcing habe ich mir wieder die Frage gestellt, was denn eigentlich eine DDD Entität sei?

Nun hab ich endlich für mich eine ganz einfache Definition gefunden: Eine Entität ist ein Dictionary<string,string> mit unwandelbarer Id [1]. Eine Entität ist ein Sammlung von Schlüssel-Wert-Paar als Zeichenfolgen mit unwandelbarer Id [1].

Jup. Das isses. Mehr nicht [2].

Den Inhalt einer Entität kann man wandeln, die Id aber nicht. Und der Inhalt einer Entität ist strukturiert. Gerade die Annahme, dass Keys Pfade sein können [2], macht mich zufrieden. Nicht nur “Vorname” oder “Mindestgebot” oder “Lagerplatz” sind also Keys, sondern ebenfalls “Wohnsitz/PLZ” oder “Telefonnummern/3” oder “Positionen/2/Menge” [3].

So ein Dictionary ist ein Dokument, d.h. es ist selbstgenügsam (self-contained). Alles, was dazugehört, steht drin. Was nicht drin steht, gehört zu einer anderen Entität. So einfach ist das.

Was Sie als Daten bei einem Key hinterlegen, ist Ihre Sache. Das kann so umfangreich und strukturiert sein, wie es will. Per definitionem ist das aber keine Entität, weil es eben ein Wert in einer Entität ist. Werte als string [4] und nicht als object zu definieren ist mir deshalb sehr wichtig. Dadurch ist ausgeschlossen, aus einer Entität Objekte zu referenzieren.

Entitäten dürfen allerdings Ids anderer enthalten. Solche Entitätsreferenzen sind ok, weil sie sich auf das wahrhaft Unwandelbare beziehen [5]. Beispiel:

var frau = new Dictionary<string,string>{{$$id, "10"}, {"Vorname", "Eva"}, ...};
var mann = new Dictionary<string,string>{{$$id, "0815"}, {"Vorname", "Adam"}, ...};

frau["partner"] = mann["$$id"];
mann["partner"] = frau["$$id"];

Mit der Definition “Eine Entität ist ein Dictionary<string,string>” ist es nun ganz einfach herauszufinden, ob ein zusammengesetzter Wert eine Entität ist oder nicht. Fragen Sie sich einfach, ob Sie den Wert einem oder mehreren Keys in einer anderen Entität zuweisen würden. Beispiel:

Ist der zusammengesetzte Wert

Person("Vorname": "Peter", "GebDat": "1967-05-12", "Geschlecht": "m")

eine Entität? In manchen Zusammenhängen mag das so sein:

var person = new Dictionary<string,string>{{"$$id", "7654}, {"Vorname", "Peter"}, ...};
var einwohner = new Dictionary<string,string>{{"$$id", "0192"}, {"Person", "7654"}};

In anderen wieder nicht. Dann ist er Teil einer umfassenden Entität, z.B.

var einwohner = new Dictionary<string,string>{...};
einwohner["Person"] = "{\"Vorname\": \"Peter\",
                        \"GebDat\": \"1967-05-12\",
                        \"Geschlecht\": \"m\"}";

oder

einwohner["Person/Vorname"] = "Peter";
einwohner["Person/GebDat"] = "1967-05-12";
einwohner["Person/Geschlecht"] = "m";

Ich denke, das macht die Entscheidung einfacher. Doch auch wenn die mal daneben geht, ist es nicht so schlimm. Entitäten in dieser Form kann man auch leicht refaktorisieren. “Inline entity” und “extract entity” scheinen mir genauso probat wie “inline method” und “extract method”. Also keine Angst vor BDUF!

Außerdem lassen sich Entitäten dieser Form sehr leicht verteilt über Ereignisse denken, z.B.

Zugezogen("$$id": "9384", "Nachname": "Müller", "Straße": "Isestr. 2", ...)
Umgezogen("$$id": "9384", "Straße": "Richterstr. 17", "PLZ": "22085", ...)
Geheiratet("$$id": "9384", "Ehepartner": "0815", "Nachname": "Schmied", ...)
Geheiratet("$$id": "0815", "Ehepartner": "9384", ...)

In jedem Ereignis wird die Entität angegeben und danach nur eine Liste von Keys mit neuen Werten. Der aktuelle Stand einer Entität ergibt sich dann aus dem Summe ihrer Ereignisse.

Endnoten

[1] Ob die Id ein Eintrag mit speziellem Key in so einem Dictionary ist oder separat gehalten wird, ist mir erstmal egal.

[2] Noch einfacher könnte man natürlich sagen, eine Entität sei ein strukturierter Text, z.B. ein Json- oder XML-Dokument. Wird letztlich bei NoSql auch so gemacht. Aber das ist mir grad zu wenig griffig, wenn ich an den Umgang damit im Code denke. Mit einem Dictionary fühle ich mich etwas wohler.

Ein geschachteltes Dokument wie

<Person id="1234">
  <Vorname>Peter</Vorname>
  <Anschrift>
    <PLZ>22085</PLZ>
  </Anschrift>
</Person>

sieht mir auch komplizierter aus als eine Liste von Key-Value-Paaren:

$$id:1234
Vorname:Peter
Anschrift/PLZ:22085

Das eine kann in das andere übersetzt werden. Das reicht mir.

[3] Wem da Metadaten fehlen, der kann sie sich gern dazudenken, z.B. “Vorname:string” oder “Positionen/2/Menge:int”. Am Ende ist jedenfalls jeder Wert auf eine Zeichenkette abbildbar.

Wie solche Pfade aussehen, ist hier ebenfalls nicht wichtig. Mit der Syntax, die ich hier benutze, sind Sie ja aber vertraut.

[4] Binärdarstellungen sind nur eine Optimierung. Mit textuellen Repräsentationen von Daten kommen wir weiter. Sie sind ausreichend, bis ein konkreter Use Case etwas anderes fordert.

[5] Allerdings hadere ich hier noch mit mir. Manchmal denke ich, dass Entitäten gar keine Referenzen enthalten sollten. Wenn sie zu anderen in Beziehung stehen, dann nur innerhalb eines Kontextes - und der wird dann von einem Aggregat aufgespannt.

Ein Aggregat ist dann eine Entität, deren Zweck es ist, andere zu verbinden. Es ist ein Beziehungsraum.

So ganz traue ich mich aber noch nicht, das konsequent zu denken. Ich habe es zwar schon einmal in der dotnetpro so beschrieben - doch im Moment bin ich wieder ein wenig im Zweifel… Hm… warum eigentlich? Dazu mach ich mir am besten ein andermal weitere Gedanken.

Dienstag, 30. Juli 2013

Was der Softwarekunde will

Wer Software kauft, kauft ein Werkzeug. Das tut er, weil er die Effizienz des Anwenders steigern will.

Alles, was Software tut, kann auch ohne Software getan werden. Wir brauchen Software also nicht für ihre funktionalen Eigenschaften. Stoffe wurden ohne Software gewoben, Logarithmen wurden ohne Software berechnet, Auktionen ohne Software durchgeführt, Rechnungen ohne Software geschrieben usw. usf.

Mit genügend Zeit, Platz, Geld kann man sozusagen Software simulieren.

Das bedeutet: Software wird nicht wegen ihrer Funktionalität geschrieben, es geht also nicht um Effektivität. Software wird vielmehr wegen ihrer nicht-funktionalen Eigenschaften geschrieben. Dafür wird Software gemacht. Ausschließlich.

Nicht-funktionale Anforderungen sind allerdings nicht alle gleich. Es gibt primäre und sekundäre.

Primär sind die nicht-funktionalen Anforderungen, die Software etwas besser tun lassen, als die Alternative. Meist ist die langsamer oder umständlicher oder hat weniger Reichweite. Dann geht es bei Software um Performance, Usability oder Skalierbarkeit.

Sekundär sind die nicht-funktionalen Anforderungen, die Software auch noch erfüllen muss, die aber nichts mehr mit der Alternative zu tun haben. Wenn eine Software schneller als ein Mensch rechnen soll, dann ist Sicherheit ein sekundärer Aspekt. Wenn Software es leichter machen soll, Überblick über Zahlen zu behalten, dann ist Portierbarkeit ein sekundärer Aspekt.

Noch genauer wird Software also wegen ihrer primären nicht-funktionalen Eigenschaften geschrieben. Welche das in Ihrem Projekt/Produkt sind, können Sie ja mal überlegen.

Diese Feststellung hat schon eine Auswirkung auf die Praxis. Aus ihr ergibt sich, dass vordringlich und im Zweifelsfall Aufwand in primäre nicht-funktionale Anforderungen investiert werden sollte.

Nicht-funktionale Eigenschaften gibt es nicht ohne funktionale. Sie sind die Adverbien zu diesen Verben: schnell rechnen, übersichtlich darstellen, verlässlich speichern. Und das sogar im Komparativ, da es ja um eine Steigerung gegenüber der Alternative geht, also: schneller rechnen, übersichtlicher darstellen, verlässlicher speichern.

Nicht-funktionale Eigenschaften und funktionale sind auf Augenhöhe. Kunden suchen Effizienz und Effektivität. Nicht die Pyramide ist daher das erste Bild, das in den Sinn kommen sollte:

image

Es geht vielmehr um einen Kreis für das Ganze, dessen Teile gleichberechtigt sind:

image

Soweit das recht Offensichtliche. Ich glaube aber, dass sich damit nicht das komplette Kundenverhalten erklären lässt. Der Kunde will mehr.

Haltbarkeit ist Wandelbarkeit

Wer in Werkzeuge investiert, der erhofft sich, dass mehr herauskommt, als reingesteckt wurde. Der Nutzen soll größer sein als die Investition. Die Wahrscheinlichkeit dafür steigt mit der Nutzungsdauer.

Dieser Gedanke ist sogar so wichtig, dass er in der Steuergesetzgebung Niederschlag gefunden hat. Abschreibungsdauern richten sich nach üblichen Nutzungsdauern.

Neben den funktionalen und primären nicht-funktionalen Eigenschaften hat der Käufer einer Software also immer auch ihre Haltbarkeit im Hinterkopf. Die Investition soll sich auszahlen.

Eine Batterie soll Wochen oder Monate nutzen, ein Auto Jahre, ein Flugzeug Jahrzehnte, ein Sakralbau Jahrhunderte.

Wer Geld ausgibt, der hat immer eine Wunschvorstellung von der Haltbarkeit des Erwerbs. Er wird sich also mit dem Verkäufer darüber explizit unterhalten bzw. anderweitig etwas über die Haltbarkeit des “Objektes seiner Begierde” in Erfahrung bringen.

Zum obigen Kreis der Anforderungen kommt deshalb ein “Tortenstück” hinzu:

image

Es wäre ja töricht anzunehmen, dass Käufer von Software nicht auf Haltbarkeit achten würden. Für sie ist Software ein Werkzeug wie ein Bohrer oder ein Bagger.

Nun ist es aber so, dass Software zwar ein Werkzeug ist, aber ein immaterielles. Dadurch verschiebt sich die Bedeutung von Haltbarkeit.

Haltbarkeit in der materiellen Welt hat etwas mit Unveränderlichkeit, Erhalt, Konstanz zu tun. Ein Messer, Fenster, Auto ist umso haltbarer, je weniger es sich über die Zeit und mit Gebrauch verändert. Weniger Verschleiß bedeutet längere Haltbarkeit und damit höhere Investitionssicherheit.

Jedenfalls war und ist das gewöhnlich so. Denn es gibt auch materielle Werkzeuge, bei denen die Haltbarkeit weniger mit Verschleiß zu tun hat. Mir fällt da z.B. ein Handy ein. Dessen materielle Haltbarkeit ist weit höher als seine immaterielle. Allemal, wenn wir von geplanter Obszoleszenz absehen. Ich könnte immer noch mit meinem ersten Handy aus dem Jahr 1998 telefonieren.

Aber ich will das nicht. Es hat nämlich nicht Schritt gehalten mit der Entwicklung. Ich habe heute andere Ansprüche an ein Handy.

Unveränderlichkeit ist von Wert, wenn sich die Einsatzwelt eines Werkzeugs über die Zeit seiner materiellen Haltbarkeit nur geringfügig ändert. Deshalb tun wir bei Messern, Bohrern, Autos etwas gegen Verschleiß.

Dadurch verschiebt sich ebenfalls die Bedeutung von Haltbarkeit von Software. Denn die Einsatzwelt von Software ist in den meisten Fällen starken Veränderungen unterworfen. Das ist der Fall, weil Software in vielen Fällen weniger Werkzeug in einem Prozess, sondern vielmehr selbst die Definition eines Prozesses ist. Je größer ein Softwaresystem, desto eher ist das der Fall.

Die Haltbarkeitsdauer, d.h. die Zeit, in der ihr Nutzen höher als die Kosten ist, ist bei Software deshalb eine Funktion ihrer Anpassungsfähigkeit. Haltbar ist Software, die sich über lange Zeit leicht Veränderungen in der Einsatzwelt nachführen lässt.

Bei Software gibt es also keine Wartung wie bei materiellen Werkzeugen. Es geht eben nicht um den Erhalt von Eigenschaften. Von Softwarewartung zu sprechen und Wartungsverträge anzubieten, ist aus meiner Sicht grob kontraproduktiv. Denn dadurch wird ein völlig falsches Bild von Software transportiert. Es werden auch die falschen Signale an die Softwareproduktion gesandt.

Kunden erwarten Haltbarkeit. Denn ohne Haltbarkeit keine Investitionssicherheit. Doch diese Haltbarkeit hat eben nichts mit Erhalt heutiger Eigenschaften zu tun, sondern mit der Fähigkeit zum Wandel von Eigenschaften. Das müssen wir Kunden deutlich machen. Wir müssen ihnen explizit Wandelbarkeit [1] verkaufen. Ohne Wandelbarkeit keine Haltbarkeit. Wir müssen Wandelbarkeit auf Augenhöhe mit Funktionalität und primären nicht-funktionalen Eigenschaften sehen:

image

Wandelbarkeit ist nicht nice to have, sondern zentral. Wandelbarkeit ist keine Eigenschaft, die sich später hineinrefaktorisieren lässt. Wandelbarkeit ist auch wichtiger als sekundäre nicht-funktionale Eigenschaften.

Wenn Software ein nutzbringendes Werkzeug sein und lange bleiben soll, dann muss sie auf das Dreibein Effizienz, Wandelbarkeit und Effektivität gestellt werden. Das ist genau das, was der Kunde will - ob er das so klar ausspricht oder nicht.

Endnoten

[1] Mit Wandelbarkeit meine ich natürlich nicht, Software zwanghaft mit Plug-Ins auszurüsten. Was ich unter Wandelbarkeit verstehe, geht tiefer. Sie ist auf allen Abstraktionsebenen ins Softwaresystem gewoben. Sie hat mit grundlegenden Prinzipien zu tun.