Eine Replik auf Wolfgang Pleus’ Artikelserie „Sustainable Service Design“

Sustainable Service Design: Nachhaltig – oder nur langlebig?

Nils Preusker

© Shutterstock/Ivan Ryabokon

Wolfgang Pleus kritisiert in seiner Artikelserie „Sustainable Service Design“ (Java Magazin 2.2015 und 3.2015), dass Nachhaltigkeit in der Softwarebranche bisher zu wenig Beachtung geschenkt werde. Ich möchte dem einen grundlegend anderen Ansatz entgegenstellen: Statt der Servicekontrakte könnte auf universelle Schnittstellen gesetzt werden, um Wiederverwendbarkeit zu erreichen.

Lange etablierte Designprinzipien können dabei helfen, Software schon in der Konzeption besser auf den Nutzen für Auftraggeber und Endanwender zuzuschneiden. Statt sich auf Langlebigkeit und strikte Vorgaben zu fixieren, schlage ich vor, den Austausch zwischen Entwicklern und Stakeholdern in den Mittelpunkt zu stellen und eine Umgebung zu schaffen, in der alle Beteiligten ihr kreatives Potenzial ausschöpfen können. Denn Langlebigkeit alleine bringt keine Nachhaltigkeit, wenn der Nutzen fehlt.

Pleus bemängelt, dass wir das Rad ständig neu erfinden, indem wir Software nach einigen Jahren wegwerfen und neu implementieren. Da beispielsweise Banken und Versicherungen seinen Beobachtungen zufolge ohnehin über lange Zeiträume gleichbleibende Datenstrukturen und Geschäftslogik verwenden, schlägt er einen Ansatz vor, den er „Nachhaltiges Servicedesign“ nennt: Services sollen abstrakt und technologieneutral beschrieben werden, um kurzlebige Technologietrends zu überdauern. Konkrete Implementierungen werden dann durch technologiespezifische Bindings umgesetzt.

Doch würden nicht auch Banken und Versicherungen von mehr Flexibilität in der Softwareentwicklung profitieren? Mit Wolfgang Pleus’ „Nachhaltigem Servicedesign“ zumindest nicht. Wie im Folgenden anhand eines kurzen Praxisbeispiels gezeigt wird, suggeriert der Name zwar Leichtgewichtigkeit und Effizienz. In der Praxis bewirkt der Ansatz aber letztendlich das Gegenteil. Services müssen zunächst abstrakt beschrieben und dann durch konkrete Bindings implementiert werden. Um sich „zukünftig in möglichst vielen fachlichen und technischen Kontexten verwenden“ zu lassen, erfordern sie für jeden neuen technischen Kontext ein neues Binding. Auch hier wird also häufiger mal das Rad neu erfunden, allerdings mit noch mehr Aufwand.

Aus unveränderter Geschäftslogik und gleichbleibenden Datenstrukturen folgert Pleus, Unternehmen würden davon profitieren, ihre Services in Form von langlebigen und technologieunabhängigen Servicebeschreibungen zu definieren. Was aber, wenn die Langlebigkeit von Geschäftslogik und Datenstrukturen eher auf schwergewichtige IT-Systeme und veränderungsfeindliche Organisationsstrukturen zurückzuführen ist? Dann gibt Wolfgang Pleus’ Auffassung zwar eine richtige Beobachtung wieder, nicht aber die tatsächlichen Bedürfnisse der Fachabteilungen und Kunden. Die Langlebigkeit weiter zu manifestieren wäre dann nicht im wirtschaftlichen Interesse des Unternehmens.

Gehen wir einmal davon aus, dass auch Unternehmen in eher konservativen Branchen von mehr Flexibilität profitieren würden. Banken könnten zum Beispiel mehr Kunden erreichen, wenn sie es schaffen würden, neue Produkte schneller auf den Markt zu bringen. Onlineangebote und mobile Apps können auf Basis von regelmäßigem Nutzerfeedback kontinuierlich verbessert werden. Dazu ist jedoch die Organisation der Entwicklung in kurzen Releasezyklen erforderlich, Nutzungsdaten müssen ausgewertet und in der Konzeptentwicklung miteinbezogen werden. In der Praxis scheitern viele Unternehmen jedoch bereits daran, ihre mobile Software an die häufigen Versionssprünge von iOS und Android anzupassen.

