Das Samurai Prinzip

Tags:

Ich weiss, ihr wärt lieber Ninjas als Samurai. Kämpfer im Dunkeln, schnell wie Neutrinos, agil wie das Scrumtier und tödlich wie der BSOD. Aber heute geht es um die Samurai. Also eigentlich geht es um Softwareentwicklung. Aber von vorne...

Die Samurai folgten einem Verhaltenscodex, dem Bushido. Darin ging es um Ehre, Mut, Treue und weiteres solch klebriges Zeugs. Ein Verstoss dagegen endete oft im rituellen Suizid. Darauf bezieht sich der folgende Spruch.

Kehre erfolgreich zurück, oder gar nicht.

Und was hat das jetzt mit Softwareentwicklung zu tun? Nun, damit ist gemeint, dass ein Funktionsaufruf nur bei erfolgreicher Verarbeitung etwas zurückgeben sollte, ansonsten aber eine Exception werfen.

Ein einfaches Beispiel: Wir brauchen eine Funktion, die einen User-Datensatz aus der Datenbank holt. Wird dieser nicht gefunden, soll nun nicht etwa null, false oder ein leeres User-Objekt zurückgegeben, sondern eine RecordNotFoundException geworfen werden.

Was aber, wenn wir einfach nur überprüfen wollen, ob der Datensatz existiert? Wir würden also erwarten, dass nichts gefunden wird. Wäre da eine RecordNotFoundException nicht falsch?
Nein, denn die Funktion die wir aufrufen wird findUserRecord() oder ähnlich heissen. Dadurch ist der Kontext der Funktion klar gegeben: Es soll ein Datensatz gefunden werden. Wollen wir schauen ob ein Datensatz existiert, müssen wir eine andere Funktion schreiben. Zum Beispiel hasUserRecord().

Durch diese Konvention werden wir automatisch dazu gezwungen Funktionen so zu schreiben, dass sie nur genau eine Aufgabe haben. Es entsteht auch automatisch ein Vertrag zwischen Funktion und Caller. Und der ist immer gleich:

Hey Caller, ich gebe dir nur im Erfolgsfall Daten zurück. Wenn was schief geht, dann musst du dich um die Ausnahme kümmern.

Man kann diese Verträge noch erweitern, wie beispielsweise bei Exception Guarantee. So darf dort die Funktion im Fehlerfall nichts am Zustand der Applikation verändern. Sprich: Wird eine Exception geworfen, muss vorher wieder der Zustand von vor dem Funktionsaufruf hergestellt werden. Dadurch ist vor dem Funktionsaufruf klar, dass wir entweder im Ausgangszustand oder im erwünschten Zielzustand landen. Und nichts dazwischen.

Wichtig anzumerken ist, dass der Caller die benötigen Rahmenbedingungen für die Funktion schaffen muss. Wenn die Funktion merkt, dass diese nicht gegeben sind, dann darf sie in aller Härte abbrechen. Dies wird dann als Logikfehler des Programmierers angesehen (und sollte gefixt werden) - und nicht als Laufzeitfehler.

Das Ganze hat natürlich auch Schattenseiten. So müssen Exceptions stets vom Caller gefangen werden. Dies bedeutet Mehraufwand beim Programmieren und kann auch zu verschachteltem, unübersichtlichem Code führen.

Ich muss eingestehen, dass ich dieses Programmierparadigma noch nie angewandt habe. Es klingt aber äussert spannend und ich werde es bei Gelegenheit testen. Habt ihr schon Erfahrungen damit oder könnt ihr euch vorstellen, so zu programmieren?

Ähnliche Artikel

Kommentare