Beschleunigen der Zusammenarbeit und agiler Entwicklung mit Komponenten

Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2019

Ihr Produkt ist erfolgreich, Ihre Organisation wächst, und es ist an der Zeit, Ihre Codebasis so hochzuskalieren, dass sie diesem Erfolg entspricht. Wenn Sie die letzten 2 bis 3 Teams skalieren, die in einer einzigen Codebasis auf einem einzelnen Produkt arbeiten, stellen Sie sich möglicherweise Fragen wie:

  • Wie können meine Teams wiederverwendbare Komponenten effizient freigeben?

  • Gewusst wie es meinen Featureteams ermöglichen, schnell zu durchlaufen, ohne die Arbeit anderer Teams zu durchlaufen?

  • Gewusst wie meinen Teams Autonomie geben, um in dem Tempo zu durchlaufen, das für sie geeignet ist?

Teams können jederzeit davon profitieren, diese Fragen zu berücksichtigen. Wenn Sie ein etabliertes Team mit einer Legacy-Codebasis sind, stellen Sie möglicherweise dieselben Fragen, wie Sie aufgefordert werden, mehr Wert zu liefern, schneller als je zuvor. Unabhängig von Ihrer Situation kann die Komponentenisierung Ihnen helfen, eine Codebasis zu erstellen, die auf die Größe Ihres Teams und die Geschwindigkeit der heutigen Entwicklung skaliert wird.

In diesem Artikel erfahren Sie, wie die binäre Komposition über Azure Artifacts Ihnen dabei helfen kann, Ihre externen Abhängigkeiten, Ihre Open-Source-Software und Ihre isolierten freigegebenen Komponenten zu verwalten und freizugeben.

Komponenten und Zusammensetzung

Die Komponentenisierung ist der Prozess der Aufteilung und Organisation Ihres Produkts in unterschiedliche Komponenten. Die meisten .NET-Projekte verfügen bereits über einige Komponenten in Form der Projekte innerhalb der Lösung. Beispielsweise kann eine einfache Website aus einer Front-End-Komponente, einer Datenzugriffskomponente und einer Modell-/Datenspeicherkomponente bestehen.

Quellkomposition

Wenn Ihr Produkt wächst, kann die Lösung und das Projektmodell ineffizient werden. Die Integration von Änderungen dauert länger und ist schwieriger zusammenzuführen, der Build wird langsamer, und Komponenten beginnen, von einem einzelnen Projekt auf mehrere Projekte zu wachsen. Im Allgemeinen ist dies der Punkt, an dem Teams beginnen, diese Gruppen verwandter Projekte in separate Lösungen zu zerbrechen.

Sobald Sie eine einzelne Lösung auswachsen haben, wird die Komponentenkomponente zu einer interessanten Frage. Wir haben mit der Quellkomposition begonnen, auf die jede Komponente über einen Projektverweis in Visual Studio verwiesen wird. Die Quellkomposition ist möglich, solange sich Ihre Quelle in einer einzigen Kompositionsgrenze befindet: eine einzelne Lösung innerhalb eines einzelnen Quell-Repositorys.

Leider beginnen diese Projektverweise zu zerbrechen, wenn mehrere Lösungen beteiligt sind. An diesem Punkt, wenn Lösung A von Lösung B abhängt, muss sie auf die erstellten Binärdateien (z. B. DLLs) verweisen, die von Lösung B erzeugt werden - dies ist binäre Zusammensetzung.

Dementsprechend müssen diese Binärdateien jetzt erstellt und zur Lösung A bereitgestellt werden, bevor sie erfolgreich erstellt werden kann. Hierzu gibt es verschiedene Möglichkeiten:

  • Sie können sie in die Quellcodeverwaltung einchecken. Je nach Quellcodeverwaltungssystem können Binärdateien schnell die Größe Ihres Repositorys, das Auschecken verlangsamen und die allgemeine Repositoryleistung beschleunigen. Wenn Sie mit der Arbeit in Verzweigungen beginnen, können mehrere Teams die gleiche Binärdatei in verschiedenen Versionen einführen, was zu anspruchsvollen Zusammenführungskonflikten führt.

  • Alternativ können Sie sie auf einer Dateifreigabe hosten, obwohl dieser Ansatz bestimmte Einschränkungen aufweist. Dateifreigaben fehlen einen Index für schnelle Nachschlagevorgänge, und sie bieten keinen Schutz vor dem Überschreiben einer Version in Zukunft.

