Follow my new blog

Mittwoch, 12. Oktober 2011

Komponentenorientierung fürs Unternehmen

Kann Unternehmensorganisation von der Softwareentwicklung etwas lernen? Dass umgekehrt Softwareenwicklung von der Unternehmensorganisation lernen kann, zeigt ja in der letzten Zeit sehr schön Kanban. Das Vorgehensmodell überträgt erfolgreiche Organisationsmuster aus warenproduzierenden Unternehmen in die Programmierung

Aber auch umgekehrt ist Lernen möglich. Die Komponentenorientierung ist ein Beispiel, wo Unternehmen der Softwareentwicklung etwas abschauen können.

Komponenten in der Softwareentwicklung

In der Softwareentwicklung stehen Komponenten zunächst für Wiederverwendbarkeit, d.h. den unveränderten Einsatz von Code in verschiedenen Anwendungen. Die Motivation dahinter ist die Erhöhung des ROI: Wenn schon in Code investieren, dann am besten in einer Weise, dass der möglichst häufig zum Einsatz kommen kann.

Beispiel Rechtschreibprüfung: Wenn ein Softwareentwicklungsteam einen Blog-Editor entwickeln soll und dafür eine Rechtschreibprüfung braucht, dann tut es gut daran, diese Funktionalität so zu formen und zu verpacken, dass sie nicht nur im Blog-Editor zum Einsatz kommen kann, sondern auch in einem zukünftigen Twitter- oder Google+-Client oder auch noch in einem Chat-Client oder Email-Client.

Die Entwicklungskosten mögen für eine solch allgemeinere Rechtschreibprüfung etwas höher sein als für eine Blog-Editor-spezifische - doch das wird kompensiert durch zukünftige Ersparnisse. Bei den anderen Produkten fallen keine weiteren Kosten für die Rechtschreibprüfung mehr an.

Programmcode wiederverwendbar auszulegen, d.h. Komponenten zu entwickeln, spart also Geld. Noch mehr Geld spart jedoch, Programmcode gar nicht mehr zu entwickeln, sondern einzukaufen. Warum sollte das Softwarehaus überhaupt eine Rechtschreibprüfung entwickeln? Rechtschreibprüfung ist eine so grundlegende Aufgabe für viele Programme, dass sicherlich schon andere vor dem Softwarehaus dafür Lösungen entwickelt haben. Warum also nicht eine solche Lösung einkaufen? Das kostet zwar Geld, aber der enorme Aufwand, den Entwicklung und Pflege einer eigenen Rechtschreibprüfung bedeuten würden, steht gewöhnlich in keinem Verhältnis zum Kaufpreis einer Komponente oder gar eventueller Lizenzgebühren.

Wo die Aufgabe einer Software sich standardisieren lässt, sollte also nach einer existierenden Komponente Ausschau gehalten werden. Das ist eine Entscheidung für buy statt build, für den Einkauf statt den Selbstbau.

Die Entwicklung von allgemeinen Komponenten statt immer wieder spezieller Softwarebausteine spart also Kosten, wenn zu erwarten ist dass sie wiederholt zum Einsatz kommen.

Der Einkauf von Komponenten statt ihrer Entwicklung spart darüber hinaus Kosten, selbst wenn kein wiederholter Einsatz im eigenen Haus zu erwarten ist.

Software aus existierenden Komponenten zusammenzusetzen spart Geld; doch selbst wenn die Kosten genauso hoch wären wie die einer Eigenentwicklung oder vielleicht sogar etwas höher, wäre der Einkauf existierender Komponenten der Eigenentwicklung vorzuziehen.
Der Nutzen eingekaufter Komponenten liegt nämlich nicht nur in einer wahrscheinlichen Kostenersparnis, sondern in der Freisetzung von Ressourcen. Wo Funktionalität nicht selbst entwickelt werden muss, kann man seine Aufmerksamkeit etwas anderem widmen.

Der Einkauf von Komponenten, die für Standardfunktionalität existieren, konzentriert die Arbeitskraft auf das, was nicht standardisierbar ist. Und genau dort liegt die Aufgabe eines Teams.

Der Job eines Teams, das einen Blog-Editor entwickeln soll, ist es vor allem, sich auf das "Blog-Editor-hafte" zu konzentrieren. Was macht einen Blog-Editor aus? Wie unterscheidet er sich von einer allgemeinen Textverarbeitung, wie unterscheidet er sich von einem Twitter-Client? Alles, was ein Blog-Editor mit anderen Programmen gemein hat, sollte das Team nicht selbst programmieren müssen, sondern einkaufen.

Damit erreicht es, dass es mit dem, worum es ihm eigentlich geht, schnellstmöglich voran kommt.

Standardfunktionalität selbst zu entwickeln ist ein Luxus, den Teams sich leisten können, wenn sie durch das Mehr an Kontrolle über diesen Softwareteil, einen deutlichen Vorteil erlangen. [1] Das ist allemal in frühen Phasen eines Softwareprojektes eher selten der Fall. Projekte werden ja nicht aufgesetzt, um etwas Existierendes zu duplizieren, sondern einen Unterschied zu machen. Auf diesen Unterschied müssen deshalb alle Kräfte ausgerichtet sein.

Neben der durch Wiederverwendbarkeit ermöglichten Konzentration auf das Wesentlich bieten Komponenten aber noch einen weiteren Vorteil: Austauschbarkeit. Komponenten sind Black Boxes, deren Aufgabe durch einen separaten Kontrakt definiert ist. Wie welche Daten wann zwischen ihnen und der Umgebung fließen, das ist unabhängig davon beschrieben, wie konkret sie ihre Aufgabe erfüllen, d.h. wie sie implementiert sind. Kontrakte verbergen Details, mit denen sich Komponentennutzer nicht herumschlagen wollen und sollten.

Kontrakte für Standardfunktionalität sind Standardkontrakte. Das heißt, nicht nur eine bestimmte Komponente kann sie erfüllen, sondern viele verschiedene Varianten oder Modelle einer Komponente. Das Blog-Editor Team, das komponentenorientiert denkt und entwickelt, ist also nicht darauf angewiesen, die Rechtschreibkomponente von Hersteller X zu verwenden. Wenn es damit Erfahrung gesammelt hat und unzufrieden ist, kann es zur Rechtschreibkomponente von Hersteller Y wechseln. Das ist selbst dann der Fall, wenn es zunächst in eine eigene Rechtschreibkomponente investiert haben sollte (out-sourcing, buy) - oder umgekehrt, wenn es später von einer eingekauften Standardkomponente zu einer Eigenentwicklung wechseln will (in-sourcing, build).

Komponentenorientierung reduziert die Gefahr eines lock-in, d.h. der Festlegung auf eine ganz bestimmte Implementation von Funktionalität. Das ist günstig, falls die Implemenation in puncto funktionaler oder nicht-funktionaler Anforderungen nicht mehr genügt oder der Anbieter sich als unvorteilhaft erweist.

Es gibt noch weitere Vorteile der Komponentenorientierung für die Softwareentwicklung. Doch schon die aufgezeigten können der Unternehmensorganisation Impulse geben.

Die Vorteile von Komponenten nochmal auf den Punkt:

  • Komponenten setzen Ressourcen frei
  • Komponenten entkoppeln

Komponentenorientierung in der Unternehmensorganisation

Unternehmen haben über "Geld verdienen heute und in Zukunft" eine inhaltliche Mission. Sie bieten einen Haarschnitt, Möbel, Hausbau, Entrümpelung und Millionen andere Leistungen. Ziel jedes Unternehmers, insbesondere jedes Gründers, sollte daher sein, die besonders knappe Ressource Aufmerksamkeit auf seine Mission zu fokussieren.

Beispiel Ad-hoc Buchdruck: Die Mission des Unternehmens ist, Lesern von elektronischen Dokumenten - seien es PDFs oder Web-Seiten - die Möglichkeit zu geben, daraus Bücher zu machen. Beliebige Seiten beliebiger Dokumente sollen ad-hoc zusammengefasst werden können. Und diese Zusammenfassungen sollen dann on-demand in beliebiger Auflagenhöhe, d.h. beginnend mit Auflage = 1, als Buch gedruckt und innerhalb von 2 Tagen geliefert werden.
Was kann der Entrepreneur, der eine solche Leistung aufbauen möchte, nun von der Komponentenorientierung lernen?

1. Out-sourcing vs in-sourcing

Der Entrepreneur sollte sich fokussieren auf das, was seine Idee, sein Geschäft ausmacht. Für das Beispiel ist das die einfache individuelle Zusammenstellung von Inhalten zu Büchern, der Druck von Einzelexemplaren und die schnelle Lieferung.

Print-on-demand Dienste wie epubli oder lulu.com bieten das heute auch schon grundsätzlich - nur nicht in dieser Einfachheit und Geschwindigkeit. Die nicht-funktionalen Aspekte machen mithin die Geschäftsidee aus: individuelle Bücher aus existierenden Inhalten in Auflage 1 drucken und übermorgen liefern. Darauf muss sich der Entrepreneur fokussieren.

Das bedeutet im Umkehrschluss: Alles, was nicht im Fokus seiner Mission ist, sollte der Entrepreneur nicht selbst leisten. Stattdessen sollte er nach Komponenten Ausschau halten, die es für ihn leisten.

Sollte der Entrepreneur seine Buchhaltung selbst machen? Nein. Das gehört nicht zu seiner Mission.

