Loading...

State Is the Root of All Evil

17. August 2023
3 Minuten Lesezeit
Beitrag teilen:

Hi,

Was unterscheidet eine Anwendung von einer (mathematischen) Funktion?

Eine Funktion nimmt einen Input x und transformiert ihn zu einem Output. Wenn gilt f(x) = 2 * x, dann ist das Ergebnis dieser Funktion bei der Eingabe von jedem x immer gleich.

Es gibt keine Seiteneffekte. Wir nennen dieses Verhalten stateless.

Aber was hat das mit der Frage vom Anfang zutun? Eine Anwendung geht darüber hinaus. (Fast) jede Anwendung muss mit State arbeiten. Sobald wir I/O Operations in unserem System haben, haben wir inhärent State. Und häufig kann ein methodenaufruf, mit dem gleichen Input, zu unterschiedlichen Zeiten, unterschiedliche Resultate liefern. Und das ist auch nicht vermeidbar und liegt in der Natur der Aufgabe, die wir lösen wollen.

Ein API call auf GET /users wird immer ein anderes Resultat liefern, je nachdem welche User sich im System registriert haben. Das ist ja genau das, was es tun soll.

Aber was ist einfacher?

Natürlich ersteres.

Wenn unsere Methode stateless und damit deterministisch ist, dann ist sie:

  • Einfach zu testen. Wir müssen nur alle Randbedinungen für den möglichen Input abdecken. Vielleicht ist die Menge an Inputs sogar endlich und wir können alle überhaupt möglichen Werte testen.
  • Einfach anzupassen. Ein neuer Entwickler kann diese eine Methode in absoluter Isolution betrachten.
  • Einfach zu parallelisieren. Wir können diese Methode mit so vielen Threads und Prozessen gleichzeitig ausführen wie wir wollen. Es kann zu keinem Konflikt kommen.
  • Einfach zu cachen. Wenn der Output für einen Input immer gleich ist, dann können wir uns den Output merken. Er kann sich nicht verändern. (Memoization ist hier das Stichwort.)

Alles wird schwieriger, wenn wir state haben.

Vor ein paar Tagen habe ich mich mit Code beschäftigt, der unnötig viel State transportiert hat. Ich war auf der Suche nach einem Bug.

Dieser Code hat sich einen Zustand, der aus der Datenbank kommt, an mehreren Stellen erneut gemerkt. Es war nur ein Boolean. Aber über mehrere Klassen hinweg wurde diese Information dupliziert.

Das Resultat war sehr unübersichtlicher Code. Ich konnte schnell lokalisieren an welcher Stelle genau der Bug auftritt. Aber herauszufinden wieso er dort auftritt hat mich viel Zeit gekostet. Ich musste genau tracken wann der state manipuliert wird. Irgendwo musste es vergessen worden sein.

Dabei wäre das alles nicht nötig. Der State war nur in der Datenbank nötig. Es hätte ausgereicht ihn am äußeren Layer - der Datenbankschicht - zu halten. Und dann wird er als Parameter immer tiefer in die dahinter liegenden Layer gereicht.

State is the root of all evil

Sobald state im Spiel ist wird alles schwieriger.

Deswegen musst du state so lange vermeiden wie es möglich ist. Das erfordert am Anfang von dir eine andere Denke - aber es wird dir schnell leicht fallen.

Rule the Backend,

~ Marcus

Top