Hallo! Ich bin Pasha Tschernjak, leitender Entwickler bei QIWI, und heute möchte ich über etwas Unvermeidliches sprechen. Über Legacy.
Lassen Sie uns mit der Frage anfangen: Was ist ein Legacy-Service? Ist es ein Service, den der Entwickler seit einer Woche/Monat/Jahr nicht mehr angefasst hat? Oder ist es ein Service, der von einem weniger erfahrenen Programmierer, vielleicht von Ihnen selbst, vor einem Jahr geschrieben wurde? Und jetzt sind Sie viel erfahrener. Oder ist ein Legacy-Service etwas, das Sie nie wieder committen wollten und langsam durch etwas Neues ersetzen? In jedem Fall ist es eine tickende Zeitbombe, einen solchen Service unbeaufsichtigt zu lassen und nicht zu aktualisieren.
Bevor ich erkläre, wie wir bei QIWI mit unseren Legacy-Services umgehen, möchte ich erzählen, wie wir Ordnung in die Dienste in Wallet gebracht haben. Seit zwei Jahren bin ich für die Funktionsfähigkeit verantwortlich. Wenn es ein Problem gibt, werde ich immer zuerst kontaktiert. Normalerweise habe ich nicht den Mut, um 23 Uhr jemanden anzurufen, also musste ich mich hinsetzen und alle Dienste in unserer Domain durchgehen.
Aber ich, wie jeder andere Mensch, liebe es, nachts zu schlafen, also versuchte ich, die Nutzung zu klären: „Leute, warum ruft ihr mich an?“. Darauf erhielt ich eine recht knappe Antwort wie: „Und wer sonst?“ Denn ich repariere die Dienste, und die Jungs wissen einfach nicht, wen sie anrufen sollen.
Deshalb haben wir bei einem der Retrospektiven des Backend-Teams von Wallet beschlossen, eine Tabelle zu erstellen, auf der unsere Dienste, Mikrodienste und Monolithen des Wallets sowie die dafür Verantwortlichen aufgeführt sind. Tabellen sind insgesamt nützlich, in einem vernünftigen Rahmen.
Neben Informationen darüber, wer wofür verantwortlich ist, gab es dort auch Antworten auf Fragen: Wer ist der Besitzer des Dienstes, wer ist für dessen Weiterentwicklung, Architektur und Lebenszyklus verantwortlich? Die Personen, die für diesen Dienst zuständig sind, sind die, die ihn im Bedarfsfall reparieren können. Der Besitzer des Dienstes hat das Recht, +2 in den Commits zu hinterlassen, und die Verantwortlichen müssen unbedingt an der Prüfung teilnehmen, bevor dieser Dienst einen neuen Commit übernimmt.
Die Zeit verging, und es wurden neue Praktiken eingeführt, wie zum Beispiel die Migration zu Kubernetes, verschiedene Tools wie Checkstyle, Spotbugs, Ktlint, das Vorhandensein von Logs in Kibana, Autodiscovery von Services anstelle der direkten Angabe von Adressen und andere nützliche Funktionen. Und überall ermöglichte unsere Tabelle die Aktualität unserer Services. Für uns fungiert sie als eine Art Checkliste, die zeigt, dass dieser Service das kann und jenes noch nicht. Aber wir gingen weiter und erkannten, dass uns Informationen über unsere Services fehlten, die wir überwachen – wo sich der Source-Code des Services befindet, wo die Builds in TeamCity gestartet werden, wie sie deployt werden, wo die Source-Codes der End-to-End-Tests gespeichert sind, Fotos von Groomings über die Architektur und die getroffenen Entscheidungen. Ideal wäre es, wenn all diese Informationen irgendwo gespeichert wären und griffbereit sind, wenn sie gebraucht werden. Daher wurde unsere Tabelle zum Ausgangspunkt für die Informationssuche.
QIWI bewahrt trotz seines Start-up-Geists den Charakter eines großen Unternehmens. Wir sind bereits 12 Jahre alt, und die Teams wechseln: Menschen gehen und kommen, es entstehen neue Gruppen. Auf unserer Domain haben wir einige Dienste gefunden, die uns im Laufe der Zeit geblieben sind. Einige stammen von Entwicklern anderer Teams, andere hatten nur indirekt mit dem Wallet zu tun, weshalb wir den Service nun auf unserem Konto haben. Warum sollen wir uns mit der Funktionsweise beschäftigen? Der Service funktioniert, und wir haben Produktfunktionen, die unbedingt umgesetzt werden müssen.
Wie es manchmal vorkommt
Doch irgendwann stellen wir fest, dass der Dienst seine Funktion nicht mehr erfüllt, etwas kaputt ist – was tun wir in so einer Situation? Der Dienst funktioniert einfach nicht mehr. Überhaupt nicht. Und wir haben davon erfahren, erstens zufällig und zweitens nach sechs Monaten. So läuft das eben. Das Einzige, was wir wussten, war, auf welchen virtuellen Maschinen der Dienst läuft und wo sich der Quellcode befindet. Wir machen ein git clone und tauchen ein in die Gedanken des Entwicklers, der das vor einigen Jahren geschrieben hat, aber was sehen wir? Kein gewohntes Spring Boot, obwohl wir an alles gewöhnt sind, schließlich sind wir Full Stack und dergleichen. Gibt es da etwa ein Spring Framework? Aber nein.
Der Typ, der das alles geschrieben hat, war strikt und schrieb alles in reinem Java. Die gewohnten Entwicklungswerkzeuge fehlen, und es kommt die Idee auf – das müsste alles neu geschrieben werden. Wir haben schließlich Mikroservices, und aus jedem Toaster ertönt das vertraute „Leute, Mikroservices sind genau das, was ihr braucht!“. Wenn etwas nicht stimmen sollte, könnt ihr locker jede beliebige Sprache nehmen und es wird alles hervorragend funktionieren.
Das Problem ist, dass wir derzeit keinen Auftraggeber haben, der für diesen Service verantwortlich ist. Was sind seine geschäftlichen Anforderungen und was sollte dieser Service überhaupt leisten? Und der Service ist eng in Ihre Geschäftsprozesse integriert.
Und jetzt sagen Sie mir, wie einfach es ist, einen Service neu zu programmieren, ohne seine geschäftlichen Anforderungen zu kennen? Es ist unklar, wie der Service geloggt wird, ob es Metriken gibt – das ist unbekannt. Welche es gibt, falls vorhanden – das ist umso weniger bekannt. Zudem gibt es im Service eine Vielzahl von Klassen mit unklarer Geschäftslogik. Etwas wird in eine Datenbank eingegeben, über die wir ebenfalls noch nichts wissen.
Womit fangen wir an?
Am logischsten ist der Beginn mit vorhandenen Tests. Dort ist normalerweise wenigstens eine gewisse Logik festgehalten, und man kann Rückschlüsse darauf ziehen, was passiert. Momentan ist TDD in Mode, aber wir sehen, dass es vor 5 Jahren kaum anders war als heute: Es gibt fast keine Unit-Tests, und sie werden uns auch genau genommen überhaupt nichts sagen. Nun, abgesehen vielleicht von einer irgendwie gearteten Prüfung, wie ein XML mit einem bestimmten Zertifikat unterschrieben wird.
Der Code war nicht verständlich und wir mussten genauer hinschauen, was in der virtuellen Maschine vor sich ging. Wir öffneten die Service-Logs und fanden einen Fehler im HTTP-Client: Ein selbstsigniertes Zertifikat, das in die Ressourcen der Anwendung eingebettet war, war abgelaufen. Wir kontaktierten unsere Analysten, die uns um ein neues Zertifikat baten, welches dann ausgestellt wurde, und der Service funktioniert wieder. Man könnte denken, das wäre alles. Oder doch nicht? Der Service läuft, er erfüllt eine Funktion, die für unser Geschäft notwendig ist. Wir haben bestimmte Standards für die Anwendungsentwicklung, die wahrscheinlich auch bei Ihnen gelten. Zum Beispiel sollten Logs nicht direkt auf der Node gespeichert werden, sondern in einem Speichersystem wie Elasticsearch, und man sollte sie in Kibana ansehen. Man kann auch die goldenen Metriken erwähnen. Das bedeutet, die Auslastung des Services, die Anzahl der Anfragen, ob er online ist oder nicht, und wie er den HealthCheck besteht. Diese Metriken können zumindest helfen zu erkennen, wann man ihn mit gutem Gewissen außer Betrieb nehmen und vergessen kann wie einen Albtraum.
Was tun?
Daher fügen wir diesen alten Dienst in die Tabelle ein und suchen dann nach Freiwilligen unter den Entwicklern, die sich um den Dienst kümmern und ihn in Ordnung bringen: sie sollten zumindest einige Informationen über den Dienst verfassen, Links zu Dashboards in Grafana hinzufügen, die Aufgaben für den Aufbau verstehen und herausfinden, wie man die Anwendung bereitstellt. Schließlich kann man die Dateien nicht einfach händisch per FTP hochladen.
Das Wichtigste dabei ist: Wie viel Zeit wird all diese nützliche freiwillige Aktivität in Anspruch nehmen? Ein Sprint für einen halbwegs erfahrenen Entwickler, beispielsweise während 20 % der technischen Schulden. Und wie viel Zeit wurde benötigt, um die fest verwurzelte Logik im Umgang mit einem bestimmten Regierungssystem zu verstehen und es auf modernere Technologien zu bringen? Dafür kann ich keine Garantie geben; es könnte einen Monat, vielleicht sogar zwei Monate Teamarbeit in Anspruch nehmen. Ich spreche hier aus Erfahrung bei der Integration mit einem neuen Dienst.
In diesem Zusammenhang gibt es keinen geschäftlichen Mehrwert — überhaupt keinen. Es ist völlig normal, einen Service zu unterstützen und dafür etwas Zeit aufzuwenden. Nach unseren üblichen Schwierigkeiten mit dem Service haben wir ihn in die Tabelle aufgenommen, Informationen darüber hinzugefügt, und vielleicht werden wir ihn irgendwann umschreiben. Aber im Moment entspricht er unseren Service-Standards.
Zusammenfassend möchte ich einen gewissen Plan skizzieren, was mit Legacy-Services zu tun ist.
Das Legacy-System von Grund auf neu zu schreiben, ist eine schlechte Idee.
Ehrlich gesagt, darüber braucht man gar nicht erst nachzudenken. Es ist klar, dass es wünschenswert wäre und gewisse Vorteile sieht, aber normalerweise ist das für niemanden nötig, auch nicht für Sie selbst.
Verzeichnis
Holen Sie den Quellcode Ihrer Anwendungen hervor, erstellen Sie ein Verzeichnis, in dem festgehalten wird, was wo liegt und wie es funktioniert. Fügen Sie auch eine Projektbeschreibung (sozusagen ein readme.md) hinzu, damit man schnell versteht, wo sich die Logs und Metriken befinden. Der Entwickler, der nach Ihnen damit arbeitet, wird Ihnen nur dankbar sein.
Verstehen Sie die Domain
Wenn Sie eine Domain besitzen, sollten Sie stets auf dem Laufenden bleiben. Es mag banal klingen, aber nicht jeder sorgt dafür, dass die Dienste einheitlich sind. Dabei ist es tatsächlich viel einfacher, in einem einheitlichen Standard zu arbeiten.
Nur registrierte Benutzer können an der Umfrage teilnehmen. Sind Sie an Contour interessiert?
Was machen Sie mit Ihrem Legacy?
31.5%Ich schreibe alles von Grund auf neu, das ist die richtige Vorgehensweise.
52.6%Ähnlich wie Sie.
10.5%Wir haben kein Legacy, wir sind gut.
5.2%Ich schreibe es in die Kommentare.
38 Benutzer haben abgestimmt. 20 Benutzer haben sich enthalten.
Quelle: habr.com
