Transkript: Programming as Theory Building and the Not Invented Here Syndrome (deutsch)

Dies ist ein Transkript meines Vortrags „Programming as Theory Building and the Not Invented Here Syndrome“, den ich auf den InfoDays: Softwarearchitektur 2025 gehalten habe (leicht bearbeitet).

(English translation here.)

Intro

Hallo, willkommen zu meinem Vortrag „Programming as Theory Building and the Not Invented Here Syndrome“! Mein Name ist Sebastian Hans. Ich bin seit 20 Jahren in der Software-Entwicklung tätig, den allergrößten Teil davon als Software-Architekt und Entwickler in Entwicklungsteams, und das ist auch das Setting für die Ideen, die ihr gleich von mir hören werdet.

Aktuell bin ich als Senior Technical Consultant bei der bbv und begleite Software- und Digitalisierungsprojekte bei Kunden. Wenn man sowas länger macht, dann sieht man Sachen, die gut laufen, und Sachen, die holpern, manchmal in der Technik, oft aber auch bei den Menschen. Und mit denen beschäftigen wir uns eben genau in diesem Vortrag „Programming as Theory Building and the Not Invented Here Syndrome“. Dazu werde ich zuerst kurz das Essay „Programming as Theory Building“ vorstellen, dann das Not Invented Here Syndrome und dann werde ich die Zusammenhänge untersuchen und Situationen aufzeigen, in denen die in der Praxis von Entwicklungsteams eine Rolle spielen.

Programming as Theory Building

Programming as Theory Building ist ein Essay von Peter Naur, das mittlerweile 40 Jahre alt ist, aber inhaltlich immer noch genauso gültig wie in den 80ern. Ich kann jedem nur empfehlen, es bei Gelegenheit selbst zu lesen, da steckt eine ganze Menge Weisheit drin. Für unsere Zwecke hier reicht es, die Kernthese zu kennen. Die lautet nämlich, dass ein Programm nicht aus seinem Source-Code besteht, sondern aus einer Theorie. Und programmieren besteht nicht darin, dass man Sachverhalte aus der echten Welt in Source-Code übersetzt, sondern darin, dass man diese Theorie aufbaut. Die Theorie – und damit das Programm – lebt in den Köpfen der Entwickler.

(Kleine Randnotiz: Ich werde im Folgenden immer von „Programmen“ reden, weil Naurs Essay diesen Begriff verwendet. Das gilt aber immer auch für Systeme und Systemverbunde – nur, damit das klar ist.)

Um ein Programm in diesem Sinne wirklich zu verstehen, reicht es also nicht, den Quellcode zu lesen, und auch nicht, die Dokumentation anzuschauen, sondern man muss irgendwie an diese Theorie kommen.

Der Begriff der Theorie, der da verwendet wird, bezeichnet nicht nur Faktenkenntnis, zum Beispiel, was tut der Code, wo finde ich welche Funktionalität und so weiter, sondern darüberhinaus auch die Fähigkeit, das zu erklären, zu begründen und einen Bezug zur realen Welt herzustellen. Man kann sich das so vorstellen, dass der Code wie der Schatten eines realen Objekts ist. Hier haben wir einen Schatten. Wenn ich mir nur den anschaue, kann ich sagen, das ist ein Kreis. Damit habe ich aber noch keine Theorie, weil ich keine Ahnung habe, was den Schatten erzeugt. Und es kann ganz verschiedene Theorien geben. Es könnte zum Beispiel eine Kugel sein. Oder ein Zylinder. Oder ein Kegel oder ein Osterei. Wenn ich die Theorie kenne, dann kann ich erklären, warum der Schatten kreisförmig ist. Nehmen wir mal den Zylinder als Theorie, dann liegt es daran, dass er entlang seiner Achse beleuchtet wird. Und wenn jemand daherkommt und sagt: „Pass auf, unsere Anforderungen haben sich um 90° gedreht, sorg dafür, dass der Schatten dazu passt!“, dann frage ich nur, um welche Achse, und wenn es die vertikale Achse ist, dann sage ich: „OK“, und – zack – bin ich fertig. Jemand, der die Theorie nicht kennt und nur den Kreis sieht, der kann nicht wissen, was zu tun ist – und er kann das Wissen auch nicht irgendwie aus dem Kreis rekonstruieren. Das geht einfach nicht.

