Die Neuronen Schmiede setzt sich in erster Linie mit Themen im Bereich Software Entwicklung auseinander. Ein Fokus dabei sind robuste Web-Anwendungen.

Statechart Power: Robustheit mit State Machines modellieren

Permalink

Mit State Machines lässt sich gut veranschaulichen, wie robust eine gewählte Implementierung ist. Als Beispiel sehen wir uns einen kleinen Teil der Now or Never Gallery an. Nachdem eine Künstlerin eine Kaufanfrage für eines ihrer Kunstwerke erhalten hat, kann sie entscheiden, ob sie verkaufen möchte oder nicht. Wir sehen uns jetzt an wie unterschiedlich die Ablehnung modelliert werden kann.

Bei der Ablehnung einer Kaufanfrage müssen drei Dinge passieren.

  • Modifizieren des Datenstandes in der Datenbank.
  • Rückbuchen des Kaufbetrages über Stripe.
  • Informieren des Kunden per E-Mail.

Variante 1

Die naivste Variante geht implizit davon aus das immer alles funktioniert. Beim decline Event wird in die Datenbank geschrieben und es werden zwei asynchrone Tasks terminiert. Wie im Statechart zu sehen ist, ändert sich der State sofort in den Endzustand. Aus der Perspektive unserer Anwendung ist die Kaufanfrage abgelehnt.

Selbst, wenn die E-Mail niemals versendet wird und der API Aufruf nicht bei Stripe ankommt, glaubt unser System, das alles in Ordnung ist. Den Benutzern der Anwendung bietet sich dasselbe Bild einer heilen Welt.

Aber das ist eine Täuschung. In einem Fehlerfall gibt es manuellen Handlungsbedarf. Im Stripe Dashboard muss die Rückbuchung von Hand gemacht werden und der Kunde wird persönlich informiert.

Variante 2

In dieser Variante wird akzeptiert, dass es bei der Rückbuchung zu Fehlern kommen kann. Wie bei der ersten Variante wird beim decline Event die Welt in Bewegung gesetzt. Der Unterschied liegt in der Zustandsänderung in den refunding State. Er signalisiert dem System und idealerweise den Benutzerinnen das der Prozess noch nicht abgeschlossen ist.

Erst wenn die Rückbuchung erfolgreich durchgeführt wurde signalisiert das refund_done Event das der Prozess abgeschlossen ist. Zumindest in der modellierten Form. Ein Fehler beim E-Mail Versand hat weiterhin keine Auswirkung auf das System und bleibt für die Menschen unsichtbar.

An dieser Stelle könnte jemand argumentieren, dass das kein Problem ist, es handelt sich ja "nur" um E-Mails. Diese Haltung kann ich nicht nachvollziehen. Wenn es nicht wichtig ist, ob eine transaktionale E-Mail versandt wird, wieso versendest du sie überhaupt?

Variante 3

Diese State Machine zeigt die volle Ausprägung. Statt den asynchronen Task für den E-Mail-Versand bereits am Beginn zu terminieren, passiert das hier erst, nachdem die Rücküberweisung erfolgreich war. Des Weiteren ändert das refund_done Event den Zustand nur in den informing_customer State. Wie bei der Rücküberweisung signalisiert das für die Beteiligten, das die E-Mail noch nicht erfolgreich versandt wurde. Erst wenn auch das eingetreten ist, abgebildet als email_delivered Event, sind wir im Endzustand und fertig.