Erfolgreiches Arbeiten im Brownfield – Teil 1

Brownfield-Entwicklung: Vom Chaos zur Kontrolle

Brownfield-Entwicklung: Vom Chaos zur Kontrolle

Erfolgreiches Arbeiten im Brownfield – Teil 1

Brownfield-Entwicklung: Vom Chaos zur Kontrolle


Wie oft haben wir es schon gehört: „Das System ist hysterisch gewachsen … Aber wenn wir jetzt von Grund auf neu entwickeln, wird alles besser!“ Aber seien wir ehrlich: Genau das haben sich auch die ursprünglichen Entwickler gedacht und nach bestem Wissen und Gewissen gearbeitet. Die Realität ist einfach: Die meiste Entwicklungszeit verbringen wir im Brownfield. Daher brauchen wir gute Werkzeuge und Methoden, um Brownfield-Projekte erschließen und sicher darin navigieren zu können.

Es löst selten Begeisterung aus, wenn ein Team eine bereits bestehende Software zur Wartung oder Weiterentwicklung übernehmen soll. Beim Brownfield haben wir eine bereits bestehende breite Codebase; bei Legacy-Code kommt i. d. R. der deutlich fortgeschrittene Zeitfaktor hinzu, da diese Systeme schon seit mehreren Jahren oder gar Jahrzehnten in Produktion sind. Dort wirken sich verstärkt Themen aus wie fehlendes Fachpersonal und veraltete Plattformen, die oftmals mit obsoleten oder gar abgekündigten Bibliotheken und Frameworks glänzen. Da hält sich die Euphorie in Grenzen.

Summa summarum: Es gibt verschiedene Defizite, wie zum Beispiel die Dokumentation, die Testabdeckung und die Codequalität, die Entwickler erst einmal abschrecken. Dabei selten bedachte Aspekte sind neben der intrinsischen Komplexität der Fachlichkeit Entwurfsmuster und Programmierstile, die aus der Mode gekommen sind und zu denen der Zugang fehlt. Nicht selten nimmt bei uns Entwicklern auch das verbreitete NIH-Syndrom (not invented here) Einfluss, das zu einer ablehnenden Haltung führen kann. Es ist ratsam, ein offenes Mindset zu fördern und die Übernahme der Codebasis möglichst emotionslos anzugehen. Damit soll verhindert werden, dass ein Projekt schon während der Übernahme abgeschrieben wird. Ein großes Problem ist außerdem, dass der Zugang zur Software oftmals nicht systematisch stattfindet, was zu unnötigen Reibungsverlusten, Vorurteilen und teuren Fehlinterpretationen führen kann.

Brownfield- und Legacy-Entwicklung

Brownfield-Entwicklung unterscheidet sich im Vergleich zur Entwicklung von Legacy-Software in der Lebensphase, in der gearbeitet wird. Geht es um ein Brownfield, bedeutet das Erweiterungen und Änderungen am Code. Entwicklung von Legacy-Software heißt meistens, dass es um Stabilisierung und Aktualisierung der Plattform geht. Die Übergänge zwischen den beiden lassen sich allerdings am besten mit Heraklith beschreiben: Panta rhei („alles fließt“). Wenn beispielsweise ein Teil einer Legacy-Software rückgebaut werden muss, weil die Funktionalität ausgelagert wurde (z. B. mit dem Strangler-Fig-Pattern), dann sind wir ‒ wenn auch weiter unten in der Grasnarbe – wieder im Brownfield. Wir unterscheiden für uns zwischen Greenfield- und Brownfield-Projekten sowie Legacy-Systemen:

  • Greenfield-Projekte: befinden sich in einem wenig fortgeschrittenen Stadium der Entwicklung. Die Software läuft noch nicht – oder noch nicht lange – produktiv und es gab bisher nur eine überschaubare Fluktuation im Team.

  • Brownfield-Projekte: kombinieren die Herausforderung, bestehende Systeme zu integrieren oder zu modernisieren, mit der Notwendigkeit, technische Schulden abzubauen.

  • Legacy-Systeme: erfordern eine andere Art der Wartung, bei der Stabilität und Fehlerbehebung im Vordergrund stehen.

dueppe_noerder_brownfield_1_1

Abb. 1: Fließende Übergänge von Greenfield zu Legacy

Entwicklungs- vs. Entwurfsmuster