Sollte er selbst drucken? Nein, jedenfalls nicht, wenn es sich vermeiden lässt. Drucken ist zwar Teil der Idee, doch deren Unterschied zu existierenden Angeboten besteht nicht in Funktionalität (Buchdruck), sondern in einer Qualität der Funktionalität (Geschwindigkeit). Die Aufgabe des Entrepreneurs ist es daher, Buchdruck nicht zu ermöglichen, sondern zu beschleunigen. Wenn er das kann, ohne selbst zu drucken, dann ist das der einzuschlagende Weg.

Sollte er selbst das Marketing machen? Nein. Das gehört nicht zu seiner Mission. Der Entrepreneur hat die Idee von einem Ganzen. Dieses Ganze aus Teilen zusammenzufügen, das ist seine vornehme Aufgabe. Er ist Integrator und Koordinator, nicht Executor.
Sollte der Entrepreneur selbst die Homepage seines Unternehmens erstellen? Nein. Das gehört nicht zu seiner Mission.

"Selbst machen" bezieht sich bei diesen Fragen nicht nur darauf, ob der Entrepreneur als Person, sondern ob sein Unternehmen eine Aufgabe selbst erledigt. In-sourcing vs out-sourcing ist die Frage.

Und die Antwort der Komponentenorientierung ist: out-sourcing soweit möglich, in-sourcing soweit nötig.

Dem out-sourcing kann natürlich das Budget entgegenstehen. Wo das Geld knapp/unsicher ist, tendieren Unternehmensgründer daher zum in-sourcen. Lieber die Buchhaltung im eigenen Haus, lieber die das Sekretariat im eigenen Haus, lieber Lager und Auslieferung im eigenen Haus usw.

Wo es vergleichbare Leistungen nicht am Markt einzukaufen gibt, stellt sich die Frage nach dem out-sourcing nicht. Immer mehr Leistungen lassen sich heute jedoch einkaufen. Der Gründer hat also die Alternative. Und er sollte sich im Zweifel für das out-sourcing entscheiden.
In-sourcing kostet auch Geld, manchmal vielleicht sogar weniger. In-sourcing hat aber mehrere Nachteile, die sich gerade ein Gründer bewusst machen sollte:

  • In-sourcing erfordert Führung. Out-sourcing erfordert nur Koordination der zugekauften Komponente mit anderen; aber in-sourcing braucht darüber auch noch Führung der "Implementation" einer Leistung. Sie ist keine Black Box. Der Entrepreneur muss sich um die einzelnen Mitarbeiter kümmern.
  • In-sourcing bindet. Ein Dienstleister kann ohne moralische Bedenken gewechselt werden; eigenen Mitarbeitern kann und/oder will man nicht so leicht kündigen.
  • In-sourcing erzeugt Fixkosten. Zugekaufte Leistungen werden meist nach Aufwand/Stück abgerechnet. Hat das Geschäft keinen Bedarf, fallen keine Kosten an. Interne Leistungen kosten jedoch immer Geld, auch wenn es nichts zu tun gibt. Gehälter und Mieten laufen weiter.
    Der Leitstern des Unternehmers sollte immer der Fokus sein. Bei jeder Entscheidung über in- vs out-sourcing sollte die Frage lauten: Wie kann ich mich mehr auf die eigentliche Mission konzentrieren?

Für Gründer kommt dann noch als zweite Frage hinzu: Wie kann ich flexibel bleiben, falls ich den Kurs des Unternehmens ändern muss?

2. Austauschbarkeit durch Kontrakte

imageEgal, ob eine Leistung selbst erbracht oder eingekauft wird, sie sollte klar kontouriert werden. Die Schnittstellen zwischen den Komponenten - ob interne oder externe - sind klar zu definieren. Kontrakte sollte so ausgelegt werden, dass die Kopplung zwischen Komponenten so lose wie möglich ist.

Wie eng Leistungserbringer - Abteilungen oder externe Dienstleister - gekoppelt sind, hängt davon ab, wie stark Änderungen auf der einen Seite des Kontraktes Änderungen auf der anderen Seite hervorrufen können.

Wenn der ad-hoc Buchdruck zum Beispiel den Versand selbst übernimmt, dann haben personelle Änderungen darin größere Auswirkungen, als bei Einbindung einer externen "Versandkomponente". Eine "Versandkomponente" ist für den Entrepreneur eine Black Box. Wie sie ihren Kontrakt erfüllt, ist ihm egal. Sollte es dort personelle Änderungen geben, darf das laut Vertrag keinen Einfluss auf die Leistungsqualität haben.

Intern lässt sich solche Entkopplung jedoch kaum herstellen. Und der Austausch einer internen "Versandkomponente" fällt auch nicht leicht.

Externe Komponenten erhöhen mithin die Flexibilität eines Unternehmens - zumindest ganz allgemein. Das ist besonders für Gründer wichtig. Die sind ja für ihre Mission noch auf der Suche nach einem Erfolgsweg. Da sollten sie in der Lage sein, Leistungen einfach zu verändern und auszutauschen. Bei internen Leistungen fällt das jedoch schwerer als bei externen. Mindestens die Kontrakte sind weniger explizit.

Deshalb sollte ein Unternehmen Wert darauf legen, nach Identifikation seiner Komponenten, deren Kontrakte möglichst ausdrücklich zu formulieren, ganz unabhängig davon, ob nun in- oder out-sourcing stattfindet.

Dazu gehört aber nicht nur die Form der Schnittstelle, also die Oberfläche, an der Komponenten miteinander (re)agieren. Es ist auch zu bedenken, was in einer Komponente an "Zustand" angehäuft wird. Der sollte sich bei Austausch nicht als hinderlich erweisen.

Ein Beispiel dafür sind Email-Dienstleister wie Google oder Hotmail. Wer sie benutzt, interagiert mit ihnen nicht nur über einen Email-Client (z.B. Web-Client oder Outlook), sondern akkumuliert auch "Zustand"; das sind all die Emails, die beim Dienstleister im Archiv liegen.
Wenn nun der Email-Dienstleister gewechselt werden soll, darf dieser "Zustand" dem nicht im Wege stehen. Er soll erhalten bleiben, wenn man z.B. von Hotmail nach Google oder Exchange umzieht. Darin liegen ja wertvolle Informationen aus Jahren der Arbeit. Wenn das nun nicht möglich ist, dann liegt ein lock-in vor. Der ist zu vermeiden. Darauf muss bei der Formulierung des Kontrakts geachtet werden.

Gerade wer auf externe Komponenten zurückgreifen will, tut gut daran, von vornherein den möglichen Fall des Wechsels anzusprechen. Im Kontrakt sollte stehen, was in dieser Hinsicht möglich ist, worauf zu achten ist. Bei externer Buchhaltung oder zugekauftem Marketing mag das relativ einfach sein, aber externe Softwareentwicklung macht da z.B. traditionell Probleme.
Das sollte aber nicht gegen out-sourcing sprechen, sondern nur für eine sorgfältige Kontraktgestaltung. Die Vorteile des out-sourcing gerade für Gründer sind so groß, dass sie nicht durch Unsicherheit in diesem Punkt verspielt werden dürfen. "Ach, dann machen wir das halt doch selbst, wenn es die Vereinbarungen so schwierig sind." wäre die falsche Reaktion.
Ein in-sourcing mag die Kontraktdefinition einfacher machen; sie fällt womöglich sogar ganz unter den Tisch, weil ja eben eine Leistung im Haus erbracht wird. Da muss man sich ja nicht um eine explizite Beschreibung kümmern, oder?

Der einfachere, weil fehlende Kontrakt zwischen Komponenten zieht dann aber später Probleme an. Ohne explizite Kontraktgrenzen wird das Unternehmen monolithisch, d.h. zu einem wenig flexiblen Block. Das verhindert zukünftige Entwicklung. Wissen ist dann eher implizit denn explizit; Leistungen werden irgendwie denn durch einen sauberen Kontrakt beschrieben erbracht. Wachstum fällt dann schwer.

Fazit

Unternehmensorganisation kann von der Softwareentwicklung lernen. Unternehmen wie Software sind komplexe Systeme, die davon profitieren, sauber strukturiert zu sein. Und beide profitieren davon, wenn sie nicht alles selbst leisten müssen, sondern sich auf ihren eigentlichen Zweck konzentrieren können.

Unternehmen sollten ihre Leistung daher als eine Kooperation von "Belangen" verstehen, die von Komponenten erbracht werden. Diese Komponenten sind Black Boxes definiert durch Kontrakte. Für jede Black Box kann dann entschieden werden, ob sie intern aufgebaut oder extern eingekauft werden soll.

Der externe Einkauf von Komponenten hat insbesondere dann vorteile, wenn das Unternehmen noch "in der Findungsphase ist", d.h. besonders flexibel agieren muss. Dann bedeutet Zukauf von externen Komponenten ein Plus an Flexibilität und Konzentration bei gleichzeitig geringeren Fixkosten.

Spendieren Sie mir doch einen Kaffee, wenn Ihnen dieser Artikel gefallen hat...

Fußnoten

[1] Ein solcher Vorteil könnte in mehr Qualität bei nicht-funktionalen Anforderungen wie Performance, Sicherheit, Usability oder Internationalisierung liegen. Dass er bei der Funktionalität liegt, ist eher nicht zu erwarten, da es sich ja sonst nicht um Standardfunktionalität handeln würde.