Ob diese Theorie vorhanden ist oder nicht, merkt man also vor allem, wenn Änderungen oder Erweiterungen gebraucht werden. Es gibt meistens viele Möglichkeiten, eine Anforderung irgendwie reinzupfriemeln, aber oft nur wenige, die zur Theorie passen. Wählt man eine davon, ist es relativ einfach und das Ergebnis ist auch weiterhin gut änderbar und wartbar. Wenn man es anders macht, erzeugt man einen unwartbaren Haufen Code, der, wenn man Glück hat, funktioniert.

Ein Beispiel

Ein Beispiel aus meiner eigenen Praxis: Ich war ein paar Jahre lang in einem Team, das eine Zahlungskomponente verantwortet hat. Diese Komponente hat eine einheitliche Schnittstelle bereitgestellt, über die Apps Zahlungen von Endkunden abwickeln konnten, und sie hatte hintendran unterschiedliche Zahlungsdienstleister für unterschiedliche Zahlungsmittel angebunden. Die Zahlungskomponente hat eine Ports-and-Adapters-Architektur, das heißt, kurz gesagt, sie unterscheidet zwischen der Domänenlogik und technischen Anbindungen an Umsysteme; die stecken in den Adaptern drin.

Im Laufe der Zeit ist ein neuer Kollege ins Team gekommen und hat die Aufgabe bekommen, einen neuen, zusätzlichen Zahlungsablauf zu implementieren, und er hat dazu Erweiterungen in der Domäne und in dem Adapter für den betroffenen Zahlungsdienstleister vorgenommen. Nun muss ich dazusagen, dass die Aufteilung zwischen generischer Domänenlogik und Spezifika für den Zahlungsdienstleister, die in den Adapter gehören, hier aus verschiedenen Gründen nicht so ganz eindeutig ist. Die Ports-and-Adapters-Architektur ist natürlich dokumentiert, aber das hilft einem nicht bei der Entscheidung, was man genau in welches Kasterl reinsteckt. Das ist Teil der Theorie, die in den Köpfen der Entwickler lebt und die man nicht direkt irgendwo anders herauslesen kann. Langer Rede, kurzer Sinn, der neue Kollege hat das Feature natürlich nicht so geschnitten, wie es gedacht war. Er hat zu viele Adapter-Spezifika in den Domänencode gezogen, sodass es da zu komplex geworden ist, und wir haben dann gemeinsam nochmal einiges umgebaut, um nachfolgende Änderungen zu vereinfachen. Damit haben wir zweierlei erreicht. Einerseits haben wir die Änderungen mit der Theorie der Zahlungskomponente in Einklang gebracht und damit ganz praktisch die Wartbarkeit der Software verbessert. Und andererseits hat der Kollege ein weiteres Stück der Theorie in seinen Kopf gebracht und kann so die Entwicklung im Rahmen der Theorie beser weitertreiben.

Also nochmal: Die Kernthese von Programming as Theory Building ist, dass ein Programm mehr ist als der Quellcode plus Dokumentation. Das Programm ist vielmehr die dahinterstehende Theorie und die lebt in den Köpfen der Entwickler. Quellcode und Dokumentation sind im besten Fall ein kleiner Ausschnitt davon.

So weit zu „Programming as Theory Building“. Kommen wir zu dem anderen Konzept, dem Not Invented Here Syndrome.

Das Not Invented Here Syndrome

Not Invented Here bezeichnet die Tendenz, Dinge abzulehnen, die man nicht selbst entdeckt oder erfunden hat. Im Kontext von Software-Entwicklung können das Werkzeuge sein, Prozesse, Programmierparadigmen oder eben auch eine Theorie, die hinter einem Programm steckt. Das ist kein formal definierter Begriff sondern eher eine Beobachtung aus der Praxis, aber es gibt Untersuchungen, die belegen, dass der Effekt real ist. Zum Beispiel eine Studie aus dem Jahr 2014. In der haben Wissenschaftler untersucht, wie Organisationen Crowdsourcing betreiben, also die „Crowd“ – irgendwelche externen Personen, Kunden, Webseitenbesucher usw. – nach Verbesserungsvorschlägen fragen, und insbesondere, wie sie die dann auswerten und umsetzen. Dabei haben sie verschiedene Arten von Distanz gemessen und zum Beispiel festgestellt, dass Vorschläge, die inhaltlich näher an dem dran waren, was die Organisationen sowieso schon gemacht haben, mehr Aufmerksamkeit bekommen haben als wirklich neue Vorschläge, die irgendwo aus der Crowd kamen, die also Not Invented Here waren. Was Not Invented Here ist, interessiert Organisationen anscheinend nicht so sehr.

Das habe ich auch selbst schon erlebt. An die Zahlungskomponente, die ich schon erwähnt habe, war auch SAP als Client angeschlossen. Aber natürlich nicht so wie alle anderen Systeme. Als diese Anbindung angebahnt wurde, haben sich die Verantwortlichen für die Zahlungskomponente und das fragliche SAP-System in die Wolle gekriegt, weil die SAP-Leute gesagt haben, der Ablauf, wie ihn sich das Zahlungskomponententeam vorstellt und die anderen Clients ihn auch realisiert haben, würde mit SAP nicht funktionieren, der widerspräche der SAP-Logik. Not Invented Here. Das können wir nicht und wollen wir nicht.

Weil diese Not Invented Here-Reaktion meistens negativ ist, hat sie einen ein bisschen schlechten Ruf. Man sagt auch: „Not Invented Here Syndrome“, und ein Syndrom ist grundsätzlich was Schlechtes. Aber die Not Invented Here-Reaktion, wie ich sie jetzt mal neutral nennen will, muss nicht unbedingt schlecht sein. Eine kleine Dosis Not Invented Here ist gut und sogar notwendig, ganz besonders, wenn man Programming as Theory Building ernst nimmt.

Not Invented Here als Sensor

Um das zu verstehen, möchte ich die Idee der Distanz nochmal aufgreifen, die in der Studie angewandt wurde. Ganz nah dran ist fast Invented Here, weit weg ist definitiv Not Invented Here. Für den Zweck dieses Vortrags schaue ich mir mal die Distanz einer Idee oder eines Konzepts zur Theorie des Programms an. Ich nenne sie hier „konzeptionelle Distanz“. Dabei ist die Distanz 0, wenn sich eine Idee innerhalb der Theorie bewegt. Und wenn ein Konzept richtig quer liegt, sodass es überhaupt nicht zur Theorie passt, dann sage ich, die beiden haben eine hohe konzeptionelle Distanz und die Idee wäre aus Sicht der Theorie des Programms Not Invented Here.

Wenn man sich dann ein Programm vorstellt – im Sinne von Theorie + Code – und eine Idee für eine Änderung, dann wäre es doch gut, wenn die Idee eine möglichst geringe konzeptionelle Distanz zur Theorie hätte. Denn dann wäre sie normalerweise leicht durchzuführen, relativ risikoarm und würde das Programm in einem guten, wartbaren Zustand hinterlassen, wohingegen eine Änderung, die weit weg von der Theorie wäre, eher schwierig umzusetzen wäre und fehleranfällig und eventuell die konzeptionelle Integrität des Programms zerstören und es somit unwartbar machen würde. So gesehen, ist es völlig rational, Ideen, die konzeptuell weit weg von der Theorie des Programms sind, kritischer zu betrachten als welche, die näher dran sind – also genau „Not Invented Here“ zu betreiben. Aus Sicht des Entwicklungsteams ist Not Invented Here quasi ein Schutzschild für die konzeptionelle Integrität unserer Theorie. Oder ein Sensor, der mir sagt: „Obacht, hier haben wir was, das nicht zu unserer Theorie passt.“

