Hallo! Ich bin Valery Laptev, Leiter der LM-Entwicklung in Russland. Zwei Jahre lang musste ich eine riesige Abteilung aufbauen, und es war eine ziemlich interessante Erfahrung.
Tatsache ist, dass Leroy Merlin in vielen Ländern ist. Die Muttergesellschaft in Frankreich heißt ADEO. Sie schreiben Code für Frankreich, Italien, Spanien und Russland. Unsere Geschäftsmodelle sind unterschiedlich: Wenn wir die niedrigsten Preise auf dem russischen Markt halten (unter allen Wettbewerbern bei der Überwachung), dann ist in Europa alles anders. Tatsächlich unterscheidet sich das Meer - von den Merkmalen des Gebietsschemas bis zu anderen Rechtsvorschriften. Es gibt Merkmale der Infrastruktur Russlands (die gleichen sehr großen Verzögerungen für Chabarowsk) und einen weiteren Lebenszyklus für die Bestellung. All dies führt zu solch höllischem Code, der aus riesigen IF-Blöcken besteht:

Vor zwei Jahren hatten wir 60 Geschäfte und viele, viele Wunschliste-Funktionen. Sie rollten in ungefähr sechs Monaten und nicht immer richtig. Der letzte Strohhalm nach einer Reihe von Features, die mit niedriger Priorität abgelehnt wurden, war die Aufforderung, ein Zeilenfeld in der Reihenfolge einzugeben, damit wir es später analysieren können. Dies war für die Merkmale der Lieferung in Russland erforderlich, da das Land größer ist als andere Länder, in denen LM vertreten ist. Sie lehnten dies ab oder sagten, dass es in sieben bis acht Monaten irgendwo sein würde.
Der Halbjahreszyklus der gemächlichen Muttergesellschaft passte nicht zu uns. Natürlich haben wir vorgeschlagen, unseren eigenen Code zu schreiben, ihn der Überprüfung zu unterziehen und auf die Implementierung zu warten ... Richtig, daraus wurde nichts Gutes.
Warum wurden Funktionen langsam implementiert?
Die Geschichte ist sehr einfach: Trotz unserer Dutzende von Geschäften sind wir nicht die ersten auf der Welt. Es gibt die Bedürfnisse Frankreichs (wo sich die Mutterorganisation befindet), es gibt die Bedürfnisse anderer Länder. Sie werden nach möglichen Gewinn- oder Kostensenkungen für eine Unternehmensgruppe priorisiert und in dieser Reihenfolge ausgeführt. Das heißt, unsere Funktionen werden fast nie erstellt, es sei denn, Sie haben großes Glück und in einer Art Sprint wird jemand seinen Teil früher beenden und den unteren Teil des Rückstands abbauen.
Die zweite Funktion besteht darin, dass Sie beim Rolling einer Funktion in den Hauptzweig (hier in diesem Legacy-IF-IF-IF-Code) überprüfen müssen, wie sie sich in anderen Ländern verhält. Lassen Sie mich
441869 aus Bash zitieren:
Programmierer: Stellen Sie sich vor, Sie sind Schriftsteller und unterstützen das Projekt "Krieg und Frieden". Sie haben TK - schreiben Sie ein Kapitel darüber, wie Natasha Rostova im Regen im Park spazierte. Sie schreiben - "es hat geregnet", außer, die Fehlermeldung fliegt heraus: "Natasha Rostova ist gestorben, Fortsetzung ist unmöglich." Warum ist sie tot? Du fängst an zu verstehen. Es stellt sich heraus, dass Pierre Bezukhovs rutschige Schuhe fielen, seine Waffe auf den Boden traf und auf eine Stange schoss und die Kugel von der Säule auf Natasha abprallte. Was zu tun ist? Waffe im Leerlauf aufladen? Schuhe wechseln? Wir beschlossen, die Säule zu entfernen. Wir erhalten die Nachricht: "Leutnant Rzhevsky ist gestorben." Es stellt sich heraus, dass er sich im nächsten Kapitel auf eine Säule stützt, die nicht mehr ...
Wenn wir irgendwo in Brasilien etwas für die russische Abendkasse einführen, kann sich im Allgemeinen jemand erholen.
Dies bedeutet eine sehr große Testabdeckung, lange Vorabversionsverfahren und im Allgemeinen eine Zurückhaltung bei der Pflege von Code, der schnell wächst. Je weniger Funktionen, desto besser. Aber du hältst dich dort fest.
Die Position insgesamt ist sehr verständlich, und genau das würde ich auf der Website der Muttergesellschaft tun. Weil es rational ist.
Lösung
Der erste Ansatz war auf der Stirn: Wir schlugen vor, einen Code zu öffnen, damit wir dort Pull-Anfragen stellen können. Es wurde angenommen, dass dort ungefähr 10 Entwickler sitzen würden, die schnell und schnell geschäftskritische Funktionen codieren, sie den Franzosen geben und sie nach ihrem eigenen Verfahren testen würden, und alles wäre in Ordnung.
Tatsächlich waren diese Leute bereits: Wir waren damit beschäftigt, die zusätzliche Geschäftslogik, die wir aus anderen Ländern erhalten haben, wie verschiedene kumulative Rabatte und ungewöhnliche Aktien (die mit unserem Geschäftsmodell einfach unmöglich sind), herauszuschneiden und Dummies an diese Stelle zu setzen.
Die Franzosen bei ADEO wollten einen Release-Zyklus, um neue Versionen selbst zu rollen und zu installieren. Akzeptierte unser Angebot über einen Zweig für Experimente.
Erhielt Zugang, begann den Code für die Überprüfung zu nehmen. Es stellte sich sowieso als langsam heraus. Rollouts für mehrere Monate - das ist nicht der Fall. Gut gewonnen ein paar Wochen, aber immer noch passte der Prozess nicht.
Dann kam sechs Monate lang eine für uns wichtige Funktion im Inhaltsteil (Verwalten von Produktdaten, die der Kunde sieht) nicht heraus. Wir saßen sechs Monate ohne Freilassung. Entweder ging ihre Funktion nicht oder die Tests bestanden nicht, dann erkannten sie nicht genau, was wir brauchten. Infolgedessen saßen wir lange Zeit ohne Updates auf einem Schlüsselsystem. Es gab NodeJS + PostgreSQL + Couchbase + Elasticsearch + Angular an der Vorderseite. Im Code sind aufgrund einer Reihe von archäologischen Schichten Dinge wie der Missbrauch der SQL-Datenbank und der nicht relationalen Datenbank aufgetreten. An einer der Stellen wurde ein riesiges Stück Stammdaten aufgenommen, in ein Feld der SQL-Datenbank eingefügt und dann in Entitäten in der NoSQL-Datenbank aufgeteilt. Auf einer Seite der Website mit der Anzeige von Waren gab es Dutzende und Hunderte solcher Anfragen. Mit der weiteren Lektüre dieses Erbes begannen sich Haare an verschiedenen Körperteilen zu bewegen. Wir haben verstanden, mit welchen Besonderheiten der Legacy-Schichtung der Kopfteil konfrontiert ist.
Eigene Entwicklung
Die erste Idee war, Features zusammen zu machen. Vor Ort, also in Frankreich. Wir vier gingen nach Frankreich und setzten uns neben unsere Kollegen, um alles gemeinsam zu verstehen und zu tun, was wir brauchten.
Es hat nicht funktioniert. Trotzdem war alles sehr langsam.
Die zweite Idee war, alles, was bereits existiert, zu teilen und schrittweise zu beenden. Wir haben uns vom Architekturkomitee zusammengesetzt, die Aussichten bewertet, die ungefähren Entwicklungspläne berechnet und festgestellt, dass wir eine andere Methode wählen müssen. Insbesondere ja, um den vorhandenen Code zu teilen, aber nicht, um ihn zu entwickeln, sondern um den Monolithen in Teile zu zerlegen und Microservices dort zu platzieren, wo sie benötigt werden.
Das heißt, wir wollten ganze Logikblöcke in Form unseres Codes neu schreiben. Und dafür begannen sie, einen Teil der Dienste auf das umzustellen, was mit uns getan werden konnte. Wir haben angefangen, Entwickler zu rekrutieren. Dann folgten wir vollständig dem Stapel der Muttergesellschaft - Java, Spring und alles ist in der Nähe, anstelle von Couchbase war Mongo (dies ist eine ähnliche NoSQL-Basis).
Als sich das Projekt entwickelte, stellten wir fest, dass wir viele Dinge auf unsere eigene Weise erledigen mussten (weil es schneller und einfacher ist, um nicht das Erbe zu unterstützen, das wir insbesondere nicht benötigen), und begannen, auf andere Technologien zu expandieren. Dann gab es Java 7, Wildfly (früher JBoss) und SVN. Wir haben gefragt, warum sie nicht auf Java 8, GIT und Tomcat migrieren. Es stellte sich heraus, dass es ihnen nichts ausmachen würde, aber nach ein paar Jahren. In der Zwischenzeit, meine Lieben, schreiben Sie auf den alten Stapel. Also haben wir Wort für Wort beschlossen, uns vollständig zu trennen. Das Unternehmen hat die Frage nach den Vor- und Nachteilen geklärt und sie voll unterstützt.
Fast sofort warf etwa 30 Prozent des Codes, schrieb viele ihrer Microservices herum. Aus der Tatsache, dass sie nicht berührt haben, ist es fast der gesamte Kern der Transaktion von Geschäftsprozessen für Geld.
Das erste, worüber wir nachdachten, war natürlich, wie man zwischen Entwicklungsbereichen unterscheidet. Ich würde auch separat darüber sprechen, aber im Allgemeinen ist das Schema wie folgt:

Horizontal ist ein Geschäftsbereich. Zum Beispiel ist alles, was mit Kundenbeziehungen zu tun hat (die erste grüne Zelle), ein Bereich, und es gibt eine Reihe von Anwendungen aus einer Abteilung. Diese Trennung der Zielfunktion erzeugt mehrere Duplikate des Codes an verschiedenen Stellen und erfordert einen guten Firmenbus (wieder eine separate Geschichte), aber Sie können die Enden klar finden und das Problem bis zum Ergebnis lösen. Wenn ich das nach fast drei Jahren betrachte, kann ich sagen, dass die Architektur richtig gewählt wurde, aber wenn ich wüsste, was ich jetzt weiß, würde ich ein paar Änderungen vornehmen.
Jetzt sind wir zu dem Schluss gekommen, dass es in der allgemeinen Struktur viele Feature-Teams gibt, aus denen große Produktteams bestehen. Gleichzeitig umfasst das Produktteam nicht nur die Entwickler selbst, sondern auch Designer und Unternehmensvertreter. Da das ultimative Ziel jeder IT-Abteilung eines Unternehmens darin besteht, entweder die Geschwindigkeit der Geschäftsentwicklung zu erhöhen oder die Kosten aufgrund der Automatisierung zu senken, benötigen wir Unternehmensvertreter in diesen Teams. Im Einzelhandel dreht sich alles um IT. Es gibt keinen einzigen Prozess, der als "unnahbar" bezeichnet werden könnte.
Ein Feature-Team ist eine kleine Gruppe von Personen (normalerweise ein Analyst, Tester, Back-End-Entwickler und Front-End-Entwickler, ops). Der Analyst spielt normalerweise die Rolle des Eigentümers des Produkts oder eine Person aus dem Unternehmen kommt an diesen Ort. Der Eigentümer hat einen Rückstand, Priorität, Aufgaben. Er diktiert ihre Entwicklung. Der Entwickler wählt die Implementierungsoption selbst aus und bespricht im Team, was und wie getan wird. Wir haben keinen Teamleiter für die Bewertung, Kodierung und Entscheidungsfindung von Aufgaben. Jeder macht alles. In der Regel geben erfahrene Teammitglieder Meinungen ab, auf die sich viele verlassen können. Aber jeder kann eine Entscheidung treffen. Natürlich gibt es Konflikte, wenn sich zwei Entwickler nicht auf die Implementierung eines Features einigen können. Wenn sich der Konflikt in eine Persönlichkeit verwandelt hat, brauchen Sie eine Eskalation zum Kopf. Das meiste davon ist jedoch die Wahl einer Lösung für die Implementierung. Dann steht jeder und nähert sich dem Brett, bis er eine Option findet, die zu jedem passt. Normalerweise stellt sich heraus, dass es schnell ging, aber es gab Fälle, in denen sie sich den ganzen Tag stritten. Wenn das Argument zum Stillstand kommt, wird der Schiedsrichter oft gerufen - eine Person aus einem anderen Team, deren Meinung jeder vertraut. Sie erklären die Essenz des Problems, löst er. Sogar ein Juni oder ein Auszubildender kann an diesem Streit theoretisch teilnehmen, aber ich kenne nur einige solcher Fälle - normalerweise haben die Joons einen Mentor, dem sie zuhören.
Ein Beispiel für ein Feature-Team: Wir haben eine Serviceplattform, mit der Sie einen Service zusammen mit Waren bei einem Auftragnehmer kaufen können. Zum Beispiel habe ich eine Tür gekauft - Sie können sie sofort in den Korb legen und installieren, so dass ein unabhängiger Meister nach unserem Standard kommt und tut. Wir werden prüfen und bezahlen, eine Garantie geben. Also macht dieses Team ein Produkt, dafür schreibt es IT-Lösungen und trifft Geschäftsentscheidungen, ändert Prozesse in Geschäften. Vereinbaren Sie mit Auftragnehmern. Dort - der Besitzer des Produkts aus dem Geschäft, der Angestellte aus den Geschäften, der Architekt, die Entwickler, die Analysten und der Tester. Sie verwenden sofort unsere Unternehmens-API-Plattform, um alle Daten hin und her zu liefern und einen Microservice zu schreiben. Ein solcher Ansatz - sofort Betriebs- und Geschäftsleute in Zusammenarbeit mit Entwicklern und einem kleinen Team - ermöglicht es Ihnen, schnell ein Produkt zu erstellen. Aber ich denke, es ist besser, wenn sie dir später selbst sagen, wie es von innen aussieht.
Anfangs wollten wir keine separaten Tester durchführen: Es gab einen Trend, dass der Entwickler entweder der TDD-Methodik folgen oder seinen Code bis zum Ende selbst testen sollte. In der Tat war es nicht sehr effektiv. Zuerst lief alles gut: schrieb - du antwortest. Sie benötigen Tests, damit Ihre Anwendung ordnungsgemäß funktioniert. Aber je mehr Aufgaben und Anwendungen wurden, desto schwieriger wurde es. Einige Anwendungen starben aus, andere gingen zum Produkt und änderten sich monatelang nicht. Es wurde schwierig, Tests zu schreiben, zu pflegen und so weiter. Teamanalysten haben sich verändert. Vor relativ kurzer Zeit waren sie sich einig, dass sie falsch lagen: Tester werden benötigt. Aber Entwickler hören nicht auf, Tests zu schreiben und - manchmal - TDD zu machen. Wir haben selbst erkannt, dass die Tests, die die Funktionalität überprüfen (die Anwendung funktioniert ordnungsgemäß) und die Tests, die überprüfen, ob die Anwendung in problematischen Situationen funktioniert, von verschiedenen Personen durchgeführt werden sollten. Und zum zweiten werden Tester benötigt, weil sie mögliche seltsame Fälle nicht nur mit Unit-Tests abdecken.
Jetzt gibt es 60 reine Entwickler - hinten, vorne, volle Stapel. Es gibt auch Analysten, Tester und Support. Und plus weitere sieben Devops. Trotzdem werden 200 geplante Personen aus dem Titel nicht rekrutiert, daher suchen wir jetzt nach neuen Mitarbeitern, da das Arbeitsfeld riesig ist. Es gibt offene Stellen in
meinem Kreis , wenn das so ist. Das heißt, aus der Entwicklung haben wir jetzt 74 von ungefähr 200.
InnerSource
Angesichts der Tatsache, dass wir nur in Russland viele unabhängige Teams haben und es immer noch Teams gibt, die in vielen anderen Ländern etwas Ähnliches gesehen haben, bewegen wir uns in Richtung
Innsource . Dies ist Open Source innerhalb einer begrenzten Gruppe von Personen sehr ähnlich.
Innerhalb der ADEO-Gruppe aller Länderabteilungen liegt der gesamte Code im Cloud-Github. Das Projekt wird nach einheitlichen Gestaltungsregeln erstellt. Es gibt keine Einschränkungen in Bezug auf Stil, Technologie und Werkzeuge. Wenn Sie Open Source Code und klare Designregeln haben, kann jeder Entwickler auf dem Stack einen Beitrag leisten. Um Sie in den Code zu kopieren, müssen Sie das Dock lesen, das Repository klonen, eine Bearbeitung vornehmen und eine Pull-Anfrage senden.
Derzeit nutzen Brasilien, Russland und Frankreich diese gemeinsame Basis sehr aktiv.
Wir versuchen jetzt, den gesamten Code der Auftragnehmer (und wir haben viele davon in verschiedene Richtungen) an InnerSource zu übertragen. In der Analyse haben wir eine Karte auf zwei Achsen erstellt: die technische Komplexität der Übertragung auf den Modus des inneren Kreises auf einer Achse und die zweite Achse, wie nützlich die Übertragung auf den inneren Kreis im Allgemeinen ist. Wenn der Code eindeutig ist und nur an einer Stelle benötigt wird, müssen Sie ihn möglicherweise nicht einmal berühren. Aber wenn viele Teams diese Seite nutzen, ist dies definitiv notwendig.
All dies fördert im Allgemeinen die Entwicklungskultur. Und es beschleunigt die Geschwindigkeit mehrerer Teams, da Sie für jede Funktion, die Sie benötigen, eine Zusammenführungsanforderung schreiben können. Es wird vom Eigentümerteam angeeignet und von demjenigen getestet, der den Beitrag leistet. Eine der wichtigsten Bedingungen ist die Verfügbarkeit von Autotests und Beschreibungen von Code im Repository.
Noch ein paar Nuancen
Als sie anfingen, gab es überhaupt nichts. Parallel zu den Entwicklern rekrutierten sie Entwickler. Jetzt werden Devobservices entweder als Service bereitgestellt (für diejenigen, die sie benötigen), oder das Produktteam verfügt über eigene Operationen, die bereits festlegen, was und wie.
Die Montage erfolgt in Jenkins, der Code wird in Sonar ausgeführt (genauer gesagt bereits SonarQube). Sonar fehlgeschlagen - keine Veröffentlichung. Tester schreiben Autotests, Codebesitzer - Funktionstests. Die Datenbank wird von Infrastrukturingenieuren als Service bereitgestellt. In seltenen Fällen werden Volllasttests durchgeführt, da die Struktur der Testbasis und der Hauptbasis unterschiedlich ist: Auf der Vorproduktion haben wir zufällige Daten und keine anonymisierten realen Daten (dies ist einer der Schritte in der Zukunft), daher müssen Sie sie vorsichtig und nicht alle auf einmal rollen.
Bald sollten wir zu Kubernetes gehen (und einige der neuen Produkte wie der
Markt sind bereits anfangs da), sobald wir den Übergangsplan herausgefunden und uns auf alle Details in der Infrastruktur geeinigt haben.
Meine Kollegen und ich werden weiterhin darüber sprechen, wie ein Teil der Arbeit angeordnet ist, denn fast überall kann man unendlich weitermachen. Nun, Sie können unserer Reality-Show folgen (weil alles gerade gebaut wird und sich schnell ändert) und wetten, ob wir es vermasseln oder nicht.