Dieser Artikel ist ein Beitrag zur Blog-Parade des

image

Donnerstag, 6. Oktober 2011

Skalierbare Softwarebausteine - Teil 2

In meinem Traum sehen fundamentale Softwarebausteine ganz einfach aus, wie ich im ersten Teil dieser kleinen Artikelserie beschrieben habe:

image

Es sind potenziell zustandsbehaftete und potenziell nebenläufige Funktionseinheiten auf beliebig vielen Abstraktionsebenen, die Input-Daten in Output-Daten transformieren. So einfach ist das :-)

Dabei könnte ich nun stehenbleiben und hübsche Diagramme mit solchen Funktionseinheiten malen. Das würde mir das Nachdenken über Softwarestrukturen schon erleichtern.

Doch ich will mich nicht in Wolkenkuckucksheim einrichten. Bubbles don´t crash. Der Traum muss also einen Realitätsbezug bekommen. Die konzeptionellen Funktionseinheiten müssen ausführbar sein; irgendwie müssen sie an Code angebunden werden.

Die Form einer normalisierten Funktionseinheit

Wenn solche traumhaften Flüsse ausführbar sein sollen, stellt sich als erstes Frage, welche Form eine Funktionseinheit in Code haben könnte. Bisher habe ich als Übersetzung Event-based Components favorisiert: Jede Funktionseinheit wird als Klasse implementiert, die für jeden Input-Stream eine Methode anbietet und für jeden Output-Stream einen Event.

Das finde ich inzwischen zu aufwändig. Es funktioniert ordentlich, doch es macht ziemliche Mühe und schränkt ein. Der Zwang zur Klasse ist in der Community auch immer wieder auf Stirnrunzeln gestoßen.

Deshalb jetzt ein Vorschlag mit kleinerem Fußabdruck:

delegate void FunctionalUnit<in TInput, out TOutput>(
    IMessage<TInput> input,
    Action<IMessage<TOutput>> output);

interface IMessage<out T> {
    string StreamQualifier { get; }
    T Data { get; }
}

Wie ist das? Deutlich einfacher, oder? Sie können eine Funktionseinheit bauen, wie Sie mögen, solange es einen Adapter gibt, der sie an diesen Delegaten anpasst. Funktionen, Methoden, auch EBC-Klassen sind möglich. Nur ein Beispiel:

class Program
{
    static void Main(string[] args)
    {
        FunctionalUnit<string, IEnumerable<string>> fuSplit;
        fuSplit = (inputMsg, outputCont) =>
            {
                var outputData = Split(inputMsg.Data);
                var outputMsg = new Message<IEnumerable<string>>(
                                           "", outputData);
                outputCont(outputMsg);
            };

        fuSplit(new Message<string>("", "a;b"),
                  (m) => Console.WriteLine(string.Join("/", m.Data)));
    }


    static IEnumerable<string> Split(string config)
    {
        return config.Split(';');
    }
}

Die Implementation der Funktionseinheit ist eine Funktion. Um die herum wickelt Main() einen Adapter, der den Input an FunctionalUnit übersetzt in das Funktionsargument und ihren Rückgabewert in den Aufruf des Continuation-Delegaten.

Dasselbe ist möglich mit einer Methode oder mit einer EBC-Klasse. Sollte es dabei um mehrere Input- und/oder Output-Streams gehen, kann der StreamQualifier von IMessage<> zur Unterscheidung herangezogen werden.

An dieser Stelle nehmen Sie bitte vor allem die Botschaft mit: Sie können Funktionseinheiten implementieren, wie Sie mögen.

Es gibt keinen Vorzug mehr für Klassen. Einzig, Ihre Implementation muss sich an den Delegaten adaptieren lassen. Das geht aber zumindest für statische und Instanz-Methoden/Funktionen und für EBC-Klassen.

Die Beschreibung von Flüssen

Dass Funktionseinheiten jede Form haben können, wird Sie etwas aufatmen gelassen haben. So ganz entfinstert wird Ihre Miene allerdings noch nicht sein, weil der Preis für die Freiheit der Form ein höherer Koordinationsaufwand zu sein scheint. Es müssen ja nun Adapter für Funktionseinheiten zusammengesteht werden, damit es zu einem Fluss kommt.

Das ist richtig. Deshalb wird nun die Frage nach einer Beschreibung von Flüssen drängender. Bisher konnte sie recht simpel in C# als Event-Event-Handler Zuweisungen von EBC-Funktionseinheiten übersetzt werden. Das geht nun nicht mehr so einfach. Eine DSL wäre zur Unterstützung schön; aus der könnte womöglich der ganze Adapter-Code und das Koordinieren von Funktionseinheiten generiert werden.

Ja, das könnte man. Aber ich möchte etwas anderes vorschlagen.

Aber erst einmal: Wie könnten Flüsse beschrieben werden? Sie könnten grafisch notiert werden. Dafür ist aber ein recht aufwändiger Designer nötig. Oder sie könnten textuell notiert werden. Ich halte letzteres für ohnehin nötig, selbst wenn es einen Designer gäbe.

ebc.xml (ebclang.codeplex.com) ist ein Versuch gewesen, Flüsse textuell zu beschreiben. Dazu gibt es auch einen Visualizer und einen Compiler. Aber XML scheint mir zu umständlich. Da steckt viel Rauschen drin.

Dann habe ich mit einer DSL experimentiert, die ich ebc.txt genannt habe. Die Transformation einer Konfigurationszeichenkette der Form “a=1;b=2” in ein Dictionary ließe sich damit so beschreiben:

ToDictionary {
  this.in –(string)-> (Split)
          –(string*)-> (Map)
          –(KeyValuePair<string,string>*)–> (Build)
          –(Dictionary<string,string>)-> this.out
}

Das ist doch lesbar, oder? Ich benutze diese Notation jedenfalls recht gern, um mal kurz in einer Email oder einem Diskussionsgruppenbeitrag einen Flow zu beschreiben.

Allerdings ist auch diese Notation noch recht länglich, finde ich. Für die Menschen-Mensch-Kommunikation ist sie ok. Doch auch sie enthält noch Rauschen.

Deshalb komme ich auf ebc.xml zurück, nur ohne XML. Die einfachste, maschinenlesbare Form der Beschreibung eines Flow ist eine Tabelle:

ToDictionary
this.in, Split
Split, Map
Map, Build
Build, this.out

Die erste Zeile bezeichnet die koordinierende Funktionseinheit, alle weiteren Zeilen verbinden Output mit Input.

Dass hier keine Typen mehr für Input/Output angegeben sind, ist nicht weiter schlimm. Entweder man rüstet das nach


this.in, Split: string
Split, Map: IEnumerable<string>

oder man überlässt die Prüfung auf Passgenauigkeit einer Übersetzungs- oder Laufzeitinstanz. Letzteres finde ich völlig ausreichend.

Mit solchen “Verbindungstabellen” lassen sich nun trefflich auch tiefe Fluss-Hierarchien beschreiben:

image

Jedes Komposit wird durch eine Tabelle beschrieben:

R
R, T
T.a, W
T.b, V
W, S.c
V, S.d
S, R

W
W, X
X, Y
Y, W

V
V, Z
Z, Y
Y, V

Wo Input- bzw. Output-Streams implizit bestimmbar sind, da müssen sie nicht angegeben werden, z.B. bei

R
R, T

Hier ist klar, dass R sich auf das Komposit bezieht und deshalb auf der linken Seite des Tupels ein Input-Stream gemeint ist. Rechts steht nicht das Komposit selbst, sondern eine enthaltene Funktionseinheit. Deren Input-Stream ist gefragt; doch da sie nur einen hat, muss der nicht näher benannt werden.

Wenn mehrere Input-/Output-Streams vorhanden sind, ist allerdings eine Qualifizierung nötig wie bei:


W, S.c

Solche Tabellen sind recht bequem hinzuschreiben. Das hat schon ebc.xml gezeigt. Als einfachste Notationsform mögen sie deshalb genügen. Minimal sind sie jedoch nicht.

Die Arbeitspferde einer hierarchischen Struktur sind die Blätter. Hier: S, T, X, Y, Z. Die Komposite bilden nur Kontexte, in denen sie zu “Kooperativen” zusammengefügt sind. Da die keine weitere eigene Aufgabe haben, können sie spätestens zur Laufzeit wegfallen als eigenständige Funktionseinheiten.

Das obige System kann auch in nur einer Tabelle so beschrieben werden:

/R, /R/T
/R/T.a, /R/W/X
/R/W/X, /R/W/Y
/R/W/Y, /R/S.c
/R/S, /R
/R/T.b, /R/V/Z
/R/V/Z, /R/V/Y
/R/V/Y, /R/S.d

Hier sind alle Blatt-Funktionseinheiten qualifiziert durch einen Pfad, der beschreibt, in welcher Schachtelung von Kompositen sie stecken. Damit lassen sich auch Y in W und Y in V unterscheiden.

Die Daten von T.a gehen nun direkt nach W/X, statt zuerst an W und dann an X.

An dieser Stelle halten Sie bitte wieder einen Moment inne und lassen Sie die Botschaft einsinken: Die Struktur beliebig komplexer Software lässt sich durch eine einzige Tabelle beschreiben.

Egal wieviele Ebenen, wieviele Komposite und Blätter: Ein solches System können Sie immer abbilden auf eine simple Tabelle der Output-Input-Beziehungen.