Heißt das, Not Invented Here ist uneingeschränkt gut und wir sollten Ideen, die Not Invented Here sind, grundsätzlich ablehnen? Natürlich nicht. Pauschalaussagen sind immer falsch. Zum einen gibt es viele unterschiedliche Arten von Distanz, bei denen man „Not Invented Here“ rufen kann, z. B. auch solche, die auf Gruppenzugehörigkeit beruhen. Sowas ist meistens schlecht. Das meine ich hier nicht. Ich meine ausschließlich die konzeptionelle Distanz.

Und es gibt noch einen anderen Grund, warum ich Dinge, die Not Invented Here sind, nicht pauschal ablehnen sollte: Die Theorie des Programms muss ja nicht perfekt sein. Manchmal lernt das Team was dazu und entwickelt die Theorie weiter. Das kann eigentlich nur passieren, indem man Ideen, die außerhalb der Theorie liegen, integriert.

Umgang mit neuen Ideen

Was mache ich also, wenn ich Entwickler in einem eingespielten Entwicklungsteam bin und jemand kommt mit einer Idee daher oder macht etwas auf eine Art und Weise, die meinen Not Invented Here-Sensor triggert? Zuerst check ich kurz, ob er aus einem guten Grund getriggert hat. Ist es die konzeptionelle Distanz zur Theorie? Wenn nicht, dann ist es vielleicht ein Fehlalarm und ich sollte den mal stummschalten und mir die Idee einfach weiter anhören. Wenn ich aber feststelle, dass das, was ich da höre oder sehe, wirklich weit weg von der Theorie meines Programms ist, dann kann ich mich freuen, denn dann hat der Sensor funktioniert. Er hat verhindert, dass wir blind etwas in unser Programm einbauen, das später Probleme verursachen wird.

Das Einfachste ist dann zu sagen: „Nein, das machen wir nicht.“ Das spart Zeit und Geld und hält das Programm schön klein. Aber das kann und will man natürlich nicht immer machen, denn hinter vielen Ideen steckt ja eine gute Absicht. Dann besteht die Aufgabe darin, die Distanz zur Theorie möglichst zu verringern. Gibt es eine Möglichkeit, das, was man mit der Idee eigentlich erreichen wollte, im bestehenden Rahmen der Theorie abzubilden? Das ist der beste Fall, dann sollte man das eben so tun. Wir erinnern uns an den neuen Kollegen bei der Zahlungskomponente. Der wollte ein Feature bauen und hat es auf eine Art und Weise versucht, die nicht zur Theorie gepasst hat, und das Team hat es dann gemeinsam so umgemodelt, dass es im bestehenden Rahmen gut funktioniert.

Wenn wir es nicht schaffen, die Idee konzeptionell an die Theorie ranzubringen, und wir sie trotzdem umsetzen wollen, dann geht das auch, aber es wird mehr Arbeit. Dann müssen wir nämlich die Theorie an die Idee anpassen. Und das heißt, nicht nur neuen Code schreiben, denn die Theorie ist ja mehr als nur Code. Wir müssen das ganze Team mitnehmen, uns gemeinsam ein neues, konsistentes mentales Modell überlegen, das die bisherige Theorie und die neue Idee in Einklang bringt, und das dann umsetzen. Dabei ist die Hauptaufgabe, dieses gemeinsame Verständnis von der neuen Theorie herzustellen. Dann den passenden Code zu schreiben, ist meistens deutlich leichter.

Noch ein Beispiel

