Im zweiten Projekt

Im ersten Projekt baut man einfach eine Lösung.

Im zweiten merkt man:

„Das hatten wir doch schon mal.“

Also abstrahiert man.

Nicht aus Prinzip.
Sondern weil es sich anbietet.

Der erste Versuch

Man zieht das Gemeinsame raus.

Ein Interface.
Eine kleine Library.
Ein bisschen Struktur.

Das fühlt sich erstmal großartig an.

Zum ersten Mal wirkt das Problem „gelöst“.

Keine Copy-Paste-Bauchschmerzen mehr.
Weniger Chaos.
Weniger „naja, fast gleich“.

Man schaut auf die Abstraktion und denkt:

„Jetzt haben wir’s sauber.“

Das ist meistens der Punkt,
an dem es interessant wird.

Illustration einer Person, die ein Modellauto mit abstrahierten, austauschbaren Rädern auf einer Werkbank montiert, umgeben von Werkzeugen und technischen Skizzen.

Und dann passt es nicht mehr

Im nächsten System kommt der erste Bruch.

Etwas ist anders.

Nicht viel.
Aber genug.

Ein Parameter fehlt.
Ein Ablauf ist leicht verschoben.
Ein Sonderfall passt nicht ins Modell.

Also biegt man die Abstraktion ein bisschen zurecht.

Noch ein Parameter.
Noch ein optionales Verhalten.
Noch kurz ein Flag.

Nichts Dramatisches.

Die Abstraktion funktioniert noch.

Aber langsam wird sie gesprächig.

Noch ein System

Beim nächsten Mal wird es deutlicher.

Plötzlich sind die Unterschiede
keine Sonderfälle mehr.

Sie betreffen das Modell selbst.

Was vorher gleich aussah,
verhält sich plötzlich unterschiedlich.

Und langsam entsteht dieses unangenehme Gefühl:

Vielleicht war das nie wirklich dasselbe Problem.

Das eigentliche Learning

Genau hier passiert etwas Interessantes.

Nicht im ersten System.
Nicht beim ersten Versuch.

Sondern beim zweiten oder dritten.

Man merkt:

  • was nur zufällig gleich war
  • was man zu früh generalisiert hat
  • wo die echten Unterschiede liegen

Und vor allem:

was tatsächlich invariant ist

Das ist der eigentliche Gewinn.

Nicht Wiederverwendung.

Erkenntnis.

Ein kleines Beispiel

Zwei Systeme brauchen „Retries“.

Klingt erstmal identisch.

Also abstrahiert man:

retry(fn, options)

Im ersten System passt das perfekt.

Im zweiten merkt man:

  • nicht jeder Fehler ist retrybar
  • Timing ist unterschiedlich
  • manche Calls dürfen nicht wiederholt werden

Plötzlich geht es nicht mehr um „Retry“.

Sondern um:

  • Fehlertypen
  • Seiteneffekte
  • Zustände
  • Idempotenz

Die Abstraktion bricht nicht.

Sie lebt noch.

Aber langsam verwandelt sie sich
in ein überraschend meinungsstarkes Error-Handling-Framework.

Und genau dabei merkt man:

Das ursprüngliche Problem war nie
„Retry“.

Abstraktion als Werkzeug

Das ist der eigentliche Punkt:

Abstraktion dient nicht nur dazu,
Code wiederzuverwenden.

Sie ist ein Werkzeug,
um ein Problem besser zu verstehen.

Sie zwingt dich:

  • Annahmen explizit zu machen
  • Gleiches von Ähnlichem zu unterscheiden
  • echte Struktur von Zufall zu trennen

Das passiert selten beim ersten Einsatz.

Meistens passiert es erst,
wenn die Abstraktion anfängt weh zu tun.

Warum ein System nicht reicht

Ein einzelnes System täuscht.

Es zeigt dir ein Modell, das funktioniert.

Aber nicht,
ob dieses Modell allgemein ist.

Ein einzelnes Projekt erzeugt schnell das Gefühl:

„So funktioniert das Problem.“

Erst im zweiten Kontext merkt man:

„Nein. So funktioniert unser Problem.“

Das ist ein großer Unterschied.

Zwei Arten von Abstraktion

Es gibt die Version:

„Das müsste doch generalisierbar sein.“

Und es gibt die Version:

„Das ist jetzt schon mehrfach passiert.“

Die erste produziert Abstraktion.

Die zweite Verständnis.

Die eine fühlt sich clever an.

Die andere hält länger als das ursprüngliche System.

Der eigentliche Gewinn

Gute Abstraktion spart nicht zuerst Code.

Sie verändert dein Verständnis.

Und manchmal merkt man erst beim Versuch,
etwas zu abstrahieren,

dass man das Problem
vorher gar nicht verstanden hat.

Wo Abstraktion interessant wird

Die wertvollste Abstraktion
ist nicht die, die überall passt.

Sondern die,
die dir zeigt,
warum zwei Dinge nur ähnlich aussahen.