Die Übersetzung des Artikels wurde für die Studierenden des Kurses vorbereitet im Bildungsprojekt OTUS.
Sie sollten ein Monorepo wählen, weil das Verhalten, das es in Ihren Teams fördert, Transparenz und kollektive Verantwortung ist, besonders beim Wachstum der Teams. In jedem Fall müssen Sie in Werkzeuge investieren, aber es ist immer besser, wenn das Standardverhalten das ist, das Sie in Ihren Teams sehen möchten.
Warum reden wir darüber?
Matt Klein hat einen Artikel geschrieben (Anmerkung des Übersetzers: Übersetzung auf Habré ). Ich mag Matt, ich denke, dass er sehr klug ist, und Sie sollten seinen Standpunkt lesen. Ursprünglich veröffentlichte er eine Umfrage auf Twitter:
Übersetzung:
An diesem Neujahrstag werde ich darüber streiten, wie absurd Monorepositories sind. Das Jahr 2019 begann unauffällig. In diesem Sinne schlage ich Ihnen eine Umfrage vor. Wer sind die großen Fans? Befürworter:
— Monorepositories
— Rust
— Falsche Umfrage / beide
Meine Antwort war: „Ich bin buchstäblich beide dieser Personen“. Anstatt darüber zu sprechen, wie Rust eine Droge ist, lassen Sie uns herausfinden, warum ich denke, dass er sich über Monorepositories irrt. Ein wenig über mich. Ich bin Chief Technology Officer bei Chef Software. Wir haben etwa 100 Ingenieure, eine Codebasis, die etwa 11–12 Jahre alt ist, und 4 Hauptprodukte. Ein Teil dieses Codes befindet sich in einem Polyrepo (meine Ausgangsposition), ein Teil in einem Monorepo (meine aktuelle Position).
Bevor ich anfange: Jedes Argument, das ich hier anführe, wird auf Repositories beider Arten angewendet. Meiner Meinung nach gibt es keine technischen Gründe, warum Sie einen bestimmten Repositorytyp wählen sollten. Sie können jeden Ansatz zum Laufen bringen. Ich freue mich, darüber zu sprechen, aber ich bin nicht an künstlichen technischen Gründen interessiert, warum das eine besser ist als das andere.
Ich stimme dem ersten Teil von Matts Standpunkt zu:
Weil ein Monorepo im großen Maßstab all dieselben Probleme lösen wird, die auch ein Polyrepo löst, während es Sie gleichzeitig dazu anregt, die Kohäsion Ihres Codes stark zu erhöhen und unglaubliche Anstrengungen erfordert, um die Skalierbarkeit Ihres Versionskontrollsystems zu steigern.
Sie werden mit denselben Problemen konfrontiert, egal ob Sie ein Monorepo oder ein Polyrepo wählen. Wie veröffentlichen Sie Releases? Wie gehen Sie mit Updates um? Rückwärtskompatibilität? Kreuzabhängigkeiten zwischen Projekten? Welche Architekturstile sind akzeptabel? Wie verwalten Sie Ihre Build- und Testinfrastruktur? Die Liste ist endlos. Und Sie werden sie alle lösen, während Sie wachsen. Kostenlosen Käse gibt es nicht.
Ich denke, das Argument von Matt ähnelt den Ansichten, die viele Ingenieure (und Manager), die ich respektiere, teilen. Es kommt aus der Perspektive eines Ingenieurs, der an einer Komponente arbeitet, oder eines Teams, das an einer Komponente arbeitet. Sie hören so etwas wie:
- Die Codebasis ist unübersichtlich – ich brauche diesen ganzen Kram nicht.
- Es ist schwieriger zu testen, weil ich all diesen Kram überprüfen muss, den ich nicht brauche.
- Es ist schwieriger, mit externen Abhängigkeiten zu arbeiten.
- Ich brauche meine eigenen Versionierungssysteme.
Sicherlich sind all diese Punkte gerechtfertigt. Das gilt in beiden Fällen – im Polyrepo habe ich meinen Kram, zusätzlich zu dem, der für den Build erforderlich ist... Möglicherweise benötige ich noch mehr Kram. Deshalb erstelle ich "einfach" Werkzeuge, die das Checkout des gesamten Projekts ermöglichen. Oder ich mache ein falsches Monorepo mit Submodulen. Wir könnten den ganzen Tag darüber diskutieren. Aber ich denke, dass Matts Argument den entscheidenden Grund überspringt, für den ich ziemlich stark für das Monorepo plädiert habe:
Es fördert die Kommunikation und zeigt Probleme auf.
Wenn wir Repositories aufteilen, schaffen wir de facto ein Problem der Koordination und Transparenz. Das entspricht dem, wie wir über Teams nachdenken (insbesondere dem, wie einzelne Mitglieder über sie nachdenken): Wir sind verantwortlich für eine bestimmte Komponente. Wir arbeiten in relativer Isolation. Die Grenzen sind auf mein Team und die Komponente(n) festgelegt, an denen wir arbeiten.
Bei einer komplexeren Architektur kann ein einzelnes Team sie nicht mehr alleine verwalten. Nur sehr wenige Ingenieure haben das gesamte System im Kopf. Angenommen, Sie verwalten eine gemeinsame Komponente A, die von den Teams B, C und D verwendet wird. Team A führt Refactoring durch, verbessert die API und ändert die interne Implementierung. Infolgedessen sind die Änderungen nicht rückwärtskompatibel. Welchen Rat würden Sie geben?
- Finden Sie alle Stellen, an denen die alte API verwendet wird.
- Gibt es Stellen, an denen die neue API nicht verwendet werden kann?
- Können Sie andere Komponenten reparieren und testen, um sicherzustellen, dass sie nicht kaputtgehen?
- Können diese Teams Ihre Änderungen jetzt überprüfen?
Bitte beachten Sie, dass diese Fragen unabhängig vom Typ des Repositories sind. Sie müssen die Teams B, C und D finden. Sie müssen mit ihnen sprechen, herausfinden, wie viel Zeit sie benötigen, und ihre Prioritäten verstehen. Jedenfalls hoffen wir, dass Sie dies tun werden.
Tatsächlich möchte niemand das machen. Es ist viel weniger aufregend, als einfach die verdammte API zu reparieren. Das alles ist menschlich und kompliziert. In einem Poly-Repository können Sie einfach Änderungen vornehmen, diese zur Überprüfung an diejenigen geben, die an dieser Komponente arbeiten (wahrscheinlich nicht B, C oder D), und weitermachen. Die Teams B, C und D können einfach auf ihrer aktuellen Version bleiben. Sie werden aktualisieren, wenn sie Ihre Genialität erkennen!
In einem Monorepo verschiebt sich die Verantwortung standardmäßig. Team A ändert seine Komponente, und wenn es nicht vorsichtig ist, bricht es sofort B, C und D. Das führt dazu, dass B, C und D vor der Tür von A stehen und sich fragen, warum Team A den Build kaputt gemacht hat. Das lehrt A, dass sie meine obige Liste nicht ignorieren können. Sie müssen darüber sprechen, was sie vorhaben. Können B, C und D vorankommen? Was ist, wenn B und C vorankommen können, aber D eng mit den Nebeneffekten des alten Algorithmus verbunden war?
Dann müssen wir darüber sprechen, wie wir aus dieser Situation herauskommen:
- Unterstützung mehrerer interner APIs, während der alte Algorithmus als veraltet gekennzeichnet wird, bis D ihn nicht mehr verwenden kann.
- Unterstützung mehrerer Versionen von Releases, eine mit der alten Schnittstelle, eine mit der neuen.
- Verschieben Sie die Veröffentlichung von Änderungen A, bis B, C und D sie gleichzeitig annehmen können.
Angenommen, wir haben 1, mehrere APIs ausgewählt. In diesem Fall haben wir zwei Code-Stücke. Den alten und den neuen. In einigen Situationen ist das ziemlich praktisch. Wir setzen den alten Code zurück, markieren ihn als veraltet (deprecated) und koordinieren den Zeitplan für seine Entfernung mit dem Team D. Im Grunde genommen ist es für Poly- und Monorepos identisch.
Für die Veröffentlichung mehrerer Versionen benötigen wir einen Branch. Jetzt haben wir zwei Komponenten — A1 und A2. Die Teams B und C verwenden A2, während D A1 verwendet. Wir müssen sicherstellen, dass jede Komponente zur Veröffentlichung bereit ist, denn bevor D weitermachen kann, können sicherheitsrelevante Updates und andere Fehlerkorrekturen erforderlich sein. In einem Polyrepo können wir dies in einem langlebigen Branch verstecken, der gut funktioniert. In einem Monorepo erzwingen wir die Erstellung des Codes in einem neuen Modul. Das Team D muss dennoch Änderungen am "alten" Bestandteil vornehmen. Jeder kann die Kosten sehen, die wir hier tragen — wir haben jetzt doppelt so viel Code, und jegliche Fehlerkorrekturen, die auf A1 und A2 angewendet werden, müssen für beide gelten. Mit dem Ansatz, Branches in einem Polyrepo zu verwenden, wird dies durch Cherry-Picking verborgen. Wir betrachten die Kosten als geringer, da es keine Duplikate gibt. Aus praktischer Sicht sind die Kosten jedoch gleich: Sie werden zwei hauptsächlich identische Codebasen erstellen, veröffentlichen und pflegen, bis Sie eine von ihnen entfernen können. Der Unterschied besteht darin, dass der Schmerz im Monorepo direkt und offensichtlich ist. Das ist noch schlimmer, und das ist gut.
Endlich sind wir beim dritten Punkt angekommen. Die Verzögerung des Releases. Möglicherweise werden die Änderungen, die A vornimmt, das Leben des Teams A verbessern. Wichtig, aber nicht dringend. Können wir einfach aufschieben? Im Monorepository drängen wir darauf, das Artefakt zu fixieren. Natürlich sprechen wir mit Team D darüber. Bleibt einfach bei der alten Version, bis ihr aufholt! Das macht ein Spiel mit den Nerven. Team A arbeitet weiterhin an seiner Komponente und ignoriert die Tatsache, dass Team D eine zunehmend veraltete Version nutzt (das ist das Problem von Team D, sie sind dumm). Währenddessen spricht Team D schlecht über die nachlässige Haltung von Team A zur Code-Stabilität, wenn sie überhaupt darüber sprechen. Monate vergehen. Schließlich beschließt Team D, die Möglichkeit eines Updates zu prüfen, aber die Änderungen in A sind nur zahlreicher geworden. Team A kann sich kaum daran erinnern, wann und wie sie D kaputt gemacht haben. Das Update wird schmerzhafter und dauert länger. Was es weiter unten auf der Prioritätenliste nach unten schiebt. Bis zu dem Tag, an dem wir ein Sicherheitsproblem in A haben, das uns zwingt, einen Branch zu machen. Team A muss in der Zeit zurückgehen, den Moment finden, als D stabil war, das Problem dort beheben und es releasebereit machen. Das ist de facto die Wahl, die die Leute treffen, und sie ist zweifellos die schlechteste. Es scheint gut für sowohl Team A als auch D zu sein, solange wir einander ignorieren können.
Im Monorepository ist das dritte wirklich keine Option. Man muss mit der Situation auf eine von zwei Arten umgehen. Man muss die Kosten von zwei Release-Branches erkennen. Man muss lernen, sich vor inkompatiblen Updates zu schützen. Aber das Wichtigste: man kommt um ein schwieriges Gespräch nicht herum.
Nach meiner Erfahrung, wenn Teams größer werden, gibt es nicht mehr die Möglichkeit, das gesamte System im Kopf zu behalten, und das ist der wichtigste Teil. Man muss die Sichtbarkeit der Unterschiede im System verbessern. Man muss aktiv daran arbeiten, die Teams dazu zu bringen, ihren Blick von ihren Komponenten abzuwenden und die Arbeiten anderer Teams und Nutzer zu betrachten.
Ja, Sie können Werkzeuge erstellen, die versuchen, das Problem der Poly-Repositories zu lösen. Aber meine Erfahrung mit kontinuierlicher Bereitstellung (Continuous Delivery) und Automatisierung in großen Unternehmen sagt mir Folgendes: Das Standardverhalten ohne zusätzliche Werkzeuge ist das Verhalten, das Sie erwarten zu sehen. Das Standardverhalten eines Poly-Repositories ist Isolation, das ist der ganze Sinn. Das Standardverhalten eines Monorepositories ist gemeinsame Verantwortung und Transparenz, das ist der ganze Sinn. In beiden Fällen werde ich ein Werkzeug entwickeln, das hilft, die Ecken abzurunden. Als Leiter werde ich jedes Mal ein Monorepository wählen, weil Werkzeuge die Kultur stärken sollten, die ich möchte, und Kultur entsteht aus kleinen Entscheidungen und der täglichen Teamarbeit.
Nur registrierte Benutzer können an der Umfrage teilnehmen. .
Wer sind die größeren Fanatiker? Befürworter:
Monorepositories
Rust
Falsche Umfrage / beide
33 Benutzer haben abgestimmt. 13 Benutzer haben sich enthalten.
Quelle: habr.com
