Quellcodes verändern, ohne die Updatefähigkeit zu verlieren

Infinite Hooks: Anfassen erlaubt!
Keine Kommentare

Da sitzt du nun vor 100 000 Zeilen Quellcode einer Software und darfst nur schauen, aber nichts anfassen. Du weißt, dass deine Änderung beim nächsten Update der Software in drei Wochen wieder weg wäre. Manchmal änderst du den Quellcode trotzdem direkt, weil du es musst, und verlierst damit die Updatefähigkeit der Software – Sicherheitspatches und neue Features vom Anbieter werden nicht mehr oder nur noch selten eingespielt. Gibt es eine Lösung?

Du wirst jetzt vielleicht sagen, dass es inzwischen moderne Software (also die mit einer Million Zeilen Sourcecode) gibt, die man auf verschiedene Arten und an ultra vielen Stellen erweitern kann. Eine direkte Änderung am Code der Software ist nicht mehr notwendig. Richtig, kaum noch. Klassenvererbung, Decorators, Datenfilter, Notifiers, Actions, Events und Hooks – das alles sind feine Sachen, die dabei helfen, deinen eigenen Code von dem des Anbieters getrennt zu halten und deren Nutzen sich schwer absprechen lässt. Aber perfekt ist das noch nicht. Da ist noch Luft. Ja, da geht noch mehr Freiheit.

Du benutzt die Software also für einen Kunden, ein Projekt. Deshalb bist du (mit deinen Kollegen) näher dran am Geschehen und weißt besser, was die Software in deinen Händen im Endeffekt tun oder nicht tun soll und wie; besser doch als derjenige oder diejenigen Programmierer, welche(r) sich den Code im core, vendor, src, system oder lib Verzeichnis ausdachte(n). Anpassungen am Core oder an Third Party Libraries für Bugfixes oder Erweiterungen außerhalb der für eigene Plug-ins oder Add-ons vorgesehenen Struktur können gemacht werden, wenn der Commit gespeichert und nach dem Update wieder eingesetzt wird.

Anwendungsbereiche

Mit diesem Konzept lässt sich die Funktionalität einer Software erweitern oder verbessern, wo es vorher nicht möglich war. Und dort, wo es bereits möglich war, kann man es schneller und auf explizitere Weise tun: Es werden lediglich die Zeilen des Herstellers in die Inkompatibilitätsgefahrenzone bewegt, die unbedingt dort hingehören, und nicht unnötigerweise viele andere mit. Außerdem warnt das System frühzeitig, wenn in einem Update des Herstellers an der gleichen Stelle Anpassungen stattfanden. Ein Umstand, den man sonst nur durch Testen oder schlimmstenfalls der Kunde als Fehler findet. Das trägt zu einer höheren Qualität der Software und einer reibungsloseren Wartung bei.

Die Unantastbaren

Klar, Open-Source-Software lässt sich prinzipiell ändern. Problematisch wird es dann, wenn man die Software auf eine neue Version aktualisieren will. Dann passiert im Wesentlichen eine Sache: Der Hersteller bügelt seine neuen Dateien einfach drüber. Doch dieses Vorgehen ist in verschiedenen Fällen unzureichend.

Open-Source-Software besteht üblicherweise aus

  1. Core-Code des Herstellers
  2. Drittanbietersoftware im Core-Code des Herstellers
  3. Drittanbietersofzware (Plug-ins)
  4. eigenem Code (eigene Plug-ins)

Um Funktionen oder Layout zu editieren respektive zu erweitern, werden Änderungen an Dateien, welche nicht zu einem eigenen Plugin (4.) gehören, nicht durchgeführt oder als Hack bezeichnet, weil diese bei einem Versionsupdate der Software oder des Drittanbieter-Plug-ins überschrieben würden und damit verloren gingen.

Für 1.-3. heißt es: Noli me tangere – berühre mich nicht! Es bleiben für Funktionserweiterungen oder Bugfixes nur zwei Wege: ein eigenes Plugin erstellen, das die gewünschte Abwandlung mit den vom Hersteller angebotenen Mechanismen durchführt, oder eine Anfrage an den Hersteller, die Quellcodeänderung zu übernehmen.

Anpassung über den Hersteller

Je nach Komplexität kann es eine langwierige Angelegenheit sein, den Softwarehersteller zur Integration einer Fehlerbehebung zu bewegen. Möglicherweise muss dazu ein Ticket angelegt werden, dessen Bearbeitungsdauer nicht vorhersehbar ist, oder Diskussionen mit der Community geführt werden.

International PHP Conference 2018

Getting Started with PHPUnit

by Sebastian Bergmann (thePHP.cc)

Squash bugs with static analysis

by Dave Liddament (Lamp Bristol)