Doch wollen wir nicht lieber den Markt gestalten, statt ihm hinterherzulaufen? Was ambitioniert klingt, ist manchmal schon durch etwas mehr Fokus und ein früher veröffentlichtes Feature möglich. Um dahin zu kommen, sollten wir aber bei den Anforderungs- und Entwicklungsprozessen ansetzen, statt Services langfristig festzuschreiben. Indem wir Kundennutzen und Kundenzufriedenheit an erste Stelle setzen können wir die Wünsche und Bedürfnisse unserer Endnutzer besser verstehen und zielgerichtet nur das entwickeln, was wirklich benötigt wird. So erhöhen wir die Effizienz der Softwareentwicklung, steigern den Wert unserer Produkte und erreichen Nachhaltigkeit durch Ressourcenschonung.

Praxistest: Nachhaltiges Servicedesign und REST Binding

Auch auf der technischen Detailebene stellt sich die Frage, ob Wolfgang Pleus’ Vorgehen am richtigen Punkt ansetzt. Sehen wir uns das anhand eines einfachen Beispiels an. Um keine fachlichen Assoziationen zu wecken, begeben wir uns in eine unschuldige Domäne und setzen ein API zur Verwaltung von Hundewelpen um. Unser Hundewelpen-API in Version 1.0 könnte so aussehen:

getAllDogs, foodNeeded, getLocation, getDog, saveDog, replaceSittingDogsWithRunningDogs, healthCheck etc.

Wolfgang Pleus schlägt nun vor, die Datenstrukturen mithilfe von XML Schema zu beschreiben und für die Operationen Java-Interfaces zu verwenden. Da er eigentlich technologieneutrale Servicebeschreibungen verspricht, erklärt er XML Schema und Java kurzerhand zu „langfristig stabilen Basistechnologien“. Im nächsten Schritt sieht sein Ansatz vor, dass jede Operation mit einem Request- und einem Response-Objekt versehen wird. Für konkrete Implementierungen sollen dann so genannte Bindings erzeugt werden.

Am Beispiel von saveDog könnte die Servicebeschreibung so aussehen: Wir definieren eine SaveDogRequest– und eine SaveDogResponse-Datenstruktur in XML Schema und ein Java-Interface mit der Methode SaveDogResponse saveDog(SafeDogRequest);. Die Liste aller Operationen landet dann am Ende in einem XML-Dokument, das den Kontrakt darstellt. Daraus sollen dann sowohl die Datentypen in der jeweiligen Programmiersprache als auch die konkreten Services und die Dokumentation generiert werden.

Wie sähe nun beispielsweise ein REST- bzw. http- und JSON-Binding aus? Es ergeben sich URLs wie http://somedomain.org/public-api/v1/getAllDogs, http://somedomain.org/public-api/v1/foodNeeded etc. Für jeden dieser URLs wird dann noch ein spezifisches Request- und Response-Objekt benötigt. Das wären allein für unser noch unvollständiges API bereits sieben URLs und vierzehn Request- und Response-Objekte.

Wer auf REST-Prinzipien Wert legt, wird bereits bei den URLs ein gewisses Unbehagen verspüren. Schließlich versucht man hier gewöhnlich, Ressourcen wie http://somedomain.org/oublic-api/v1/dogs zu identifizieren, statt Operationen in URLs abzubilden. Auch die Request- und Response-Objekte sind bei einem HTTP- und JSON-Binding eigentlich nicht sinnvoll, da die Operationen üblicherweise über die HTTP-Verben GET, POST, PUT DELETE und evtl. PATCH ausgedrückt werden, und Statuscodes und HTTP-Header über Erfolg oder Misserfolg der Operation Auskunft geben. Wären wir nicht gezwungen, die Request- und Response-Objekte zu verwenden und Operationen als Methoden auszudrücken, könnten wir z. B. eine Liste von Hundewelpen über einen HTTP-Request mit „GET http://somedomain.org/oublic-api/v1/dogs“ laden und würden HTTP 200 OK und ein Array von JSON-Objekten mit Hundewelpen zurückbekommen. Für alle Operationen, die für Hundewelpen zur Verfügung stehen, würden wir lediglich eine Datenstruktur, also z. B. ein JSON-Objekt Dog oder Puppy benötigen. Alle oben genannten Operationen ließen sich dann über einen URL, eine Datenstruktur und die Standard-HTTP-Verben abbilden. Statt „saveDog“ also „POST http://somedomain.org/oublic-api/v1/dogs Content-type: application/json“ und ein JSON-Objekt „Dog“. In der HTTP-Response bekämen wir einen HTTP-Statuscode „201 Created“ und z. B. den Location-Header „http://somedomain.org/oublic-api/v1/dog/hasso“, um später auf den erzeugten Hundewelpen zuzugreifen.