Dazu habe ich auch ein Beispiel, und zwar aus derselben Zahlungskomponente. Da mussten wir einmal einen Zahlungsdienstleister austauschen. Der Vertrag mit dem alten ist ausgelaufen, im Rahmen einer Ausschreibung wurde ein neuer gefunden und der musste angebunden werden, und zwar ohne Downtime. Es gab schon eine Möglichkeit, die Zahlungsdienstleister pro angebundener App zu konfigurieren, um die Zahlungen für eine App an den jeweils passenden Adapter zu schicken. Das heißt, der Theorie des Programms folgend, hätten wir zum Migrationszeitpunkt die Apps konfigurativ umstellen können und wären fertig gewesen. Da es aber um viele Kunden und um viel Geld ging und solche Big-Bang-Migrationen ziemlich risikobehaftet sind, hatte ich die Idee, die Umstellung doch lieber pro Kunde vorzunehmen. So ließe sie sich viel feingranularer steuern und wir könnten das Risiko deutlich senken.

Die konzeptionelle Distanz zur bestehenden Theorie war da allerdings schon relativ groß und obwohl die Idee von mir, also aus dem Team selbst heraus kam, haben wir uns genau überlegt, ob wir das so einführen wollen und wie wir dieses Konzept der Migration pro User mit dem verheiraten, was schon da war. Letztlich haben wir uns gemeinsam dafür entschieden, diese Konfiguration pro App komplett auszubauen, die Migration pro User zu implementieren und die nach der Migration zusammen mit dem alten Zahlungsdienstleister auch wieder auszubauen. Letzteres mag überraschen, aber das hatte mit der neuen Theorie zu tun, die wir zum Thema Routing von Zahlungen an Zahlungsdienstleister gebildet hatten.

Alte Theorie:

Das Routing ist eigentlich keine richtige Logik. Da reicht es, wenn man irgendwo eine Tabelle hat, und man kann das Routing praktisch beliebig zur Laufzeit ändern.

Neue Theorie:

Das Routing ist eine Kernfunktion der Zahlungskomponente und wenn man das ändert, ist das ein nicht-triviales Vorhaben, das wahrscheinlich mit Custom-Logik und Edge-Cases verbunden ist, die man am besten mit Code abbilden kann.

Hätten wir uns nicht die Zeit genommen, die Theorie anzupassen, sondern die Migration pro User einfach zusätzlich reingefrickelt … das will ich mir gar nicht vorstellen, was dabei rausgekommen wäre. Bestimmt nichts, was sich leicht weiterentwickeln ließe.

Umgang mit bestehenden Theorien

Betrachten wir das Ganze doch mal aus einer anderen Perspektive, nämlich aus der Sicht desjenigen, der mit einer Theorie von jemand anderem umgehen will oder muss. Das kann zum Beispiel ein Stück Software sein, die jemand anders entwickelt hat und an der es jetzt etwas zu ändern gibt. Und nehmen wir auch mal an, dass die konzeptionelle Distanz zu dem, was ich sonst so gewohnt bin, mittel bis hoch ist. Dann werde ich anfangs Schwierigkeiten haben, die Theorie dahinter zu verstehen. Ich kann dann die Änderung an der Software nicht so durchführen, dass ich mir sicher sein kann, dass das Ergebnis gut ist. Die Theorie ist zu weit weg. In anderen Worten, mein Not Invented Here-Sensor löst aus. Das heißt aber nicht, dass ich in die Not Invented Here-Abwehrhaltung verfallen sollte. Denn die Konsequenz aus der Theory-Building-These ist ja: Wenn ich keine halbgare Frickellösung haben will, dann muss ich mir zuerst die Theorie des Programms beschaffen. Die muss in meinen Kopf rein. Wie das geht, hängt von der Situation ab.

Onboarding in ein aktives Entwicklungsteam

Eine Möglichkeit ist: Ich komme in ein eingespieltes Entwicklungsteam. Dann kann ich davon ausgehen, dass die Leute eine Theorie in ihren Köpfen haben, die ich aber noch nicht kenne. Ich sehe erst mal nur den Source-Code. Dann heißt es als erstes: Die Abwehrhaltung abschalten! Das Unproduktivste, was ich machen kann, ist, bei jeder Gelegenheit zu sagen: „Das ist aber komisch. Wie kann man nur auf so eine Idee kommen? Ich hätte das ganz anders gemacht.“ Und so weiter. Das hindert mich nur daran, meine Hauptaufgabe zu erledigen, die da wäre, möglichst schnell die Theorie des Programms zu verinnerlichen. Dabei hilft:

Ach ja, und mit dem Team reden.

Ich hatte das erst vor kurzem bei einem Service, der mit historisierten Daten hantiert. Da können sich Attribute von manchen Entitäten über die Zeit hinweg ändern und sie werden mit „von“ und „bis“ gespeichert. Andere nicht. Und auch Beziehungen zwischen Entitäten sind teilweise historisiert, teilweise nicht. Ich kann im Code sehen, dass das passiert, und es steht auch ein bisschen was darüber im internen Wiki, aber richtig verstanden, warum das so ist, wie es ist, habe ich erst im Gespräch mit dem Team. Ich hätte auch gleich sagen können: „Das ist doch alles viel zu kompliziert, ich hätte das ganz anders gebaut.“ Not Invented Here. Aber das hätte mir nicht dabei geholfen, das Thema zu verstehen.

Also wenn ich irgendwo neu reinkomme: Die ablehnende Not Invented Here-Reaktion abschalten und möglichst schnell die Theorie aufsaugen.

Umgang mit Legacy-Software

Eine andere Situation wäre: Ich übernehme Verantwortung für ein bestehendes System, bei dem niemand mehr verfügbar ist, dem ich Fragen stellen kann. Das kann unterschiedliche Gründe haben. Vielleicht ist es ein altes System, an dem lange nichts mehr zu tun war, und die Leute mit Ahnung sind inzwischen weitergezogen. Und jetzt ist wieder etwas zu tun und ich habe das große Los gezogen. Aber vielleicht ist auch ein Team da, aber es sind nicht mehr die ursprünglichen Entwickler sondern welche, die später dazugekommen sind und die Theorie selbst nicht verinnerlicht haben. Ich habe das schon erlebt – vielleicht ihr auch – dass ich in ein Team gekommen bin, das das eigene System nicht kennt – oder nur Teile davon. Dann wird es schwierig, dann muss man die Theorie rekonstruieren. Das ist Arbeit.

Und auch bei dieser Arbeit kann wieder mein Not Invented Here-Sensor bzw. die Idee der konzeptionellen Distanz hilfreich sein. Die sagt mir nämlich, womit ich mich noch beschäftigen muss. Ich habe ja schon, wenn ich anfange, eine gewisse Vorstellung davon, wie die Theorie aussehen könnte, und wenn es nur meine Intuition ist, die auf meiner Erfahrung mit anderen Programmen beruht. Wenn ich mir dann das Material anschaue, das da ist – Code, Bildchen, Doku, whatever – dann gibt es Dinge, da denke ich mir: „Ja, OK, klar.“ Und es gibt Dinge, da löst mein Entfernungssensor aus – also der für die konzeptionelle Distanz. Da denke ich mir dann: „Hui, das passt gar nicht zu dem, was ich mir bisher zusammengereimt habe!“ Manche Entwickler verfallen dann in die Not Invented Here-Abwehrhaltung und grummeln über den Legacy-Scheiß, mit dem sie sich rumschlagen müssen. Ich nehme das als Signal, genauer hinzuschauen, denn das ist eine Stelle, an der meine Theorie offensichtlich noch falsch oder zumindest unvollständig ist. Also grabe ich mich da rein und versuche, genau die Stelle zu verstehen und die ursprüngliche Theorie noch ein Stück weiter zu rekonstruieren.

Das geht bis zu einem gewissen Punkt. Aber meistens nicht vollständig. Wenn man an dem Punkt angelangt ist, dann kann – und sollte – man anfangen, die Theorie zugunsten der aktiven Entwickler umzubauen, um aus diesem „ich habe keine Ahnung, was ich da tue“-Modus rauszukommen. Dann hat man wieder eine lebende Theorie, die tatsächlich in den Köpfen der Entwickler drinsteckt, und kann damit weiterarbeiten.