API Summit 2018

From Bad to Good – OpenID Connect/OAuth

mit Daniel Wagner (VERBUND) und Anton Kalcik (business.software.engineering)

Selbst dann, wenn der Hersteller z. B. aufgrund eines Premiumwartungsvertrags möglichst schnell reagieren möchte, so hat er auf die Reaktionszeit im Fall von Drittanbietersoftware, welche er wiederum in seinem Produkt einsetzt (2.), keinen oder nur wenig Einfluss (Kasten: „Bug im TinyMCE HTML-Editor in Shopware“).

Bug im TinyMCE HTML-Editor in Shopware

Beispiel: Die Artikelbeschreibung in Shopware kann in bestimmten Versionen des Internet Explorers nicht bearbeitet werden. Der Grund dafür ist ein fehlendes Exception Handling in einer JavaScript-Datei im verwendeten WYSIWYG-Editor TinyMCE.

TinyMCE wird standardmäßig in Shopware als Bibliothek eingebunden. Der Fehler ist der Shopware AG bereits bekannt und kann dort nur durch Integration einer Version von TinyMCE behoben werden, in der dieser Fehler ausgemerzt ist.

Auch die Entwickler von TinyMCE wurden bereits öffentlich auf den Bug aufmerksam gemacht, doch diese für den Kunden wegen Browserwahleinschränkungen am Arbeitsplatz dringende Angelegenheit hat in der Community nicht die höchste Priorität.

Handelt es sich bei der Anpassung nicht um eine Fehlerbehebung, sondern um lediglich im eigenen Projekt benötigte Erweiterungen, so ist der Weg über den Hersteller erst recht schwierig.

Anpassung über eigenes Plug-in

Das Vorgehen, Layout und Funktion über Klassenvererbung, Datenfilter und Hooks zu ändern, wird allgemein als richtig propagiert und mit umfangreicher Dokumentation auf den Seiten des Herstellers beschrieben. Mit diesen Mechanismen kann man den Quellcode dort anpassen, wo und wie es vorgesehen ist. Doch oft sind Änderungen an der Software anders oder an anderen als vom Hersteller geplanten Stellen praktisch oder notwendig. Erneut würde man dann wieder vor dem Problem stehen, den Anbieter oder die Community um eine zusätzliche Anpassungsmöglichkeit zu bitten – sofern diese je nach Dateityp oder Architektur überhaupt durchführbar ist.

Nicht zu vernachlässigen ist auch der Zeitfaktor: Die betreffende Codestelle in den Core-Dateien ist oft sehr schnell ausfindig gemacht und auch eine mögliche Lösung. Der größte Aufwand besteht oft darin, herauszufinden, wie der Hersteller eine Erweiterung und Anpassung an dieser Stelle vorsieht; das eigene Expertenwissen hilft nicht, denn die Vorgehensweise hat mit der eingesetzten Programmiersprache kaum noch zu tun und kann sich außerdem von Version zu Version des Systems ändern.

Was hilft, ist sich eine Liste von Codeänderungen anzulegen, die nach einem Software- oder Plug-in-Update automatisch wieder eingefügt werden. Voraussetzung ist dabei, dass die zu speichernde Änderung als Git Commit vorliegt. Man ändert also eine Core-Datei und reicht diese ins Repository ein. Im Verzeichnisbaum (Abb. 1) wird zur Datei navigiert und der Commit gewählt, den man für die Datei behalten will.

Abb. 1: Verzeichnisbaum

Abb. 1: Verzeichnisbaum

Bei einem Versionsupdate gehen zunächst alle Core-Änderungen verloren, werden aber anschließend erneut ins Repository gepusht. Abb. 2 zeigt zwei reguläre und dann einen automatischen Commit.

Abb. 2: Git- Log

Abb. 2: Git- Log

Schlägt eine Änderung nach einem Update fehl, ist das ein wichtiger Hinweis darauf, dass es genau an dieser Stelle in der neuen Version des Herstellers Änderungen gab. Dies ist ein weiterer Vorteil des Konzepts, der den Einsatz sogar dann sinnvoll macht, wenn es ein offizielles Vorgehen zu einer bestimmten Anpassung gibt.

Ein anderes Beispiel ist die saveOrder-Methode von Shopware. Beim Speichern einer Bestellung kann in Shopware über ein eigenes Plug-in entweder zuvor oder danach Code ausgeführt werden, oder aber man ersetzt die gesamte Prozedur. Abbildung 3 zeigt die herkömmliche Erweiterung dieser Funktion um die folgende Zeile Code: $order->prepareForWarehouse().

Um das Ziel zu erreichen, müssen mindestens 22 Zeilen Code geschrieben werden.

Abb. 3: Herkömmliche Erweiterung der „saveOrder“-Methode in Villabajo