Doch der „Sustainable-Service-Design“-Ansatz fordert von uns die Verwendung von Request- und Response-Objekten und führt schließlich mit großer Wahrscheinlichkeit dazu, dass wir alle Operationen über HTTP POST tunneln.

In der Design- und Umsetzungsphase fallen also deutliche Mehraufwände an, und beim Entwickeln der Bindings bleibt uns die Möglichkeit verwehrt, die spezifischen Vorteile der jeweiligen Umsetzungstechnologie auszureizen.

Nachhaltiges Vorgehen

Stellt sich die Frage, wie wir es besser machen können. Ich glaube, dass das Agile Manifest hierfür einen guten Ausgangspunkt bietet. Seit mittlerweile fast anderthalb Jahrzehnten liefern uns die gesammelten Erfahrungen der damaligen Unterzeichner ein Wertesystem, an dem sich Softwareentwickler und Softwarearchitekten in ihrer Arbeit orientieren können. Das Agile Manifest empfiehlt, Kommunikation, funktionierende Software und das Reagieren auf Veränderung in den Mittelpunkt unseres Vorgehens zu stellen. Konsequent angewandt führt das meiner Ansicht nach zur Vermeidung von unnötigem Aufwand und zu besser auf Kundenbedürfnisse zugeschnittener Software – wichtige Schritte also auf dem Weg zur nachhaltigen Softwareentwicklung.

Statt uns in erster Linie auf Prozesse und Werkzeuge zu stützen (wie im „Sustainable Service Design“ z. B. bei automatischen Transformationen mit Maven-Plug-ins), sollten wir mehr auf Individuen und Interaktionen vertrauen, zum Beispiel, indem wir die abteilungsübergreifende Kommunikation fördern, uns regelmäßig mit dem Kunden über den Entwicklungsstand austauschen oder Praktiken wie Pair Programming im Team etablieren – es gibt viele Möglichkeiten, auf organisatorischer Ebene dafür zu sorgen, dass Projektbeteiligte Verantwortung übernehmen und alle gemeinsam dafür sorgen, ein Vorhaben zum Erfolg zu führen.

In Wolfgang Pleus’ Ansatz wird durch „XSLT-Transformationen […] der Kontrakt während des Build-Prozesses automatisch in eine lesbare Dokumentation transformiert“. Dadurch soll die Zusammenarbeit zwischen Fach- und IT-Spezialisten gestärkt werden. Doch das im Artikel abgebildete Beispiel entpuppt sich als eine rohe Liste von Methoden und Datentypen. IT-Experten könnten mit Programmcode mehr anfangen, und dass Fachexperten jemals einen Blick auf diese Dokumentation werfen, halte ich für zweifelhaft. Wahrscheinlicher ist, dass diese Art von autogenerierter Dokumentation im Regal (bzw. im Wiki) verstaubt.

Um effektive Dokumentation zu erzeugen, sollten wir zunächst über die Zielgruppe nachdenken. Handelt es sich zum Beispiel um Schnittstellen, die durch APIs von anderen IT-Systemen angesprochen werden, dann sollten wir als Endanwender Softwareentwickler adressieren. Die Ausrichtung auf eine bestimmte Zielgruppe erhöht den Fokus und spart so Zeit und Aufwand. Ähnlich wie bei der Entwicklung grafischer Benutzeroberflächen lohnt es sich außerdem, frühzeitig Feedback einzuholen. Dazu bieten sich im Falle von REST-APIs Tools wie api-mock oder raml-mockup an. Beide bieten eine einfache Notation (Markdown bzw. Yaml), um APIs zu beschreiben und mit der Beschreibung einen Mock-Server zu starten. Die Beschreibungssprachen sind jeweils so ausdrucksstark, dass wir beispielsweise im Rahmen eines kurzen Designworkshops einfach mitschreiben können und das API dann direkt anhand einer ersten lauffähigen Version ausprobieren können. So können wir bereits Feedback von Anwendern einholen, bevor wir die erste Zeile Code geschrieben haben.

Analog zu diesem Vorgehen können wir bei grafischen Benutzeroberflächen mit Papierprototypen arbeiten. Auch Techniken wie „Guerilla User Testing“, also der spontane Usertest mit freiwilligen Probanden im Café an der Ecke oder sogar auf der Straße bieten sich an. Zumindest sollten wir uns nicht davor scheuen, ausgewählte Benutzer so früh wie möglich während der Umsetzung mit den Zwischenprodukten arbeiten zu lassen. So können wir frühzeitig Feedback einholen und das Endprodukt iterativ verbessern.

Weitere wichtige Aspekte sind Unit, Last- und Regressionstests sowie frühzeitige Integration und die Vorbereitung des Betriebs. Je früher wir lauffähige Software produzieren, desto früher können wir Test- und Betriebsinfrastruktur aufbauen und mit der Integration in Umsysteme beginnen. Um Verzögerungen beim Livegang vorzubeugen, hilft es erfahrungsgemäß, die Infrastruktur von Anfang an mitzuentwickeln. Ansonsten trifft die alte Projektmanagementweisheit zu: Die ersten 90 Prozent des Projekts kosten 90 Prozent der Zeit. Die restlichen 10 Prozent kosten die anderen 90 Prozent.

Zu den „SSD-Prinzipien“ a la Wolfgang Pleus gehört unter anderem „konsequent Contract First“. Bevor wir also eine Zeile Code schreiben, gehen wir erst mal in die Vertragsverhandlung und meißeln den Servicekontrakt in Stein. Wie wir im vorherigen Absatz gesehen haben, tragen frühzeitiges Feedback und lauffähige Software aber zu einem besseren Endprodukt und mehr Effizienz im Entwicklungsprozess bei. Statt die Servicekontrakte vorab festzuzurren, sollten wir den Kunden – ob es sich um Fachabteilungen, Entwicklerkollegen oder externe Kunden handelt – besser frühzeitig mit ins Boot holen und auf offene Kommunikation setzen. Wenn die Erfüllung eines Vertrags im Vordergrund steht, laufen wir nämlich Gefahr, defensiv vorzugehen statt konstruktiv an Lösungen zu arbeiten, und statt mitzudenken Features stur nach Spezifikation zu bauen. So wird einerseits oft mehr als notwendig geliefert (Verschwendung), andererseits leidet die Qualität und Sinnhaftigkeit der Software. Am Ende profitieren jedenfalls weder wir noch die Auftraggeber davon, wenn Software stur nach Plan und an Wünschen und Bedürfnissen der Endanwender vorbei entwickelt wird. Besser versuchen wir da, das kreative Potenzial auszuschöpfen, das entsteht, wenn man gemeinsam die Fachdomäne erkundet und das Entwicklerteam die Bedürfnisse der Endanwender versteht. Neben einem besseren Resultat bei der Software erreichen wir damit obendrein auch noch mehr Zufriedenheit bei den Entwicklern. Schließlich ist es ein gutes Gefühl, sich einbringen und mit seiner Arbeit identifizieren zu können.

Indem wir die oben genannten Werte leben, sind wir unweigerlich besser für den Umgang mit Veränderungen aufgestellt. Mehr Austausch, auch über Abteilungsgrenzen hinweg, hilft uns, die Domäne und die Bedürfnisse der Endanwender besser zu verstehen und potenzielle Probleme oder widersprüchliche Anforderungen im Voraus zu identifizieren und zu klären. Indem wir frühzeitig lauffähige Software produzieren, fallen auch technische Hürden früher auf. Zusätzlich sind wir in der Lage, ausgewählte Endnutzer frühzeitig das neue System ausprobieren zu lassen und Feedback einzusammeln. So lässt sich auch feststellen, ob es Missverständnisse bei den Anforderungen gab. Features, die sich auf diese Weise als überflüssig erweisen, können einfach aus den Anforderungen gestrichen werden, um unnötigen Aufwand zu vermeiden. Und schließlich sorgen kurze Iterationen dafür, dass sich Verbesserungsvorschläge jederzeit einbringen lassen. Selbst wenn sich grobe Missverständnisse abzeichnen, lässt sich so noch rechtzeitig der Kurs korrigieren.

Designprinzipien und Technologien

Auf der Architektur- und Umsetzungsebene bietet es sich an, dass wir uns auf erprobte Designprinzipien besinnen. Die Unix-Philosophie zum Beispiel sieht vor, Programme zu schreiben, die nur eine Aufgabe erledigen und diese gut machen. Darüber hinaus sollen Programme zusammenarbeiten und Textströme verarbeiten, da es sich dabei um eine universelle Schnittstelle handelt. Wenn wir Textströme durch JSON und HTTP oder leichtgewichtige Messaging-Technologien ersetzen, sind wir recht nah an einem Architekturansatz, von dem in letzter Zeit immer häufiger die Rede ist: Microservices. Martin Fowler beschreibt diesen Architekturansatz in einem sehr lesenswerten Artikel auf seiner Webseite. Einfach ausgedrückt bedeutet der Microservice-Ansatz, dass Anwendungen in mehrere Einzelkomponenten zerlegt werden, die jeweils in ihrem eigenen Prozess laufen und über leichtgewichtige Mechanismen miteinander kommunizieren. Zur asynchronen Kommunikation kommen dabei häufig leichtgewichtige Messaging-Technologien wie RabbitMQ oder ZeroMQ zum Einsatz, während die synchrone Kommunikation über „HTTP-Ressourcen-APIs“ abgebildet wird. Während Wolfgang Pleus in seinem Artikel weiterhin Themen wie Routing und Transformationen im Enterprise Service Bus (ESB) verortet, geht Martin Fowler einen Schritt weiter und spricht von „Smart Endpoints and Dumb Pipes“. Unix lässt grüßen.