Ein Beispiel dafür ist ein Entwickler-Team, das eine Java-Library geerbt hat, die aus fünf Schichten aufgebaut ist. Niemand kannte den Sinn dieser Schichten und da gab es genau diese Not Invented Here-Reaktion von einigen Entwicklern und sie wollten das Ding am liebsten gar nicht anfassen. Als ich dazugekommen bin, haben wir uns angeschaut, welche Probleme wir tatsächlich haben und wo uns Schichten helfen und wo eher nicht, und wir haben jetzt angefangen, den Code gemäß unserer neuen Theorie zu ändern.

Reprise

Ihr seht also, es gibt einen Zusammenhang zwischen der Idee des Programming as Theory Building von Peter Naur und Not Invented Here. Nochmal kurz zusammengefasst, sagt Programming as Theory Building, dass die Essenz des Programmierens nicht das Schreiben von Code ist, sondern das Aufbauen einer Theorie. Diese Theorie lebt in den Köpfen der Entwickler und ist das eigentliche Programm. Der Code gehört auch dazu, aber der sorgt nur dafür, dass das Programm auf einer Maschine ausführbar wird. Änderungen am Code lassen sich im Einklang mit der Theorie viel leichter durchführen und führen zu besseren Ergebnissen als Änderungen, die ohne Rücksicht auf die Theorie vorgenommen werden, weil das Programm eben hauptsächlich aus der Theorie besteht.

Not Invented Here ist eine Reaktion auf Ideen, die von weit weg kommen, wobei die Entfernung in unterschiedlichen Dimensionen liegen kann. Oft ist diese Reaktion ablehnend und kontraproduktiv, aber das muss nicht so sein.

Eine für die Entwicklung besonders wichtige Dimension ist die konzeptionelle Distanz. Wie weit liegen zwei Konzepte oder Ideen oder Theorien auseinander? Laut der Theory-Building-These sind Programmänderungen mit einer hohen konzeptionellen Distanz zur Theorie genau die problematischen. Und deswegen kann die Not Invented Here-Reaktion nützlich sein, weil sie mich auf so etwas hinweist.

Wenn ich gelernt habe, die automatische Abwehrhaltung loszuwerden, die oft damit verbunden ist, und sie stattdessen als Signal zu betrachten, dann bin ich frei, mir zu überlegen, ob und wie ich die konzeptionelle Distanz verringern will. Vielleicht will ich das gar nicht und sage tatsächlich: „Nein, das mach ich nicht!“ Aber wenn ich es machen will, gibt es im Wesentlichen drei Möglichkeiten: Ich kann die eine Seite anpassen oder die andere oder ich tue beides und lande irgendwo in der Mitte.

Wir haben uns ein paar Situationen dazu angeschaut: Beim Onboarding eines neuen Entwicklers sind die beiden Konzepte die Theorie des Programms und die vorgefertigten Ideen und Vorstellungen im Kopf des Entwicklers. Da möchte ich in der Regel, dass der Entwickler zuerst mal die Theorie des Programms versteht und später seine eigenen Erfahrungen einfließen lässt, um die Theorie zu verbessern.

Bei Änderungsvorschlägen kann zweierlei passieren. Entweder man schafft es, die Anforderungen im Rahmen der Theorie des Programms umzusetzen – das ist der beste Fall –, oder man muss tatsächlich die Theorie des Programms anpassen, um die Lösungsidee zu integrieren. Aber dann auch wirklich die Theorie, nicht nur punktuell den Code!

Und wenn man ein Legacy-System übernimmt, bei dem die Theorie nicht mehr greifbar ist, wird man oft die Situation haben, dass man sie nicht ganz rekonstruieren kann. Man sollte es aber versuchen und dann die verbleibenden Teile an die eigenen Vorstellungen anpassen und eine neue Theorie bilden, damit man vernünftig damit arbeiten kann.

Wenn ihr also das nächste Mal auf eine Not Invented Here-Reaktion stoßt, bei euch selbst oder bei anderen, dann überlegt euch mal, was dahintersteckt und ob das nicht ein Signal sein könnte, euch tiefer mit dem Thema zu beschäftigen!

Danke schön und Happy Programming! Oder Theory-Building!