Business-Blog | adesso insurance solutions

Von Spezifikationen, Entwicklern und Äffchen

Geschrieben von Jonathan Dittrich | 29.06.2022

 

Typischerweise beginnt Softwareentwicklung heute mit einer Spezifikation. In ihr werden die Anforderungen gesammelt, die die Software später erfüllen muss. Wer versucht zu verstehen, wie eine Spezifikation im Detail auszusehen hat, und zudem in einigen Projekten unterwegs war, ist schnell verwirrt. Letztlich kann alles von User Stories auf Klebezetteln bis Pseudo-Code in extra dafür angelegten formalen Sprachen als Spezifikation gelten.

Wendet man sich mit dieser Fragestellung an das IREB (das International Requirements Engineering Board), scheint die einzige Antwort zu sein, dass es kontextabhängig ist, was für eine Spezifikation sinnvoll ist, was sie umfasst und wie sie zu formulieren ist. Das können wir nur so akzeptieren und nicht erwarten, den gleichen Grad an Formalität und Uniformität, den wir in Programmcodes kennen, auch in Spezifikationen vorzufinden.

Nichtsdestotrotz lassen sich einige kontextunabhängige Punkte zu Spezifikationen und ihrem Verhältnis zum fertigen Code festhalten. In diesem Blog-Beitrag werden einige dieser Punkte erarbeitet – mit einem besonderen Blick auf die Implikationen für die Rollen von Spezifikateuren (also Requirements Engineers, Business Analysts etc.) und Entwicklern sowie ihr Verhältnis zueinander.

Spezifikationen und der Lösungsraum

Wie verhalten sich Spezifikation und Implementierung zueinander? Einfach gesagt, stellt die Implementierung Funktionalitäten bereit, welche die Anforderungen aus der Spezifikation erfüllen. Damit ist das Verhältnis zwischen Spezifikation und Implementierung aber nicht eindeutig. Die Anforderungen ein und derselben Spezifikation können durch verschiedene Implementierungen erfüllt werden. Es gibt also zu einer Spezifikation mehrere mögliche Implementierungen. Die Menge aller möglichen Implementierungen einer Spezifikation werden wir im Folgenden den Lösungsraum einer Spezifikation nennen.

Lösungsräume verschiedener Spezifikationen können unterschiedlich groß sein (also unterschiedlich viele mögliche Implementierungen umfassen). Betrachten wir ein Beispiel: Angenommen unsere Spezifikation verlangt, dass eine Menge von Paketen aufsteigend nach der Kennzahl jedes Pakets sortiert wird. Der Lösungsraum für diese Spezifikation umfasst damit alle Sortieralgorithmen, also bspw. bekannte Implementierungen wie Bubble Sort, Merge Sort, Insertion Sort und Heap Sort. Erweitern wir unsere Spezifikation um die Anforderung, dass auch sehr große Mengen von Paketen ohne einen quadratischen Anstieg der Sortierdauer sortiert werden sollen, verkleinert sich der Lösungsraum.

Im schlimmsten Fall (also einfach gesagt, wenn die Ausgangsmenge von Paketen möglichst unsortiert ist) steigt die Dauer des Sortiervorgangs zur Menge der zu sortierenden Pakete im Fall der Implementierungen Bubble Sort und Insertion Sort quadratisch an. Wird das durch eine weitere Anforderung – bspw. durch eine Angabe über die zulässige Dauer – ausgeschlossen, so verkleinert sich der Lösungsraum und beinhaltet u. a. die beiden Implementierungen Bubble Sort und Insertion Sort nicht mehr.

Die Spezifikation als Menge von Anforderungen entscheidet also über die Implementierungen, die im Lösungsraum enthalten sind, und legt damit auch seine Größe fest. Im Folgenden werden einige Nachteile erörtert, die zu kleine und zu große Lösungsräume mit sich bringen.

Nachteile eines zu großen Lösungsraums 

Werden Details in der Spezifikation weggelassen oder sind die Anforderungen eher vage, ist der Lösungsraum oft zu groß. Dieses Szenario birgt die Gefahr, dass die Spezifikation nicht alle tatsächlichen Anforderungen des Kunden enthält. Damit umfasst der Lösungsraum auch Implementierungen, die nicht zur gewünschten Software passen.