Damit meine ich nicht, dass Kontrollanweisungen wie if oder while überflüssig werden bzw. auch irgendwie über eine Tabelle verknüpft werden sollen. Die stecken ja in den Blättern der Holarchie und sind unsichtbar. Implementationsdetails. Mir geht es nur um die Funktionseinheiten der beschriebenen Form. Wie groß Sie die auf unterster Ebene machen, ist Ihre Sache. Je mehr Sie in Blättern verstecken, desto weniger profitieren Sie vom hiesigen Ansatz.

Höhepunkt: Flüsse zur Laufzeit

Und nun zum eigentlichen Punkt, den ich mit dem vorherigen und diesem Artikel machen will. Der Höhepunkt meines Traums ist eine Runtime Engine für Flüsse. Denn die wird sehr einfach möglich durch diese einfachste Beschreibung von Flüssen.

Ich bin der Meinung, dass wir Flüsse nicht mehr übersetzen sollten. Wir sollten sie auch nicht mehr von Hand “verstöpseln”. Stattdessen sollten wir sie ganz, ganz simpel über eine Tabelle beschreiben, die Blätter (Operationen) benennen – und eine Runtime Engine “interpretiert” dann die “Flusstabelle”.

image

Wie aus Ihren Funktionen, Methoden, EBC-Klassen Operationen werden, ist ein anderer Belang. Der finde ich gerade nicht so spannend. Dafür kann ein Container geschrieben werden, bei dem Sie Ihre Implementationen registrieren können und der sie hin FunctionalUnit-Adapter wickelt. Er könnte Operationen aus Assemblies sogar eigenständig sammeln.

Dito ist die Herkunft der einen, das ganze System beschreibenden Tabelle für mich zweitrangig. Die kann aus mehreren Tabellen generiert worden sein. Oder sie kann aus einer ebc.txt DSL übersetzt worden sein. Auch das ist eine Funktionalität, die sich kapseln lässt.