Oftmals befinden sich im Code einer bestehenden Anwendung Systematiken, die keinen gängigen Entwurfsmustern (GOF), Architekturmustern (EAP) oder Enterprise Integration Patterns (EIP) entsprechen. Diese Muster nennen wir Entwicklungsmuster. Dabei handelt es sich um eine Systematisierung im Source Code, nach der entwickelt wurde. Da bekanntermaßen viele Wege nach Rom führen, ist es theoretisch möglich, jeden Kernanwendungsfall einer Software anders zu entwickeln. Das passiert zum Glück eher selten. Wir Entwickler neigen dazu, Muster und Vorgehensweisen zu vereinheitlichen. Erkennen kann man die Muster an der Struktur des Codes.

Der Langlebigkeit eines Legacy-Systems ist es dann allerdings geschuldet, dass auf Codeebene verstärkt Variationen in der Umsetzung zu finden sind. Ursachen hierfür sind meist Wechsel im Team oder neue Vorlieben der Entwickler.

Ein Beispiel dafür: Um eine weitere Domain in die Anwendung einzubauen, wird ein Package strukturgleich zu den anderen Domains angelegt, mit denselben Unter-Packages und demselben Zweck. Das entspricht zwar keinem GOF, EIP oder EAP, ist aber eine erkennbare Systematisierung. Meist werden solche Strukturen noch durch Interfaces und Klassenhierarchien gestützt; wenn man also einmal den abstrakten Teil verstanden hat, ist die Erweiterung oder Änderung am Code schon bedeutend einfacher. Es empfiehlt sich daher, bestehende Entwicklungsmuster zu analysieren. Die klare Empfehlung lautet, diese Entwicklungs- und Entwurfsmuster zu abstrahieren und zu katalogisieren – und vor allem bestehende Muster weiter zu nutzen oder ganzheitlich zu migrieren.

Unsere These ist, dass durch eine systematische Einarbeitung der Aufwand zur Übernahme einer bestehenden Software massiv reduziert werden kann. Das erfordert aber ein vom Team getragenes Prozedere, das wiederum ein hohes Maß an Disziplin im Team fordert. Wir nennen diesen Prozess Anamnese. Eine Anamnese ist eine Kartografierung der bestehenden Software und die Lokalisierung von Hotspots sowie die damit verbundenen Maßnahmen zur systematischen Einarbeitung. Anamnese bedeutet nicht, ganzheitlich die gesamte Software zu analysieren. Wer zum Arzt geht, wird ja auch entlang klarer Vorgaben sukzessive untersucht und nicht beim ersten Termin komplett durchleuchtet. Ähnlich verhält es sich hier.

Strategy Assessment, oder: Was soll überhaupt erreicht werden?

Zunächst einmal muss man das strategische Ziel festlegen. Das ist notwendig, um auf der richtigen Ebene anzusetzen. Wir unterscheiden hierbei im Wesentlichen zwischen:

  • Maintenance, bei der wenige bis keine Änderungen mehr am Quellcode gemacht werden müssen. Wenn es Änderungen gibt, finden diese auf technischer Ebene statt.

  • Migration, bei der das fertige System auf einen neuen Stand gebracht und ggf. die Fachlichkeit angepasst wird.

  • Neubau, bei dem die Software für den Kunden von Grund auf neu entwickelt wird.

Man beachte, dass das keine absolute Einteilung ist, sondern fließende Übergänge impliziert. Die Entscheidung, welche der drei Optionen gewählt wird, kann zu Beginn oft noch nicht definiert werden, sondern wird im Laufe der Anamnese ermittelt.

dueppe_noerder_brownfield_1_2

Abb. 2: Methoden zur Modernisierung von Brownfield- und Legacy-Software

Einarbeitung in die Brownfield-Software

Brownfield-Software kommt in den unterschiedlichsten Gestalten und mit (teilweise abenteuerlicher) Dokumentation daher, was die Einarbeitung beeinflussen kann. Eine unstrukturierte Vorgehensweise führt dabei in den meisten Fällen zu Problemen. Beispielsweise wird die Aktualisierung eines in Produktion befindlichen Systems häufig gescheut („läuft ja“, wenn es um die Kosten geht, oder „never touch a running system“, wenn das Risiko im Vordergrund steht).

Nicht selten wird der Einstieg in die Software über aktuelle Tickets gesucht, was in der Regel zu einem bruchstückhaften Architekturwissen führt. Änderungen und/oder Erweiterungen werden dann nicht entlang der Architektur vorgenommen, sondern beulenhaft an das Produkt angeklebt und eingeflickt. Es entsteht eine sogenannte Duct Tape Architecture. Eine systematische Einarbeitung hilft, diesen Overhead zu reduzieren.

Proaktiv vs. reaktiv

Bei der Anamnese steht das gesunde Verhältnis von investiertem Zeitaufwand zu erlerntem Detailwissen im Fokus. Das Durchleuchten einer Software dient zunächst der Kartografierung von Komponenten...