Des Weiteren birgt diese Situation gewisse Gefahren für die Rolle des Spezifikateurs. Erstens besteht die Gefahr, dass dieser zum RE-Monkey degradiert wird. In dieser Rolle ist der Spezifikateur in keiner konzeptionellen Arbeit involviert, sondern erfasst in erster Linie die Aussagen der Stakeholder. Es findet kein Abgleich mit der bisherigen Infrastruktur (bisherige Implementierungen, Umsysteme, Geschäftsvorgänge etc.) statt, sondern es werden Anforderungen unkritisch und unreflektiert übernommen. 

Zweitens ist der Spezifikateur damit weit von der tatsächlichen Implementierung und damit von der Software entfernt. Es wird eine unspezifische Spezifikation abgegeben und darauf vertraut, dass der Entwickler aus dem riesigen Lösungsraum eine passende Implementierung auswählt. Letztendlich hat der Spezifikateur aber keinerlei Verständnis davon, wie die erfassten Anforderungen in der Software umgesetzt werden. Das kann technisch funktionieren, ist aber im Mindesten degradierend für die Rolle des Spezifikateurs.

Nachteile eines zu kleinen Lösungsraums
 
Das Gegenteil entsteht durch eine zu detaillierte Spezifikation. Im schlimmsten Fall besteht die Spezifikation aus Pseudo-Code und gibt algorithmisch (wenn auch offen für verschiedene Programmiersprachen) Zeile für Zeile vor, wie Anforderungen umzusetzen sind. Damit entsteht ein zu kleiner Lösungsraum.

Das erste Problem eines zu kleinen Lösungsraums ist, dass durch die Spezifikation potenziell bessere Lösungen aus dem Lösungsraum ausgeschlossen werden. Es ist nicht ungewöhnlich, dass ein erfahrener Entwickler elegantere (also bspw. kürzere oder einfacher zu erweiternde/wartende) Implementierungen in einem Lösungsraum findet als ein Spezifikateur. Gehen wir jedoch davon aus, dass sich der Entwickler an die Spezifikation hält, ist das in diesem Fall nicht mehr möglich. Entscheidet sich der Entwickler gegen die Spezifikation, muss die Frage gestellt werden, welchen Sinn die Spezifikation überhaupt noch erfüllt.

Ein zweites Problem kann entstehen, falls die Spezifikation nicht in Pseudo-Code formuliert ist, aber dennoch übermäßig spezifisch ist. Da der Lösungsraum sehr klein ist, kann es dem Entwickler schwer fallen, eine Implementierung zu finden, die tatsächlich noch darin enthalten ist. Wäre die Spezifikation offener formuliert und der Lösungsraum damit größer, wäre es auch einfacher, passende Implementierungen zu finden.

Ein letztes Problem betrifft den Status des Entwicklers in der Entwicklung von Software mit einem zu kleinen Lösungsraum. Wird der Spezifikateur bei einem zu großen Lösungsraum zum RE-Monkey, so wird der Entwickler bei einem zu kleinen Lösungsraum zum Code-Monkey. Seine wesentliche Aufgabe besteht nicht mehr im Verstehen der Anforderungen und im Finden einer adäquaten Lösung, sondern im Übersetzen von Pseudo-Code in Code der gewünschten Programmiersprache. Im schlimmsten Fall lassen sich seine Aufgaben auch durch einen Code-Generator erledigen.

Eine weitere Konsequenz dieses Problems ist, dass der Entwickler kein echtes Verständnis der entwickelten Software mehr hat. Wer nur Pseudo-Code abtippt, versteht nicht, was die Software eigentlich tut und warum sie gewisse Probleme auf eine bestimmte Art und Weise löst. Ähnlich fehlt auch ein Verständnis dafür, wie sich neue Probleme oder sich ändernde Anforderungen im System umsetzen lassen.

Die Lösung aller Probleme
 
Die angesprochenen Probleme eines zu kleinen, sowie eines zu großen Lösungsraums legen nahe, dass es darum geht, einen Lösungsraum mit der perfekten Größe zu finden. Diesen Ansatz zu verfolgen, ist jedoch vergebliche Mühe. Oft lässt sich erst mit der fertigen Software beurteilen, welcher Lösungsraum und welcher Detailgrad einer Spezifikation angemessen gewesen wäre.
 

