Als der Auftraggeber mit ein paar 3.5 Zoll Disketten ins Sitzungszimmer trat, staunten wir nicht schlecht. «Unser Novell Server steigt immer öfter aus, wodurch die Produktion lahmgelegt wird. Könnt ihr die Software auf Windows portieren und an SAP anbinden?» – «Und die Firma welche die Software geschrieben hat?» – «Die gibt es nicht mehr.»
Es handelte sich um Steuerungs- und Visualisierungssoftware aus dem Jahr 1996 für ein paar Sondermaschinen geschrieben in Borland C, MS-DOS. Die Maschinen wurden vor sechs Jahren in die Tschechei verlegt. Niemand wusste genau wie sie funktionierten, Dokumentation gab es keine.
Wie groß würden Sie den Aufwand schätzen, um so einen Auftrag zum Erfolg zu bringen?
Mittlere bis große Softwareprojekte sind teuer und sollten daher möglichst lange leben. Auch für Software gilt: Was gut gepflegt wird, lebt länger. Was aber, wenn das Projekt erfolgreich abgeschlossen wird und dessen Quellcode in den Archivschrank verschwindet? Was, wenn nach zehn Jahren ein neues Modul an diese archivierte Software angebunden werden soll? Sind die Entwickler dann noch da? Ist das Domänenwissen von damals noch vorhanden? Kann man das Projekt mit der neuen Entwicklungsumgebung noch kompilieren? Gibt es NuGet [1], NPM [2] oder Yarn [3] in zehn Jahren noch?
Alles Wichtige an einem Ort
Das Domänenwissen in Confluence [4], die Anforderungen in Jira [5], externer Code auf einem NuGet-Server [1], Quellcode in Git [6] und der Buildprozess in der Azure Cloud [7]. So kann ein mittleres bis grosses .NET Projekt heute aussehen. Während der Entwicklungsphase funktioniert das wunderbar. Wenn das Projekt aber abgeschlossen ist, muss man alles für die Wiederbelebung Wichtige an einem Ort ablegen. Häufig dauert es nicht lang, bis eines der Systeme durch ein Neueres abgelöst wird. Auch der Kunde wird an einem funktionierenden Backup interessiert sein, da er keine Garantie hat, dass es seinen Dienstleister in ein paar Jahren noch gibt.
«Alles Wichtige» ist alles, was es braucht um das Projekt in zehn Jahren noch zu verstehen, zu kompilieren, zu deployen und laufen zu lassen. Dies bedingt Massnahmen in folgenden Bereichen:
- Dokumentation
- Beseitigen externer Abhängigkeiten
- Einfrieren der Entwicklungs- und Laufzeitumgebung
- Best Practices für nachhaltige Software
Dokumentation
Wenn ein Wiki nicht nachhaltig genug ist um wichtige Informationen zu speichern, wohin dann mit dem Projekt relevanten Domänenwissen? Eine gute Lösung ist ein technisches Handbuch, das zusammen mit dem Quellcode gepflegt und gespeichert wird. Ein solches Dokument eignet sich ebenfalls, um alle Softwarefunktionen zu beschreiben, da diese in der Regel als Softwareanforderungen innerhalb eines Ticketsystems gefangen sind. Das Handbuch kann man während dem Buildprozess automatisch versionieren und als PDF exportieren. Das PDF kann wiederum als Online-Hilfe im Produkt integriert werden. Dies verlangt vom Entwickler (oder zum Beispiel dem Product Owner), dass dieser nach der Implementation einer neuen Funktion das Handbuch aktualisiert. Ein Eintrag in der Definition of Done der User Stories sorgt dafür, dass nichts vergessen geht.
Software-Kommentare sind ein weiteres Hilfsmittel, um das Projekt zu dokumentieren. Sobald etwas nicht offensichtlich ist oder an einer Stelle spezielles Domänenwissen gefordert wird, sollte der Entwickler dies ausführlich in einem Kommentar beschreiben. Damit ist nicht nur seinem Nachfolger geholfen, sondern auch ihm selbst. Was jetzt kristallklar ist, kann nach einem Jahr schon ein Rätsel sein. Zur Projekt relevanten Dokumentation gehören auch Handbücher von Drittanbietern (API Dokumentation, Peripherie). Auch diese sollen am gleichen Ort wie das Handbuch im Projekt gespeichert werden. Zur Sicherheit exportieren Sie das Wiki und das Ticketsystem als PDF und archivieren es gleich mit.
Beseitigen externer Abhängigkeiten
Extern ausgelagerter Code ist ein Risiko für die Wiederbelebung der archivierten Software. Spätestens in der Abschlussphase sollte der gesamte externe Code lokal im Projekt integriert sein. Wer garantiert Ihnen, dass es die verwendeten Pakete in zehn Jahren noch auf NuGet oder NPM gibt? Gibt es diese Paketmanager dann überhaupt noch?
Ein paar Tipps für die Nachhaltigkeit:
- Verzichten Sie wo immer es geht auf externe Pakete. Ein AutoMapper ist mit zwei einfachen Unit-Tests zum Beispiel überflüssig.
- Integrieren Sie wenn möglich die Funktionalität als Quellcode im Projekt. Nicht mehr weiter entwickelte Bibliotheken können so für neuere Framework-Versionen kompiliert werden.
- Verstecken Sie externe Funktionalität hinter einer Facade; das macht sie einfacher austauschbar.
- Bleiben Sie an der Oberfläche; benutzen Sie nur Basisfunktionalität. So verhindern Sie, dass Sie sich abhängig machen von einem bestimmten Hersteller nur weil sein Produkt diese spezielle Funktionalität anbietet.
- Schalten Sie alle automatischen Updates aus (Dependencies, Entwicklungsumgebung, usw.). So verhindern Sie, dass Sie später in Teufels Küche kommen.
- Vergessen Sie nicht die lokal installierten Bibliotheken oder spezielle DLLs, die sich gern im GAC (Global Assembly Cache) verstecken [8]. Am besten werden die originalen Installer ebenfalls im Projekt abgelegt.
Einfrieren der Entwicklungs- und Laufzeitumgebung
Den Quellcode von heute können Sie mit grosser Wahrscheinlichkeit bereits in fünf Jahren nicht mehr kompilieren ohne das Projekt zuerst mühsam zu konvertieren. Dies ist insbesonders dann ineffizient, wenn nur ein kleiner Fehler schnell behoben werden muss. Erstellen Sie deshalb beim Projektabschluss eine virtuelle Maschine mit der gesamten Entwicklungsumgebung. Übrigens ist die Virtualisierung der Laufzeitumgebung von Servern heute schon gang und gäbe.
Automatisierte Tests
Tests sind wie eine Versicherung: Sie verhindern möglichen Schaden, haben aber auch ihren Preis. Die Kosten für das Schreiben und insbesondere für die Aufrechterhaltung automatisierter Tests werden oft unterschätzt. Wie viele Projekte haben Sie schon erlebt, in denen nicht alle Tests grün (passed) waren, weil der Zeitdruck zu hoch war oder das Budget dafür fehlte am Ende?
Automatisierte Tests können sehr hilfreich sein für den Nachfolger. Weil dieser am Anfang unmöglich den ganzen Code verstehen kann, ist die Chance groß, dass seine Änderung an einem anderen Ort etwas kaputt macht. Ein guter Test würde diesen Fehler aufdecken. Meistens aber muss der Test nur nachgepflegt werden, damit dieser nach der Änderung wieder grün wird. Dadurch wird der Nachfolger gezwungen, sich mit anderen Codestellen zu beschäftigen und er wird schneller mit dem Projekt vertraut.
Sonstiges
Rechnen Sie damit, dass die Entwickler von heute in ein paar Jahren nicht mehr da sind. Daher muss der Arbeitgeber auf den Verlust seiner Entwickler vorbereitet sein. Ingenieure werden auf manchen Portalen sogar darauf hingewiesen, dass
«Mehr als fünf Jahre Verweildauer vor einem Jobwechsel mit Vorsicht zu genießen sind» [9].
Die oben genannte Dokumentation ist daher ein Muss für den in der Regel nicht überlappenden Wissenstransfer. Wichtig ist es auch, bei Lösungen an der Oberfläche zu bleiben und eher pragmatisch vorzugehen. Entwickler wählen gern die kompliziertere Lösung, weil sie sich damit verwirklichen können (Software-Ego). Durch unnötige Komplexität verliert der Nachfolger aber viel Zeit damit, sich einzuarbeiten und das Risiko, dass er einen Fehler macht, ist unnötig groß. Die Lösung soll nicht komplizierter sein als das Problem.
Bleiben Sie konservativ: wenden Sie nur etablierte Technologien an, vermeiden Sie neue Technologien mit Hype Status.
Teilen Sie den Code so gut es geht in unabhängige, eigenständige Komponenten auf. Diese Komponentenbasierte Entwicklung stand vor 15 Jahren im Vordergrund, ist aber heute irgendwie untergegangen. Eigenständige Komponenten sind einfacher zu testen und, wenn sie gut geschrieben sind, ideal zur Wiederverwendung. Der Nachfolger kann sich auf eine Komponente konzentrieren, ohne den Rest der Software verstehen zu müssen.
Fazit
Die oben erwähnten Best Practices sorgen dafür, dass archivierte Software nach langer Zeit mit möglichst wenig Aufwand wiederbelebt werden kann. Viele der erwähnten Maßnahmen gelten aber auch für Projekte, die kontinuierlich gepflegt werden. Die meisten Software-Entwickler sind schon zufrieden mit einer funktionierenden Lösung. Ein erfahrener Entwickler aber hat einen breiteren Horizont und macht sich Gedanken über Nachhaltigkeit und den Kostenaspekt einer Lösung.
[1] NuGet Package Manager for .NET, https://www.nuget.org
[2] NPM, JavaScript Package Manager, https://npmjs.com
[3] Yarn JavaScript Package Manager, https://yarnpkg.com
[4] WiKi-Software, https://de.atlassian.com/software/confluence
[5] Webanwendung zur Fehlerverwaltung, Problembehandlung und operativem Projektmanagement, https://de.atlassian.com/software/jira
[6] Software zur verteilten Versionsverwaltung von Dateien, https://github.com/git
[7] Cloud Computing-Plattform für Unternehmen, https://azure.microsoft.com
[8] Code Project, Copy DLL from GAC, https://www.codeproject.com/Articles/43775/Copy-DLL-from-GAC
[9] INGENIEUR.DE, Technik-Karriere-News, https://www.ingenieur.de/karriere/arbeitsleben/wie-lange-sollten-ingenieure-bis-zu-einem-jobwechsel-warten/