Nein, zentral ist für mich die Runtime Engine zur Interpretation von Flows. Da spielt die Musik. Und jetzt festhalten:

  • Die Runtime ist der zentrale Ort, an dem der Fluss (oder die Hierarchie der Flüsse) belauscht werden kann. Die Runtime leitet Output an Input weiter. Sie hat also jede Nachricht ausdrücklich in der Hand. Ihr können wir unsere Wünsche äußern, welche Nachrichten wir abgreifen wollen. Vielleicht wollen wir sie nur protokollieren, vielleicht wollen wir sie aber auch manipulieren. Alles ist möglich durch den zentralen Eingriffspunkt Runtime. Stellen Sie sich eine Logging vor, das sie zur Laufzeit mit Pfaden einschalten können: “log /*/T.*”, d.h. logge alle Nachrichten, deren StreamQualifier dem Pattern entspricht.
  • Die Runtime ist der zentrale Ort, an dem alle Flüsse in ihrer Geschwindigkeit kontrolliert werden können. Wenn wir wollen, können wir sie komplett anhalten – und dann wieder starten. Oder wir verlangsamen sie nur, um den Fluss vielleicht grafisch visualisiert mitverfolgen zu können.
  • Die Runtime ist der zentrale Ort, an dem wir Performancedaten messen lassen können. Was sind die Durchflusszeiten, wie groß sind die Nachrichten in Strom /R/S.c durchschnittlich usw.
  • Wenn die Runtime Output an Input “von Hand” zustellt, dann kann sie diese Übertragung selektiv aussetzen, während wir eine Operation zur Laufzeit ersetzen.
  • Oder wir können der Runtime zur Laufzeit eine Änderung des Flusses mitteilen. Der ist ja nur eine Tabelle, die wir aktualisieren können.
  • Und schließlich bekommt die Runtime jede Exception mit. Wenn wir wollen, stellen wir in der Runtime ein, was mit Exceptions passieren soll, die bei der Verarbeitung ganz bestimmter Streams auftreten.
  • Ach, bevor ich es vergesse: Natürlich ist die Runtime auch die Instanz, von der wir uns wünschen können, ob Funktionseinheiten synchron, async+sequenziell oder parallel ausgeführt werden sollen.

Sie sehen, ich träume von großen Vorteilen, wenn wir beginnen, Software als Hierarchie von Datenfluss-Funktionseinheiten zu betrachten.

Technisch ist das alles grundsätzlich möglich. Ich habe es in einem Spike schon ausprobiert. Hier und da lauern sicherlich noch Teufelchen im Detail. Aber wenn wir das Ergebnis für wünschenswert halten, dann werden wir Wege finden, es vom Traum zur Realität werden zu lassen.

Mit diesen beiden Postings wollte ich dazu meine Gedanken ein wenig ordnen. Ein Codeplex-Projekt für Implementation einer Runtime ist schon aufgesetzt. Jetzt muss ich nur noch die Zeit finden, sie schrittweise auch zu implementieren. Vielleicht machte ich daraus eine Application Kata mit vielen Iterationen. Dann können andere parallel und auf anderen Plattformen es auch angehen.

Einstweilen lassen Sie mich wissen, ob Sie mitträumen oder es sich für Sie wie ein Albtraum anhört…

Spendieren Sie mir doch einen Kaffee, wenn Ihnen dieser Artikel gefallen hat...

Mittwoch, 5. Oktober 2011

Skalierbare Softwarebausteine - Teil 1

Wie können wir Software mit evolvierbarer Struktur herstellen? Wie kann Software selbst so agil werden wie unsere Prozesse es schon geworden sind? Diese Frage treibt mich immer noch um. Die bisher angebotenen Lösungsansätze aus Richtung Clean Code finde ich noch nicht ausreichend. TDD und SOLID sind ganz gute Ansätze… nur fehlt ihnen aus meiner Sicht ein umfassender Blick auf Software. Das SRP in SOLID ist zwar grundlegend – doch DI ist demgegenüber merkwürdig sprachspezifisch, finde ich. Und TDD fokussiert auf Code, so dass von TDD wenig Hilfe zu erwarten ist, wenn noch gar kein Code oder eine Code-Idee vorhanden ist.

Ich glaube deshalb weiterhin, dass wir noch einen Schritt zurücktreten müssen. Wir müssen eine allgemeinere Vorstellung von Software entwickeln, in die dann TDD und SOLID usw. hineinpassen. TDD und SOLID sollen also nicht einfach ersetzt werden, sondern einen soliden Platz bekommen.

Warum die real existierende Objektorientierung uns behindert

Die Objektorientierung, so könnten Sie sagen, ist doch aber schon so eine allgemeine Vorstellung von Software. Ja, das stimmt. Irgendwie ist sie das. Und dann doch wieder nicht. Zumindest nicht die real existierende Objektorientierung, die sich von einer idealen ursprünglichen stark unterscheidet. Die real existierende Objektorientierung (REOO) hat aus meiner Sicht einfach einige große Mängel:

  • Sie REOO skaliert konzeptionell nicht. Wir können Software mit ihr nicht vom kleinsten bis zum größten Baustein durchgängig beschreiben. Dass Software aus Bausteinen unterschiedlicher Größe/Granularität zusammengesetzt ist, sollte außer Zweifel stehen. Damit meine ich nicht, dass Bausteine mal mehr und mal weniger LOC haben. Ich meine ihre konzeptionelle Größe, ihren Funktionsumfang. Eine ganze EXE umfasst mehr Funktionalität als eine Klasse in der EXE.
    Mir fällt es jedenfalls sehr schwer, Software aus Objekten unterschiedlicher Granularität vorzustellen. Der UML offensichtlich auch, sonst würde sie Klassendiagrammen nicht auch noch Komponenten- und Paketdiagramme beistellen. Weder Komponenten noch Pakete gehören jedoch zur Objektorientierung. Wie ihre Namen schon sagen, geht es nicht um Objekte (oder Klassen als deren Schemata), sondern um Komponenten und Pakete.
  • Die REOO ist fixiert auf ein essenziell statisches Bild der Realität. Nomen est omen: Die Realität besteht aus Objekten, aus “Dingern”, die erstmal sind, deren Existenz eine Dauer hat. Diese “Dinger” haben dann vor allem einen Zustand. Die Praxis der REOO versucht sie vor allem anhand von Daten zu identifizieren, für die sie verantwortlich sind. Objekte sind mithin Zuständigkeitsaggregate. Sie bündeln den Umgang mit Daten. Das wird positiv formuliert als Kapselung.
    Ich verstehe, dass diese Sichtweise Appeal hat. Menschen mögen Greifbares. Mit Lego kann jedes Kind umgehen, mit Mathematik jedoch nicht; die ist viel abstrakter. Also mögen Softwareentwickler auch lieber umgehen mit Greifbarem, eben mit Objekten.
    Wenn ich die Wurzel der Softwareentwicklung im Maschinenbau und der Elektrotechnik verorte (und nicht in der Mathematik), dann finde ich das auch nur konsequent. Die vormaligen Hardwarebausteine sind in die Software übertragen worden: aus konkreten Zahnrädern und Hebeln und Transistoren und Widerständen sind Objekte geworden.
    Oder ich könnte philosophisch werden und die Softwareentwicklung an die Griechen binden. Demokrit mit seinen Atomen und Platon mit seinen Ideen haben die Welt bestehend aus klar umrissenen Entitäten aufgebaut gesehen. Die einen waren anfassbar, wenn auch seeeeehr klein. Die anderen abstrakt, dafür beliebig groß. In jedem Fall haben beide ihre “Weltenbausteine” als unwandelbar angesehen, als statische Bausteine.
  • Die REOO verbindet Objekte über Abhängigkeiten. Ein Objekt, das viel kann, ist von Objekten abhängig, die weniger können. Dadurch entsteht eine Abhängigkeitshierarchie, über die die Gesamtleistung vertikal verteilt ist. Auf jeder Ebene passiert ein bisschen.
    Das hat die REOO als Problem erkannt – im Zusammenhang mit der Testbarkeit. Als Gegenmaßnahme empfiehlt sie IoC und DI und Attrappen. Damit werden Objekte auf jeder Ebene einzeln testbar.
    Ich halte das für eine Symptombehandlung. Die Abhängigkeiten bleiben bestehen. Funktionalität ist weiterhin vertikal in der Hierarchie verstreut.

Meine Kritik an der real existierenden Objektorientierung ist also sehr fundamental. Sie macht uns die Beschreibung von Lösungen schwer, weil wir die mit ihren Mitteln nicht leicht auf beliebigen Abstraktionsebenen denken können. Sie fixiert sich auf ein Weltbild, das es uns schwer macht, das zu beschreiben, was Software essenziell repräsentiert: Prozesse. Und die Ergebnisse der Objektorientierung, der Code, hat eine Form, die ganz fundamental anti-agil ist, also im Widerspruch zur zentralen Erkenntnis der Softwareentwicklung steht, dass Software sich ständig anpassen muss.

Aber nun genug des OO-Bashings :-) Es soll nur als Motivationshintergrund dienen, warum ich immer noch und wieder an einem anderen Software-Weltbild bastle. Nicht, dass mit REOO nix ginge. Doch, klar, es geht was. Mit Pferdefuhrwerken ging auch etwas. Jahrhunderte lang. Und dann kam der Trecker. Nun geht noch mehr.

Vorschlag für ein alternatives Weltbild

Damit ich nicht den Anschein erwecke, eine rundum-sorglos Lösung zu bieten – Silverkugeln gibts ja nicht und sind in unserer Branche bei vielen auch nur im Anschein verhasst –, spreche ich lieber mal von einem Traum.

Ja, ich habe einen Traum, in dem wir Software viel einfacher entwickeln. Das ist natürlich auch irgendwie dem verhaftet, was ich in 30 Jahren Softwareentwicklung erfahren habe. Wie Software in 100 Jahren entwickelt wird, kann ich mir wohl nicht vorstellen. Doch für Sie mag mein Traum dennoch esoterisch anmuten. Macht ja aber nichts, ist eben nur ein Traum :-) Träumen Sie doch mal mit. Lassen Sie sich darauf ein. Schicken Sie Ihre Skepsis für eine kleine Weile auf Urlaub. Die kann sich ja mal den Versuchen zur Rettung von Euro und Europa zuwenden.

In meinem Traum entwickeln wir Software anders, weil Software darin ein anderes Weltbild unterliegt. Software oder die Welt besteht darin nicht aus “Dingern”, sondern aus Prozessen. Im Kern steht nicht etwas Statisches, sondern Dynamik. Es geht ums Tun, um Bewegung, um Wandlung. Softwareentwickler fragen nicht, nach “Objekten”, sondern nach “Aktivitäten”.

Nach diesem Weltbild besteht Software aus diesem:

image

Das ist eine Aktivität. Da passiert etwas. Das ist neutral gesprochen eine Funktionseinheit. Kent Beck würde es vielleicht Element nennen.

“Baustein” möchte ich eigentlich ungern dazu sagen, da “Baustein” schon wieder Statik suggeriert wie “Objekt”. Aktion, Aktivität oder eben Funktionseinheit scheinen mir passender.

So eine Funktionseinheit “macht ihr Ding”, indem sie eingehende Daten verarbeitet. Sie steht also für das alte EVA-Prinzip: Eingabe-Verarbeitung-Ausgabe.

Daten können aus verschiedenen Richtungen in die Funktionseinheit einfließen (Input). Das, was sie daraus macht, kann in verschiedene Richtungen aus ihr herausfließen (Output).

Und wenn eine Funktionseinheit nicht reicht, dann arbeiten mehrere zusammen in einem Fluss. Der Output der einen wird zum Input der anderen:

image

Das war´s. So sieht Software aus. Auf jeder Abstraktionsebene. Damit lässt sich eine ganze Anwendung beschreiben wie auch der kleinste Teil einer Anwendung.

Zustand

Input ist ein Trigger für Funktionseinheiten. Kommt Input an, tun sie etwas. Allerdings muss sich eine Aktivität nicht ausschließlich auf einfließenden Input beziehen. Sie kann auch ein Gedächtnis haben, d.h. Zustand. Aus dem kann sie lesen und den kann sie verändern.

Zustand macht es zwar schwerer, über das Ergebnis einer Aktion nachzudenken, aber ich halte Zustand für einen so natürlichen Bestandteil der Welt, dass wir ihn nicht mit Macht ausschließen sollten. Das rückt Funktionseinheiten natürlich in die Nähe von REOO Objekten – doch der Unterschied besteht für mich im Fokus. Bei REOO steht Zustand eher am Anfang, bei meiner Träumerei eher am Ende.

Im einfachsten Fall ist solcher Zustand lokal. Eine Aktion hat individuellen Zustand:

image

Wenn Aktionen kooperieren sollen, dann kann es allerdings nötig sein, dass sie Zustand gemeinsam nutzen. Das ist dann shared state und sollte explizit gemacht werden. Das wird spätestens dann wichtig, wenn der Zugriff darauf gleichzeitig erfolgen soll. Dann muss er nämlich synchronisiert werden.

image

Nebenläufigkeit

Ohne weitere Angaben arbeiten Aktionen sequenziell und synchron. Während eine Funktionseinheit Input verarbeitet, tut das keine andere. Wenn sie Output produziert, stößt sie damit eine empfangende Funktionseinheit an, die ihn als Input verarbeitet, bevor die produzierende weitermacht.

image

Sequenzielle und synchrone Verarbeitung lässt sich gut denken und nachverfolgen. Aber in der realen Welt kommt sie eher nicht vor. Und sie nutzt die verfügbaren Prozessorressourcen womöglich nicht optimal.

Es ist deshalb konsequent, Aktionen auch nebenläufig betreiben zu können. Sie laufen dann auf (mindestens) einem eigenen Thread (und womöglich auf einem eigenen Prozessorkern).

image

Sobald der Fluss von Input-Output durch eine Aktion mit eigenem Thread läuft, findet die weitere Verarbeitung auf diesem Thread statt, bis wiederum eine Aktion mit eigenem Thread angestoßen wird usw.

image

Dass Aktionen nebenläufig betrieben werden können, bedeutet jedoch nicht, dass Nebenläufigkeit auch innerhalb von Aktionen stattfindet. Die scheint mir problematisch, weil sie dazu führt, dass Input in anderer Reihenfolge als der, in der er eintrifft, verarbeitet wird. In meinem Traum ist daher die Verarbeitung innerhalb einer Funktionseinheit immer noch sequenziell. Input wird in der Reihenfolge seines Eintreffens verarbeitet.

Zumindest sollte das wohl der Default sein. Wenn in ganz bestimmten Situationen eine Aktion davon profitiert, in sich ebenfalls nebenläufig zu sein, d.h. Input auf mehreren Threads parallel zu verarbeiten, dann sei das so. Es könnte so ausgedrückt werden:

image

Aktionen sind zunächst also synchron und sequenziell, dann können sie auch asynchron sequenziell sein und schließlich vollständig parallel.

Unabhängigkeit

Es ist vielleicht keiner Erwähnung wert, weil der Fluss von Input-Output es so natürlich macht, doch ich sage es lieber einmal ausdrücklich: Aktionen sind von einander unabhängig.

Zwei verbundene Aktionen wissen nichts von einander. Der Producer (generiert Output) weiß nicht, wer seinen Output weiterverarbeitet. Der Consumer (verarbeitet Input) weiß nicht, von wem sein Input stammt.

Das (!) ist ein fundamentaler Unterschied zur REOO. Und deshalb ist es wohl gut, dass ich ihn hier nochmal betone ;-)

Eine Gesamtleistung als Ergebnis einer Kooperation mehrerer Funktionseinheiten erfordert keinerlei Abhängigkeiten zwischen den Kooperationspartnern. Sie wissen nicht einmal, dass sie kooperieren.

Jede Aktion innerhalb einer “Kooperative” bekommt Input “von irgendwoher” und produziert Output “für unbekannt”.

Ein Zusammenhang von Funktionseinheiten wie dieser:

image

sieht also eher so aus:

image

Schachtelung

Um größere und sehr große Systeme zu beschreiben, müssen Aktionen hierarchisch angeordnet werden können. Aus großer Flughöhe sieht ein System dann eigentlich immer so aus:

image

Wenn man niedriger fliegt, kommen Details in den Blick:

image

Und wenn man noch tiefer runter geht, d.h. in das System hineinzoomt, dann kommen noch mehr Details in den Blick:

image

So kann es beliebig tief gehen. Software kann also als Baum dargestellt werden:

image

Das sieht nun wieder wie eine REOO Objekthierarchie aus. Das macht auch nichts, solange klar ist, dass der “Verfeinerungsbaum” einem wesentlichen Prinzip folgt: alle Aktionen, die nicht Blatt sind, haben ausschließlich die Aufgabe, Aktionen zu “Kooperativen” zu kombinieren.

In Nicht-Blättern stecken keine Algorithmen. Sie entscheiden nichts, sie enthalten keine Schleifen. Sie sorgen nur dafür, dass Output der einen Aktion zu Input für eine andere wird. That´s it.

Ebenfalls betonenswert: Funktionseinheiten auf allen Ebenen sehen gleich aus. Sie verarbeiten Input zu Output mit eventuellen Seiteneffekten. Und sie sind gleichzeitig Teil von darüber gelagerten Funktionseinheiten, von denen sie in einen Kooperationszusammenhang gestellt werden, wie sie Ganzes sind in Bezug auf Funktionseinheiten, die sie selbst zu einem Kooperationszusammenhang zusammenstellen.

Software ist damit grundsätzlich selbstähnlich aufgebaut; man könnte vielleicht sogar sagen, fraktal. Software ist eine Holarchie und die Funktionseinheiten sind ihre Holons.

Darüber habe ich früher schon öfter geschrieben wie hier oder hier oder 2005 hier. Aber auch wenn ich riskiere, damit zu langweilen, ist mir diese Sichtweise so wichtig, dass ich sie wiederhole. Wir tun uns einen Gefallen, wenn wir dahin kommen, Software so zu sehen. Aller Softwareentwurf kann durch solche Regelmäßigkeit nur einfacher werden.

Normalisierung

Zum Abschluss für heute noch eine Verallgemeinerung. Aktionen habe ich als Funktionseinheiten mit beliebig vielen Input- und Output-Strömen beschrieben. So soll es auch sein.

Für etwas mehr Regelmäßigkeit können Sie jedoch reduziert werden. Das hat später Vorteile, wie Sie sehen werden, wenn es an die Implementierung geht.

Die “Einheitsdarstellung” oder normalisierte Form für Aktionen ist diese:

image

Normalisierte Funktionseinheiten haben genau 1 Input-Strom und genau 1 Output-Strom. Immer.

Statt Input/Output entlang verschiedener Ströme fließen zu lassen, gibt es je nur einen Strom, auf dem Input/Output-Daten mit einem Qualifier näher beschrieben sind; der ordnet sie logisch einem der vielen früheren physischen Ströme zu.

Wie und ob sie sich von Input triggern lassen, sei dahingestellt. Ob sie Output herstellen, sei dahingestellt. Mir geht es um ihre Form. Alle Funktionseinheiten aller Ebenen können ohne Verlust an Flexibilität und Individualität gleich aussehen.

Zwischenstand

Soweit mein Traum von einer universellen, skalierbaren Grundstruktur von Software. Sie besteht aus einer beliebig tiefen Hierarchie von potenziell zustandsbehafteten und potenziell nebenläufigen Aktionen. Software tut etwas. Sie verarbeitet Daten. Deshalb wird sie beschrieben durch Tätigkeiten einheitlicher Form.

Klar, das ist Flow-Design nochmal beschrieben. Mir scheint eine so knappe Darstellung allerdings sinnvoll als Grundlage für das, was ich im Folgenden beschreiben möchte. Sie fasst den Stand der Flow-Design Überlegungen zusammen – allemal für die, die nicht alles verfolgen, was bisher dazu geschrieben wurde.

Ganz ohne Neuigkeit ist dieser Artikel andererseits aber auch nicht. Die Nebenläufigkeit ist jetzt “offiziell” im Bild und die Normalisierung. Der nächste Artikel wird zeigen, dass sie nicht nur konzeptionell nett ist.

Spendieren Sie mir doch einen Kaffee, wenn Ihnen dieser Artikel gefallen hat...

Montag, 3. Oktober 2011

Digitale Erleichterung für den Schulalltag – oder: Kinder sind keine Scherpas

Wie wäre das, wenn Sie jeden Tag mit 25% Ihres Körpergewichts auf dem Rücken zur Arbeit gehen müssten? Für mich wären das ca. 17 kg, aber ich bin nicht groß. Für viele unter Ihnen wären das bestimmt 20 kg oder gar 25 kg. Ein Gewicht, dass Sie natürlich in einem Rucksack tragen können - nur wäre das jenseits dessen, was sie als bequem ansehen würden. Auf einen Sonntagswanderausflug würden Sie bestimmt höchstens 5 oder max. 7 kg mitnehmen, also deutlich weniger als 10% Ihres Körpergewichts.

Millionen Menschen in Deutschland können sich das allerdings nicht aussuchen. Sie sind gezwungen, um die 25% Ihres Körpergewichts jeden Tag zur Arbeit zu schleppen. Und es sind kleine Menschen, deren Haltungsapparat noch nicht voll ausgebildet ist. Es sind unsere Kinder.

Kinderarbeit in fernen Ländern beklagen wir zurecht. Dass Kinder in Deutschland jedoch täglich mit echten Lasten größere Strecken zurücklegen müssen, ist nicht auf unserem Radar.

Im Bild meine Tochter Verena. Sie ist derzeit 11 Jahre alt und besucht die 6. Klasse eines Gymnasiums in Hamburg. Ihr Ranzen wiegt um die 7,5 kg; ihr Gewicht ist 28 kg. Der Effekt ist deutlich zu sehen: kompensierende Haltung, ja, Fehlhaltung.

image

Klar, das Gewicht am langen Arm zu tragen, wäre noch schlimmer. Die Empfehlung "Ranzen statt Aktentasche" ist korrekt. Nur sollte das nicht bedeuten, dass jedes Ranzengewicht dann auch gleich akzeptabel ist. Ich finde 7,5 kg oder 25% des Eigengewichts jedenfalls deutlich zuviel.

imageIch weiß nicht mehr, wie schwer mein Schulranzen früher war. In der Grundschule war er jedenfalls deutlich kleiner, er sah eher so aus wie nebenstehen. Dass er mit 7,5 kg bestückt war, ist unwahrscheinlich.

Später im Gymnasium bin ich mit einem recht dünnen Samsonite Koffer ausgekommen. Den habe ich – gegen alle Empfehlung – am langen Arm getragen. Da waren bestimmt auch keine 7,5 kg drin.

Heute ist das anscheinend anders. Brotdose, Trinkflasche und Hefte gibt es immer noch. Die Zahl der zu schleppenden Bücher scheint sich aber erhöht zu haben. Hier das, was ich an einem Tag in Verenas Ranzen gefunden habe: Mathe, Englisch, Französisch, Geschichte, Erdkunde, Musik.

image

Manche Bücher können in der Schule gelassen werden, wenn sie nicht für Hausaufgaben benötigt werden. Gute Idee – die natürlich mindestens gelegentlich dazu führt, dass ein Kind ein nötiges Buch vergisst. Und wenn es Bücher zuhause hat, dann vergisst es sicher auch mal eines einzupacken, das am nächsten Tag gebraucht wird. Aber das ist alles nicht so schlimm wie das täglich hohe Gewicht.

7,5 kg kommen vor allem zusammen durch Schulbücher und Notizbücher, die die Lehrer fordern. Nicht Schreibhefte, sondern echte kleine “Schreibbücher” (z.B. für spezielle Ansagen der Klassenlehrer).

Zum Gewicht kommt die Qualität der Bücher. Was trägt denn meine Tochter da. In Hamburg herrscht derzeit Lehrmittelfreiheit, d.h. Schulbücher müssen nicht gekauft werden (oder zumindest nicht alle). D.h. die Kinder “erben” ihre Bücher von Vorgängern. So sehen sie denn auch aus. Hier als Beispiel das Musikbuch:

image image image

So viel ist uns also die Bildung unserer Kinder wert?

Aber ich will nicht in ein Lamento über unser Bildungssystem verfallen. Mir geht es hier um etwas anderes. Ich finde die Gewichtsbelastung und auch die schlechte Lehrmittelqualität nämlich gänzlich unnötig. Sie ist anachronistisch, weil es besser geht. Es geht ganz einfach viel besser. Nämlich so:

image image

Das ist das iPad von Verena. Auf ihm sind alle Schulbücher, die sie sonst im Ranzen trägt, als PDFs. Das iPad 1 wiegt damit 0,875 kg!

Das iPad mit allen Büchern der 6. Klasse wiegt nur knapp 10% des Ranzens und also nur knapp 2,5% von Verena. Das, so finde ich, ist ein angemessenes Gewicht für den täglichen Schulweg.

Zugegeben, im iPad ist noch keine Brotdose und keine Trinkflasche enthalten :-) Aber alle Schulbücher und alle Schreibhefte können darin sein. Ohne Gewichtsveränderung kann darin sogar jedes Buch jeder Jahrgangsstufe inkl. aller je gemachten schriftlichen Ausfertigungen gespeichert sein. Rein technisch könnte Verena also mit einem iPad zur Einschulung ausgestattet werden und es bis zum Schulabschluss behalten. In 12 (oder 13) Jahren müsste sie für den Unterricht nicht ein Buch schleppen und nicht ein Heft kaufen. Sie könnte alle Arbeiten mit und im iPad erledigt.

Technisch ist das kein Problem.

Ob das immer didaktisch/pädagogisch wünschenswert ist, ist eine andere Frage. Mit einem Stift das Schreiben auf Papier zu lernen, ist sicher eine Fertigkeit, die Schule auch vermitteln sollte. Allerdings geschieht das heute schon schlecht genug, wie das Gekrakel vieler Schüler beweist. Der Zeigefinger sollte also nicht zu doll wackeln, wenn es ums Schreiben auf einem iPad geht. (Ob mit der virtuellen Tastatur oder einer zusätzlichen geschrieben würde, sei auch nochmal dahingestellt.)

Was in der Schule gelesen wird, was für die Schule geschrieben wird, was für die Schule “collagiert” wird (Hausarbeiten aus Text und Bildern), was notiert wird… das kann genauso gut oder gar noch besser (leichter, in höherer Qualität, mit mehr Lerneffekt fürs restliche Leben) mit einem iPad getan werden.

imageDamit kann es heute losgehen. Schulbücher müssten nicht mal aufwändig umgestaltet werden; ein Scan wie ich es mit den Büchern von Verena gemacht habe, reicht erstmal. Als Leseprogramm finde ich den GoodReader sehr nützlich.

Ein kleines Problem machen “Workbooks”, also Bücher, in die etwas hineingeschrieben werden soll. Die könnten technisch aber als PDF-Formulare ausgelegt werden. Das ist etwas mehr Aufwand als ein reiner Scan – doch der ist sehr überschaubar, wenn der ein Verlag das einmal tun würde zum Nutzen aller Schüler.

Schulhefte und Notizbücher werden ersetzt durch diverse Apps. An Textverarbeitungen und Notiz-Apps gibt es keinen Mangel. Da kann man organisieren und reinmalen und schreiben, dass es eine Freude ist. Und wenn die Lehrerin Termine ansagt, können die sogar in Kalender eingetragen werden. Ja, die Lehrerin könnte sogar einen Kalender für die Klasse zentral führen. Dann müssten nicht 30 Kinder eine Notiz machen. Den Kalender könnten Eltern dann abonnieren.

Es ist überhaupt nicht auszudenken, wie der Schulalltag sich vereinfachen ließe, wenn denn die Kinder statt mit gewichtigen Papierbergen mit einem iPad (bzw. einem vergleichbaren Device) ausgestattet würden. Ich wage ja gar nicht auszumalen, was da alles möglich wäre in puncto Apps für die Bildung. “Spielend lernen” könnte eine ganz neue Bedeutung bekommen. Physikalische Experimente auf dem iPad, Exploration mathematischer Probleme, ein anderer Zugang zur Chemie, Recherchieren am PC nicht als mühseliger Sonderfall, sondern als Bestandteil des Schulalltags…

Aber ich höre sie schon, die Kritikusse: Dem Plagiat sei damit ja Tür und Tor geöffnet. Und die wichtigen Fertigkeiten im Umgang mit dem Papier, die dann nicht mehr gelernt würden. Sowieso sei damit die Verblödung der Kinder und Jugendlichen durch “den Computer” auch noch staatlich gefördert.

imageKinder die zerfledderte Bücher schleppen und in Hefte krakeln: das ist der Inbegriff heutigen Schulideals, scheint mir. Naja, kein Wunder, wenn ich Lehrer sehe, die nicht einmal ein Handy haben und sich von der Elternschaft auch keines für den gelegentlichen Gebrauch zur Abstimmung bei Klassenreisen schenken lassen. Da wird kokettiert mit der eigenen Unkenntnis, wie Fotos elektronisch verbreitet werden könnten. (“Das geht doch irgendwie mit einer CD oder so, nicht wahr? Ich kenne mich da nicht aus. [hihi]”)

Nein, ich halte weiterhin dagegen: Eine Schulwelt, in der jedes Kind mit einem iPad (bzw. ähnlichem Device) ausgestattet ist, halte ich für wünschenswert.

Handfest dagegen sprechen nicht eventuelle pädagogische Einwände einer zaghaften Lehrerschaft, die sich früher schon gegen Schiefertafeln gewandt hat, als man noch auf Birkenrinde in der Schule geschrieben hat.

Handfeste Einwäde sind für mich derzeit:

  • Ein iPad kostet eine ganze Menge. Das kann sich nicht jede Familie für jedes Kind leisten. Es gibt auch günstigere Varianten, aber das kapazitive Display und die Geschwindigkeit sind für mich erstmal Minimalanforderung. Schlechter sollten Schul-Devices nicht ausgestattet sein.
    imageIch bin allerdings sicher, dass die Zeit hier für die Schüler arbeitet. In Russland ist man augenscheinlich schon weit(sichtig)er.
    Auf der anderen Seite: Wenn ein Device für mehrere Jahre gekauft wird, sagen wir mal mindestens für die Zeit nach der Grundschule (also max. 8-9 Jahre), dann wären selbst Kosten von 500 EUR kein Problem. Pro Jahr wären vielleicht 75 EUR fällig (inkl. einer Verlustversicherung). Dafür ließe sich doch eine Finanzierungsform finden, oder? Ein bisschen Kreativität wäre halt gefragt.
    Letztlich müsste sich am Preis also gar nicht soviel ändern. Mit einem potenten Hardware-Sponsor und einem potenten Telco-Provider und einer potenten Versicherung wäre da was zu machen. Warum probiert eine Privatschule das nicht einfach einmal aus? Fragen köst nix.
  • Wenn ein iPad verloren ginge, gestohlen oder beschädigt würde im Schulalltag, dann wären gleich alle Aufzeichnungen und Bücher weg. Dass das einem Ranzen passiert, ist möglich, aber unwahrscheinlich. Ein iPad hingegen ist empfindlicher und attraktiver für Diebe.
    Es müssten Vorkehrungen verschiedener Art getroffen werden, um einem Verlust entgegen zu wirken und ihn im Notfall zu kompensieren. Daten können über die Cloud gesichert werden. Der Zugang kann personalisiert werden. Klassenräume könnten abgeschlossen werden in der Pause. Und Devices könnten versichert werden. Man sollte eh darüber nachdenken, ob die Devices nicht “im Abo” gekauft werden, so dass sie nach vielleicht 3 Jahren ohnehin ausgetauscht würden.
  • imageSchulbücher müssten digitalisiert werden. Das kann jeder für sich machen, wie ich es getan habe. Aber eigentlich ist das natürlich Aufgabe der Verlage. Die tragen natürlich starke Bedenken, was ihre Umsätze angeht. Doch das wäre eigentlich kein Problem. Schulen kaufen heute Buchkontingente, das können sie auch morgen tun.
    Wie gesagt, im ersten Schritt müssten die Bücher nicht mal aufgepeppt werden. Ein Scan reicht in den meisten Fällen aus.
    Und danach kann jeder Verlag schrittweise seine Bücher in Apps oder anderes umwandeln (die die Kinder (bzw. ihre Eltern) kaufen). Da würde sich sogar ein Markt für weitere Titel auftun: das Schulbuch muss gekauft werden, doch zum Schulbuch gibt es dann vom Verlag noch Nachhilfe-Apps. Ha! Was für ein Geschäft!
  • Verena könnte heute womöglich schon ihr iPad in die Schule mitnehmen. Da ist ja alles, was sie braucht, drauf. Die Lehrer würden die Stirn runzeln, zucken, doch am Ende es akzeptieren, denke ich. Gefragt habe ich allerdings nicht, weil Verena nicht will. Es wäre ihr unangenehm, als einzige mit einem solchen Device im Unterricht zu sitzen. Da schleppt sie lieber 7,5 kg, als sich so als Außenseiter zu zeigen.
    Das bedeutet, Devices müssen in einer Weise eingeführt werden, die “peerkompatibel” ist. Kindern dürfen sich dadurch nicht ausgegrenzt fühlen. Es ginge also nur klassenweise.

Soweit die Hürden, die ich sehe. Es sind keine didaktischen, keine pädagogischen, sondern eher organisatorische.

Keine scheint mir aber unüberwindlich. Im Gegenteil. Wenn auch nur eine Schule das Ergebnis für wünschenswert hielte, könnte sie aus dem Stand ein Experiment aufsetzen. Warum nicht eine Klasse in einem höheren Jahrgang (z.B. 10. Klasse) mit Devices ausstatten und schauen, was passiert?

Sponsoren für Hardware, 3G und Versicherung ließen sich ganz bestimmt finden. Die Kosten wären dann kein Problem.Schulverlage würden es sicher auch mitmachen.

Die größte Herausforderung wäre wahrscheinlich, die Lehrerschaft zu überzeugen. Die kann selbst nicht verlässlich mit Devices umgehen. Die kann schon gar nicht verlässlich verstehen, was ihre Schüler mit Devices heute schon daheim alles tun. Die Barriere ist mithin in den Köpfen.

Deshalb scheint mir eine Privatschule der vielversprechendste Keim für eine solche Entwicklung. Dort ist man mehr als anderswo darauf angewiesen, sich zu entwickeln.

Also: Wo ist die innovative Schule, die unsere Kinder erleichtert? 0,875 kg sind machbar. Kein Kind muss 25% seines Körpergewichts an Material zur Schule schleppen.

Wenn uns unsere Kinder wirklich wichtig sind, dann bemühen wir uns, sie mit dem Besten auszustatten, was unsere Gesellschaft hervorgebracht hat. Und das sind nicht nur Goethe, Einstein, klimatisierte Busse für Klassenreisen und hübsche Tafelbilder. Machbar ist viel mehr. Machbar ist auch mehr als Smartboard-Schulen heute tun. Wir müssen es nur wollen.

Spendieren Sie mir doch einen Kaffee, wenn Ihnen dieser Artikel gefallen hat...

Samstag, 1. Oktober 2011

Ungesunde Zahlungshemmung

imageZahlen für Fortbildung? Gerade habe ich eine Folge von Uncle Bobs Videos gekauft. Dabei habe ich ein Zucken gespürt. "12 USD für ein Video? Lohnt sich das?" Trotz meiner Zweifel habe ich gezahlt...

...und als bei Paypal dann stand "8,96 EUR", habe ich gedacht: "Wie blöd bin ich eigentlich? Ich denke darüber nach, 8,96 EUR für meine Fortbildung auszugeben - aber ich zucke nicht, wenn ich für den selben Preis einen Roman kaufe oder ins Kino gehe. Das ist unverhältnismäßig."

Ja, genau, das ist unverhältnismäßig. Mein Zucken war Symptom eines verqueren Wertesystems: Entertainment darf Geld kosten, Weiterbildung darf kein Geld kosten.

Das, was in Zukunft Geld bringt (weil es meine Kompetenz erhält oder vergrößert), darf kein Geld kosten - das, was mich Entspannt (auch wichtig, klar), also kein Geld bringt, darf Geld kosten?

Natürlich ist das Missverhältnis nicht so krass. Es geht nicht um Geld ausgeben dort und gar kein Geld ausgeben hier. Ich gebe selbstverständlich auch sonst Geld aus für Weiterbildung (insb. in Form von Büchern) und manches Entertainment ist mir zu teuer.

Mein Gefühl ist jedoch, dass das Zucken auf ein grundsätzliches und nicht nur bei mir Vorhandenes Missverhältnis hinweist. Wir haben durch das Internet als bodenlosem Becher der kostenlosen Information schleichend eine ungesunde Attitüde entwickelt. Ja, ungesund ist sie, so glaube ich, weil sie letztlich unsere ökonomische Gesundheit untergräbt.

Die Sache mit dem Geld ist im real existierenden Wirtschaftssystem essenziell. Wir brauchen es für alles mögliche. Deshalb sind wir darauf angewiesen, dass wir Geld verdienen. (Das mag man unschön finden, ist aber erstmal so.) Also verlangen wir für unsere eigene Arbeit gutes Geld. Wir finden, wir verdienen den Preis, den wir aufrufen (in Form von Stundensatz oder Gehalt).

Wir wollen also viel Geld bekommen - anderen wollen wir aber möglichst wenig Geld geben. Wir wollen die Leistung von Uncle Bob möglichst umsonst (zumindest war ich einen Moment enttäuscht darüber, dass seine Videos nicht umsonst wie sein Blog sind (oder nicht viel weniger kosten)), wir wollen die Leistung von MSDN online kostenlos, wir wollen die Leistungen der vielen Blogger kostenlos, wir wollen ein kostenloses Stackoverflow, wir wollen ein kostenloses Coderepository online usw. usf.

Wir sind maßlos in dem, was wir alles kostenlos haben wollen.
Gleichermaßen sind wir aber maßlos in dem Geld, was wir eigentlich für unsere eigene brilliante Leistung bekommen wollen.

Das ist doch eine Asymmetrie, ein Missverhältnis, das nicht funktionieren kann. Das kann nur zu Spannungen führen. Alles bekommen, aber nichts zahlen? So "denken" 3jährige. Als Erwachsene sollten wir es besser wissen.

Die Preisspirale zu unserem Nutzen umkehren

Wir müssen uns einfach immer wieder klar machen: Wenn wir selbst so denken, dann denken auch unsere Kunden so. Die fragen sich auch, warum sie uns eigentlich Geld geben sollten. Warum sollten sie für unsere Software etwas bezahlen, wenn es doch woanders Open Source kostenlos gibt?

Wie fühlt sich das für Sie an? Ihr Kunde mag es Ihnen (bzw. dem Vertrieb Ihres Unternehmens) nicht sagen, aber denken wird er es: “Boah, soviel Geld… warum soll ich das ausgeben? Im Internet gibt es soviel Software kostenlos.”

Ist das ein gutes Gefühl, wenn Sie sich überlegen, wie Ihre Kunden über Sie denken? Unabhängig davon und erstmal wichtiger: Wohin führt denn eine solche Haltung? Sie setzt eine Abwärtsspirale in Gang. Und die dreht sich ja auch schon. Uns wird schon schwindelig davon, wenn wir auf weithin sinkende Löhne und Stundensätze blicken.

Dann reagieren wir reflexartig: Kosten senken! Am besten selbst alles billiger fordern. Warum kostet Uncle Bobs Video eigentlich soviel wie ein normaler Kinobesuch? Kann der das nicht billiger machen für mich als armen gebeutelten Entwickler, der unter Kostendruck steht und dem die Kunden nicht mehr soviel Zahlen wollen?

Merken Sie es? Alles dreht sich. Nach unten. Weil Sie und ich so “kleinlich denken”. Wir glauben, wir könnten (langfristig) einen Blumentopf gewinnen, indem wir immer billiger einkaufen – aber an unseren eigenen Umsatzforderungen nichts ändern.

Das ist Quatsch.

Entweder sind wir konsequent und senken auch unsere Forderungen.

Oder wir sind konsequent und erhöhen unsere Ausgabenbereitschaft.

Der Vergleich des Preises von Uncle Bobs Video mit einer Kinokarte hat mir (mal wieder) gezeigt, wie meine Entscheidung ausfallen sollte: Ich erhöhe meine Ausgabenbereitschaft. Das ist mein klitzekleiner Beitrag zur Umkehr der Spiralbewegung. Denn wenn ich bereit bin, Geld auszugeben – insbesondere für etwas, das mir ja hilft, meinen Wert zu halten/steigern –, werden vielleicht auch andere Menschen so denken. Das kommt dann auch mir zugute.

Wertschätzung

Der rohe Geldfluss ist aber nur eine Hälfte des Problem bei diesem Missverhältnis. Geld ist nicht alles. Wir wollen auch für unsere Arbeit geschätzt werden. Wir sind ja (hoffentlich) stolz auf das, was wir leisten. Allemal die Software Craftsmen sollten sich diesem Gefühl verbunden sehen.

Wie drücken wir denn aber anderen unsere Wertschätzung aus? “Gut gemacht!” mag ja im Kollegenkreis probat sein, doch in anonymen Beziehungen ist es schwieriger. Klar, der positive Kommentar eines Leser zu einem Blogbeitrag von mir freut mich. Und weitere positive Kommentare freuen mich noch mehr.

Positive Kommentare skalieren jedoch nur schlecht. Und irgendwann, ja, das gebe ich zu, irgendwann sind sie mir auch nicht mehr genug. Denn von positiven Kommentaren kann ich meine Miete nicht bezahlen. Niemand lebt von Luft und Liebe und Schulterklopfen. So ist das halt grad noch in unserer Welt. Deshalb haben wir gelernt, Wertschätzung in Geld auszudrücken und Geld als Wertschätzung zu akzeptieren. (Und wer das nicht glaubt, der verzichte einfach auf die nächste Gehaltserhöhung.)

Dass nicht-monetäre Wertschätzung ihre Grenzen hat, zeigt sich für mich auch im real existiert habenden Sozialismus. Dort wurden Orden als Wertschätzung verteilt. Helden der Arbeit wurden gekürt. Aber hat das zufrieden gemacht? Offensichtlich nicht dauerhaft.

Wertschätzung in einer Form, die den Empfangenden in die Lage versetzt, sie auch noch in die Erfüllung anderer Bedürfnisse zu konvertieren, ist doppelt gegebene Wertschätzung.

Geld ist nicht alles. Geschenke zu Weihnachten sollten nicht Bedeutung allein durch ihren Preis bekommen. Das ist selbstverständlich. Nur geht es mir grad nicht um Weihnachten, sondern eine essenziell ökonomische Situation: die Nutzung von mit Mühe hergestellten Produkten, seien das Entwicklervideos oder Code-Repositories.

Wenn wir für diese Produkte Geld bezahlen, dann tragen wir nicht nur zu ihrem Erhalt bei (s.o.), sondern drücken damit auch noch Wertschätzung aus. Das sollten wir nicht abtun.

Wir möchten wertgeschätzt werden? Dann sollten wir bewusster selbst wertschätzen. Das kann in Form von positiven Äußerungen sein – am Ende skaliert Geld aber besser. Uncle Bob könnte die vielen wertschätzenden persönlichen Kommentare gar nicht wertschätzen. Aber wenn er auf seine Paypal-Abrechnung schaut, fühlt er sich bestimmt wertgeschätzt. Das mag dann abstrakter sein, aber es kommt an. Ja, ich glaube, dass Uncle Bob meine 12 USD Wertschätzung wahrnimmt. Nicht persönlich, aber doch.

Wertschätzung dreht sich auch in einer Spirale. Sie wird allseits größer, wenn wir bereit sind, wertzuschätzen. Sie wird kleiner, wenn wir damit zurückhaltend sind. Was wollen wir?

Beim Geld wie bei der Wertschätzung ist es so, dass wir (mittel- bis langfristig) nicht damit rechnen können, etwas zu bekommen, was wir nicht bereit sind zu geben.

Das Zucken anlässlich Uncle Bobs Video hat mich aufgerüttelt. Ich werde mich bemühen, in Zukunft bewusster erstmal zu Geben.