Statt vor der eigentlichen Entwicklung nach dem perfekt großen Lösungsraum zu suchen, gibt es folgende, bessere und einfachere Möglichkeiten: Es ist leichter, einen zu großen Lösungsraum im Nachhinein einzuschränken, als einen zu kleinen Lösungsraum wieder zu erweitern. Weitere Anforderungen oder die detailliertere Formulierung bestehender Anforderungen lassen sich auch im Entwicklungsprozess noch einfügen. Tatsächlich kann die Notwendigkeit mancher Details in den Anforderungen erst im Entwicklungsprozess ermittelt werden. Liegt hingegen bspw. eine Spezifikation mit Pseudo-Code vor, ist es äußerst schwierig, daraus wieder fachliche Anforderungen abzuleiten.

Da die nachträgliche Einschränkung des Lösungsraums einfacher ist, sollte man tendenziell Spezifikationen schreiben, die einen solch großen Lösungsraum zulassen. Wie aber können dann die oben beschriebenen Probleme eines zu großen Lösungsraums gelöst werden, ohne ihn vorab zu weit einzuschränken? Damit keiner zum Äffchen wird (RE-Monkey oder Code-Monkey), sollte man die Vorstellung aufgeben, dass die Aufgabe des Spezifikateurs mit der Abgabe des Spezifikation-Dokuments an den Entwickler abgeschlossen ist.

Stattdessen müssen die beiden im Anschluss miteinander kommunizieren. Der Entwickler muss die fachlichen Anforderungen verstehen und der Spezifikateur muss zumindest den Ansatz der technischen Umsetzung verstehen, damit beide gemeinsam eine Lösung finden können. Dabei hat jeder seine Spezialbereiche. Der Spezifikateur kennt die Anforderungen und die fachlichen Hintergründe besser, der Entwickler hingegen hat ein besseres Verständnis von Details der bisherigen Architektur, Feinheiten von Frameworks etc.

Fachlichkeit und technische Umsetzung lassen sich als Extrembereiche eines Kontinuums verstehen. Die beiden Endpunkte werden einerseits durch den fachlichen Endnutzer und andererseits durch die Architektur des Systems vorgegeben. Manchmal gewinnt man den Eindruck, dass Spezifikateur und Entwickler sich jeweils an einem äußeren Punkt dieses Kontinuums verstehen und ihre Verantwortung nur in einem kurzen Abschnitt wahrnehmen. Tatsächlich sollten die beiden sich jedoch einander annähern, um eine gemeinsame Kommunikationsgrundlage zu schaffen. Der Spezifikateur sollte ein Grundverständnis der technischen Umsetzung haben, um nachvollziehen zu können, wie der Entwickler versucht, die von ihm verstandenen fachlichen Anforderungen umzusetzen. Der Entwickler sollte ein Grundverständnis der Fachlichkeit und der Anwendungsfälle besitzen, um überhaupt den Lösungsraum zu kennen und eine der besten Lösungen auswählen zu können.

Es geht nicht darum, dass jeder auf dem Stand eines Senior-Entwicklers oder eines fachlichen Angestellten ist. Beide sollen ihr Spezialwissen und ihre Vertiefungen haben. Ein Spezifikateur muss nicht verschiedene Möglichkeiten zum Vergleichen von Objekten in Java kennen und der Entwickler muss nicht wissen, dass Wartezeiten für Krankenversicherungen tarifübergreifend in der MB/KK geregelt sind. Aber ein Spezifikateur sollte wissen, was ein Objekt und OOP sind und ein Entwickler sollte wissen, was Wartezeiten sind (angenommen, es geht um die Erstellung von Software für Krankenversicherungen). Damit können sie gemeinsam den Lösungsraum definieren, großartige Software bauen und keiner wird dabei zum Äffchen.

Sie möchten erfahren, wie die Software von adesso insurance solutions bei der Digitalisierung von Versicherungen hilft? Dann wenden Sie sich gerne an unseren Experten Karsten Schmitt, Head of Business Development.