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.
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.