Beim Microservice-Ansatz lockt natürlich die Versuchung, Teams nach Serviceverantwortung aufzuteilen. Damit würden wir jedoch Komponententeams schaffen, die langfristig zu Wissenssilos führen und dem ganzheitlichen Denken bei der Featureentwicklung entgegenwirken. Mithilfe von Microservice-Architekturen können wir, richtig angewandt, Komplexität in den Griff bekommen und Software modular weiterentwickeln. Um die Software zu erneuern, können einzelne Services aktualisiert oder ganz ersetzt werden. Auch in Bezug auf Wartbarkeit und Skalierbarkeit profitieren wir durch den Fokus auf Modularisierung und Kapselung bei Microservice-Architekturen.

Bei aller Begeisterung sei aber auch darauf hingewiesen, dass Microservice-Architekturen besondere Anforderungen an Entwickler stellen. Aufgrund der starken Modularisierung und der Kommunikation über das Netzwerk sollten sie sicher im Umgang mit Kommunikationsprotokollen und Messaging sein. Da sich Prozesse über mehrere Komponenten oder Services erstrecken, ist ganzheitliches Denken wichtig. Wer aber neugierig ist, gerne plattformübergreifend denkt und sich vielleicht sogar schon in verschiedenen Programmiersprachen zu Hause fühlt, ist bestens für die Entwicklung in Microservice-Umgebungen aufgestellt.

Fazit

Wenn wir Nachhaltigkeit nur über die Lebensdauer von Serviceimplementierungen definieren, bleibt dabei die Flexibilität auf der Strecke. Daher schlage ich ein ganzheitliches Vorgehen vor. Organisatorisch können wir Kommunikation, Offenheit und Austausch fördern und den Rahmen schaffen, in dem effizient Software entwickelt wird. Auf der technischen Detaileben stehen uns erprobte Designprinzipien und leichtgewichtige Kommunikationsprotokolle zur Verfügung. Die lassen sich sowohl in modernen Microservice-Architekturen als auch in klassischen, weniger verteilten Anwendungen einsetzen. Schließlich sind Architekturkonzepte und Technologien aber auch nur Mittel zum Zweck. Denn wirklich nachhaltiger Mehrwert entsteht, wenn wir mit gerade soviel Aufwand wie nötig die Bedürfnisse unserer Zielgruppe erfüllen.

Aufmacherbild: Allowed and forbidden signs with text SQL in circle von Shutterstock / Urheberrecht: Ivan Ryabokon

Geschrieben von
Nils Preusker

Nils Preusker ist Softwarearchitekt bei MovingIMAGE24 in Berlin, wo er seit 2013 an einer Videomanagementplattform arbeitet, mit der Unternehmen ihre Videoinhalte verwalten und einfach ins Netz bringen können. MovingIMAGE24 arbeitet mittlerweile unternehmensweit nach Scrum, mehr dazu unter https://miss.movingimage.com.

Kommentare

Hinterlasse einen Kommentar

1 Kommentar auf "Sustainable Service Design: Nachhaltig – oder nur langlebig?"

avatar
400
  Subscribe  
Benachrichtige mich zu:
Sven
Gast
Naja, wenn man die Programmiersprache nicht als langlebig („langfristig stabile Basistechnologie“) bezeichnen kann, was dann? Wenn die Programmiersprache gewechselt wird, muss eh sämtlicher Code neu geschrieben werden. Und XML/XML-Schema festzulegen finde ich auch in Ordnung. Selbst wenn XML mal irgendwann durch etwas anderes abgelöst werden soll, lässt sich XML wunderbar in andere Formate migrieren, weshalb es nicht teuer wäre wenn sich die Technologie ändern sollte. Ich finde die Agile-Ansätze auch sinnvoll, aber wenn es sich irgendwo lohnt in nachhaltige Spezifikation zu investieren, dann genau bei APIs/Schnittstellen. Schnittstellen sollten stabil sein und häufig ist es keine Option eine Schnittstelle zu ändern… Read more »