Paketkomposition

Pakete befassen sich mit vielen Herausforderungen beim Verweisen auf Binärdateien. Anstatt sie in die Quelle einzuchecken, können Sie eine Lösung B als NuGet-Pakete erstellen, die eine andere Lösung A dann nutzen kann. Wenn Lösung A und Lösung B als separate Komponenten Standard beibehalten werden, bei denen gleichzeitige Änderungen in A und B selten sind, ist die Paketkomposition eine hervorragende Möglichkeit, die Abhängigkeit von A von B zu verwalten. Die Paketkomposition ermöglicht B das Iterieren von eigenen Schwankungen, während A frei ist, Aktualisierungen von B zu erhalten, wenn der Zeitplan von A zulässt, und es ermöglicht mehreren Teams, Lösung B zu durchlaufen und zu aktualisieren, ohne die Lösung A (oder andere Lösungen C oder D) zu beeinflussen.

Die Paketkomposition ist jedoch mit einer eigenen Reihe von Herausforderungen verbunden. Bisher haben wir ein einfaches Beispiel untersucht. Das Skalieren der Paketkomposition bis zur Größe einer großen Codebasis (etwa Windows oder Bing) kann zu einer Reihe von Herausforderungen führen:

  • Das Verständnis der Auswirkungen von änderungen in einer Komponente, die in der Abhängigkeitsdiagramm niedrig ist, wird sehr schwierig.

  • Rautenabhängigkeiten können zu einem bedeutenden Straßenblock für Agilität werden. In einer Rautenabhängigkeit hängen Komponenten B und C beide von einer freigegebenen Komponente A ab, während Die Komponente D sowohl von B als auch von C abhängt. Wenn Komponente A eine neue Version mit unterbrechungsrelevanten Änderungen einführt, wenn B-Updates für die neue Version jedoch nicht vorgenommen werden, kann D keine B-Updates übernehmen, ohne einen Abhängigkeitskonflikt einzuführen. In diesem einfachen Beispiel kann eine Unterhaltung mit C alles sein, was erforderlich ist, um den Konflikt zu lösen. In einem komplexen Diagramm können Diamanten jedoch schnell unlösbar werden.

  • Wenn Änderungen auf zwei Komponenten angewendet werden müssen, die mit Paketen zusammengesetzt sind, wird der Iterationszyklus des Entwicklers erheblich langsamer. Wenn Komponente A aktualisiert wird, müssen sie neu erstellt, neu verpackt und erneut veröffentlicht werden. Anschließend muss Komponente B auf die kürzlich veröffentlichte Version aktualisiert werden, um die in Komponente A vorgenommene Änderung zu überprüfen. Durch die Verwendung der Quellkomposition, die das gleichzeitige Erstellen von Komponente A und B ermöglicht, wird ein schnellerer Iterationszyklus für Entwickler bereitgestellt.

Was sollten Sie verwenden?

Im Allgemeinen haben wir gesehen, dass große Teams am erfolgreichsten sind, wenn sie eine Mischung aus Kompositionsstrategien verwenden. Um zu ermitteln, was für Ihre Codebasis am besten geeignet ist, erstellen Sie zunächst die Abhängigkeitsdiagramm Ihres Produkts, und beginnen Sie, Ihre Komponenten in Gruppen verwandter Komponenten zu gruppieren.

Beispielsweise verfügen Sie möglicherweise über eine Sammlung von Komponenten, die Ihr Framework bilden, und eine andere Gruppe von Komponenten, die Ihren benutzerorientierten Dienst bilden. Stellen Sie dann für jede Gruppe verwandter Komponenten die folgenden Fragen:

  • Kann ich häufige Check-Ins in den Sätzen erwarten, die ich für meine Teams eingerichtet habe?

  • Ist ein einzelnes Team für den gesamten Satz verantwortlich?

  • Gibt es für einen einzelnen Satz einen gemeinsamen Freigaberhythmen?

In unserer Erfahrung haben wir festgestellt, dass die Verwendung der Quellkomposition für verwandte Projekte von einem einzelnen Team oder einer Gruppe verwandter Teams am effektivsten ist. Umgekehrt erweist sich die binäre Zusammensetzung für Open-Source-Software, externe Abhängigkeiten (Komponenten von entfernten oder isolierten Teams) als vorteilhaft und unabhängige gemeinsam genutzte Komponenten.