Abb. 3: Herkömmliche Erweiterung der „saveOrder“-Methode in Villabajo

Während die Entwickler in Villabajo noch verwirrt in der Shopware-Dokumentation zu EventSubscriber nachschlagen, haben die Programmierer in Villariba die Zeile Code bereits eingefügt (Abb. 4).

Abb. 4: Direkte Codeänderung in Villariba

Abb. 4: Direkte Codeänderung in Villariba

Die Chancen, dass diese Anpassung kompatibel zum Shopware Core bleibt, sind vierzehnmal höher, haben wir schließlich nur eine Zeile eingefügt und nicht die komplette Methode überschrieben.

Kompatibilitätswarnung

Sollte es in der neuen Version von Shopware in einer dieser 14 Zeilen eine Änderung geben, dann merkt man in Villariba unter Umständen gar nichts davon, was zu unvorhersehbaren Effekten und Fehlern sogar im Livesystem führen kann.

Hat sich jedoch just diese eine Stelle in der neuen Version geändert, an welcher der gespeicherte Commit wieder platziert werden soll, dann sendet das System eine Nachricht (Abb. 5). Diese enthält einen Link zum Git-Repository, in dem Details eingesehen werden können. In diesem Fall muss tatsächlich Hand angelegt werden; wichtig ist, dass man frühzeitig gewarnt wurde.

Abb. 5: Konfliktwarnung

Abb. 5: Konfliktwarnung

Mögliche Typen

Prinzipiell gibt es drei Arten, auf die sich solch eine Änderung behalten lässt:

  1. Änderung an einer Datei innerhalb eines Commits: Es wird eine Datei innerhalb des Repositorys gewählt und anschließend aus der Historie der Commits derjenige, welchen man verewigen möchte. Der Commit kann Änderungen an anderen Dateien enthalten, die jedoch ignoriert werden.
  2. Ganzer Commit: Durch Angabe lediglich der Commit ID werden sämtliche Änderungen an allen innerhalb des Commits betroffenen Dateien gespeichert.
  3. Suchen und Ersetzen: Ohne Versionsverwaltung wird nach einer Textstelle gesucht und diese ersetzt.

Realisiert wurde die Eine-Datei-Variante (1.), weil sie die höchste Flexibilität und Integrationsfähigkeit bietet.

Webhook

Damit nach einem Softwareupdate umgehend reagiert wird, lässt sich für das Git Repository ein Webhook eintragen; dieser triggert das Scannen der Branches auf Änderungen und das Einfügen des Quellcodes. Eine in einem Branch gespeicherte Änderung wird dabei auf alle Branches angewandt, welche nicht explizit deaktiviert wurden.

Performance

Die Geschwindigkeit, mit der eine gespeicherte Anpassung in eine Datei implementiert wird, ist für einzelne Projekte nicht wirklich ein Thema, doch bei mehreren Branches und einem Dutzend Commits schon deutlich spürbar, weshalb Änderungen in eine Redis Queue eingetragen und dann von n PHP-Skripten parallel abgearbeitet werden. Eine Docker-/Kubernetes-Version zeigte weiteres Skalierungspotential.

„.gitignore“ Whitelisting

Damit eine Änderung gespeichert werden kann, muss sich diese Änderung ins Repository einreichen lassen. Gerade die Hersteller- oder Drittanbieterdateien befinden sich wegen der hohen Anzahl und der Tatsache, dass sie normalerweise nicht geändert werden, oft in Verzeichnissen, die in der .gitignore-Datei eingetragen und damit aus Git ausgeklammert sind.

Das kann prinzipiell auch so bleiben, die zu ändernden Dateien lassen sich explizit und einzeln in die Versionsverwaltung aufnehmen; dafür gibt es zwei unterschiedliche Herangehensweisen, dargestellt in Listing 1 und Listing 2.

pippo/*
!pippo/pluto
pippo/pluto/*
!pippo/pluto/paperino.xml

# alles ignorieren
*
# außer bestimmten Dateien
!.gitignore
# selbst, wenn in Unterverzeichnissen
!*/
# Dateien im Dateibaum rekursiv erlauben 
!/vendor/**
# auch spezifisch in einer verschachtelten Struktur
!/vendor/tiefer/tiefer/ast/im/baum/**
!*/a/b/file1.txt


PHP Magazin

Entwickler MagazinDieser Artikel ist im PHP Magazin erschienen. Das PHP Magazin deckt ein breites Spektrum an Themen ab, die für die erfolgreiche Webentwicklung unerlässlich sind.

Natürlich können Sie das PHP Magazin über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. In unserem Shop ist das Entwickler Magazin ferner im Abonnement oder als Einzelheft erhältlich.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -