Planowanie zależności kompilacji dla potoku
W tej lekcji dowiesz się więcej na temat tworzenia pakietów kodu, aby ułatwić udostępnianie. Dowiesz się, dlaczego należy tworzyć pakiety, rodzaje pakietów, które można tworzyć, gdzie można hostować pakiety i jak można uzyskiwać do nich dostęp podczas ich hostowania. Zapoznasz się również z przechowywaniem wersji pakietów.
Bazy kodu zawsze rosną coraz bardziej złożone. Zespół nie może napisać całego kodu używanego przez aplikację. Zamiast tego zespół zawiera istniejący kod napisany przez innych deweloperów. W aplikacji może istnieć wiele z tych pakietów lub zależności. Ważne jest, aby aktywnie zarządzać tymi zależnościami, aby móc je prawidłowo obsługiwać i upewnić się, że spełniają wymagania dotyczące zabezpieczeń.
Zaewidencjonujmy i zobaczmy, jak działa zespół. Andy zebrał zespół, aby omówić potencjalną zmianę w kodzie, która pomogłaby innemu zespołowi.
Spotkanie zespołu
Andy: Witaj wszystkich. Rozmawiałem z zespołem, który pracuje nad systemem zaplecza dla Space Game. Mogą używać modeli używanych dla witryny internetowej w aplikacji zaplecza, którą planują napisać.
Amita: Co oznaczają modele?
Andy: Jak wiesz, witryna internetowa Space Game jest aplikacją ASP.NET Core. Używa wzorca Model-View-Controller (MVC) w celu oddzielenia danych od sposobu wyświetlania tych danych w interfejsie użytkownika. Myślałem, że możemy utworzyć pakiet zawierający nasze klasy modeli, aby każda aplikacja mogła z nich korzystać.
Amita: Jaki jest dokładnie cel?
Andy: Oba nasze zespoły będą współdzielić tę samą bazę danych. Gra wysyła najlepsze wyniki do bazy danych, a my odczytujemy te wyniki, aby wyświetlić je w rankingu.
Amita: To ma sens. Jak utworzymy ten pakiet?
Andy: Dlatego chciałem porozmawiać z tobą. Mamy kilka możliwości i jestem otwarty na pomysły.
Tim: Chciałbym pomóc, ale najpierw mam kilka pytań. To dla mnie nowość i chcę dowiedzieć się, jak to działa.
Co to jest pakiet?
Pakiet zawiera kod wielokrotnego użytku, z którego inni deweloperzy mogą korzystać we własnych projektach, nawet jeśli go nie napisali.
W przypadku skompilowanych języków pakiet zazwyczaj zawiera skompilowany kod binarny, taki jak pliki .dll na platformie .NET lub pliki klas w języku Java. W przypadku języków, które są interpretowane, a nie kompilowane, takich jak JavaScript lub Python, pakiet może zawierać kod źródłowy.
W obu przypadkach pakiety są zwykle kompresowane do pliku ZIP lub podobnego formatu. Systemy pakietów często definiują unikatowe rozszerzenie pliku, takie jak .nupkg lub .jar, w celu wyczyszczenia użycia pakietu. Kompresja może pomóc skrócić czas pobierania, a także utworzyć pojedynczy plik, aby uprościć zarządzanie.
Pakiety często zawierają również jeden lub więcej plików, które udostępniają metadane lub informacje o pakiecie. Te metadane mogą opisywać przeznaczenie pakietu, określać postanowienia licencyjne oraz zawierać dane kontaktowe autora i informację o wersji pakietu.
Dlaczego warto utworzyć pakiet?
Tworzenie pakietu ma wiele korzyści w porównaniu do duplikowania kodu.
Jednym z powodów, dla których warto utworzyć pakiet zamiast duplikowania kodu jest zapobieganie dryfowi. Gdy kod jest duplikowany, każda kopia może szybko odbiegać od wymagań określonej aplikacji. Migrowanie zmian z jednej kopii do pozostałych staje się trudne. Innymi słowy: traci się możliwość poprawiania kodu w sposób korzystny dla wszystkich.
Pakiety grupują również powiązane funkcje w ramach jednego składnika wielokrotnego użytku. W zależności od języka programowania pakiet może zapewnić aplikacjom dostęp do niektórych typów i funkcji, jednocześnie ograniczając dostęp do szczegółów implementacji.
Kolejny powód, aby utworzyć pakiet, to zapewnienie spójnego sposobu tworzenia i testowania jego funkcji. Gdy kod jest duplikowany, każda aplikacja może kompilować i testować ten kod na różne sposoby. Jeden zestaw testów może obejmować kontrole, z których inny zestaw może przynieść korzyści.
Jednym z kompromisów jest to, że masz inną bazę kodu do testowania i konserwacji przy użyciu pakietu. Podczas dodawania funkcji należy również zachować ostrożność. Ogólnie rzecz biorąc, pakiet powinien zawierać funkcje, które korzystają z wielu rodzajów aplikacji. Na przykład Json.NET to popularny pakiet NuGet dla platformy .NET, który umożliwia pracę z plikami JSON. Json.NET jest składnikiem typu open source, dlatego społeczność może sugerować usprawnienia i zgłaszać problemy.
Jeśli wiele aplikacji może korzystać z tego samego kodu, zalety znacznie przewyższają wady. Istnieje tylko jedna baza kodu, tylko jeden zestaw testów i tylko jeden proces kompilacji, którym trzeba zarządzać.
Jak mogę zidentyfikować zależności?
Jeśli celem jest zreorganizowanie kodu na oddzielne składniki, należy zidentyfikować te elementy aplikacji, które można usunąć, spakować do wielokrotnego użytku, przechowywać w centralnej lokalizacji i wersjonować. Możesz nawet zastąpić własny kod składnikami innych firm, które są oprogramowaniem open source lub licencją.
Istnieje wiele sposobów identyfikowania potencjalnych zależności w bazie kodu. Obejmują one skanowanie kodu pod kątem wzorców ponownego użycia i analizowanie architektury rozwiązania. Oto kilka sposobów identyfikowania zależności:
Zduplikowany kod.
Jeśli niektóre fragmenty kodu pojawiają się w kilku miejscach, oznacza to, że można ponownie użyć kodu. Scentralizuj te zduplikowane fragmenty kodu i odpowiednio je ponownie pakuj.
Wysoka spójność i niskie sprzężenia.
Drugim podejściem jest wyszukanie elementów kodu, które mają wysoką spójność nawzajem i niskie sprzężenie z innymi częściami kodu. W istocie wysoka spójność oznacza utrzymanie części bazy kodu, które są ze sobą powiązane w jednym miejscu. W tym samym czasie niskie sprzężenie polega na rozdzieleniu niepowiązanych części podstawy kodu tak bardzo, jak to możliwe.
Indywidualny cykl życia.
Poszukaj części kodu, które mają podobny cykl życia, który można wdrożyć i wydać osobno. Jeśli ten kod może być obsługiwany przez oddzielny zespół, jest to dobre wskazanie, że możesz spakować go jako składnik poza rozwiązaniem.
Stabilne części.
Niektóre części bazy kodu mogą być stabilne i zmieniane rzadko. Sprawdź repozytorium kodu, aby znaleźć kod o niskiej częstotliwości zmiany.
Niezależny kod i składniki.
Za każdym razem, gdy kod i składniki są niezależne i niepowiązane z innymi częściami systemu, można je potencjalnie odizolować do oddzielnych zależności.
Możesz użyć różnych narzędzi, aby ułatwić skanowanie i badanie bazy kodu. Obejmują one różne narzędzia, które skanują pod kątem zduplikowanego kodu i rysują wykresy zależności rozwiązania do narzędzi, które mogą obliczyć metryki pod kątem sprzężenia i spójności.
Jakie rodzaje pakietów są dostępne?
Każdy język programowania lub struktura zapewnia swój własny sposób tworzenia pakietów. Popularne systemy pakietów zawierają dokumentację dotyczącą sposobu działania procesu.
Być może znasz już te popularne systemy pakietów:
- NuGet: tworzy pakiety bibliotek platformy .NET
- NPM: pakiety bibliotek JavaScript
- Maven: tworzy pakiety bibliotek języka Java
- Docker: pakiety oprogramowania w izolowanych jednostkach nazywanych kontenerami
Gdzie są hostowane pakiety?
Pakiety można hostować we własnej sieci lub użyć usługi hostingu. Usługa hostingu jest często określana mianem repozytorium pakietów lub rejestru pakietów. Wiele z tych usług zapewnia bezpłatny hosting dla projektów open source.
Oto kilka popularnych usług hostingowych dla typów pakietów, które właśnie opisaliśmy:
-
Pakiety NuGet są używane na potrzeby artefaktów kodu platformy .NET. Te artefakty obejmują zestawy .NET i powiązane pliki, narzędzia, a czasami metadane. NuGet definiuje sposób tworzenia, przechowywania i używania pakietów. Pakiet NuGet jest zasadniczo skompresowaną strukturą folderów z plikami w formacie ZIP i ma rozszerzenie nupkg .
-
Pakiet NPM jest używany dla języka JavaScript. Pakiet NPM to plik lub folder zawierający pliki JavaScript i plik package.json opisujący metadane pakietu. W przypadku node.js pakiet zwykle zawiera jeden lub więcej modułów, które można załadować po użyciu pakietu.
-
Narzędzie Maven jest używane w projektach opartych na języku Java. Każdy pakiet ma plik Project Object Model opisujący metadane projektu i jest podstawową jednostką do definiowania pakietu i pracy z nim.
-
Pakiety platformy Docker są nazywane obrazami i zawierają kompletne, samodzielne wdrożenia. Najczęściej obraz platformy Docker reprezentuje składnik oprogramowania, który może być hostowany i wykonywany przez siebie bez żadnych zależności od innych obrazów. Obrazy platformy Docker są warstwowe i mogą być zależne od innych obrazów.
Źródło danych pakietów to Twój serwer repozytorium pakietów. Ten serwer może znajdować się w Internecie lub za zaporą w sieci. Możesz na przykład hostować własne źródła danych NuGet przy użyciu produktów hostingowych, takich jak Azure Artifacts i MyGet. Możesz również hostować pakiety w udziale plików.
Hostowanie pakietów za zaporą umożliwia dołączanie źródeł danych do własnych pakietów. Możesz również buforować pakiety zaufane w sieci, gdy systemy nie mogą łączyć się z Internetem.
Jakie elementy tworzą dobrą strategię zarządzania zależnościami?
Dobra strategia zarządzania zależnościami zależy od tych trzech elementów:
Standaryzacja.
Standaryzacja sposobu deklarowania i rozwiązywania zależności pomoże procesowi zautomatyzowanego wydania pozostać powtarzalnym i przewidywalnym.
Formaty i źródła pakietów.
Każda zależność powinna być spakowana przy użyciu odpowiedniego formatu i przechowywana w centralnej lokalizacji.
Przechowywanie wersji.
Należy śledzić zmiany występujące w czasie w zależnościach, podobnie jak w przypadku własnego kodu. Oznacza to, że zależności powinny być wersjonowane.
Kto ma dostęp do pakietów?
Wiele źródeł pakietów zapewnia nieograniczony dostęp do pakietów. Możesz na przykład pobrać Json.NET z nuget.org bez konieczności logowania się lub uwierzytelniania.
Inne źródła danych pakietów wymagają uwierzytelniania. Dostęp do źródła danych można uwierzytelnić na kilka sposobów. Na przykład niektóre rodzaje źródeł danych wymagają nazwy użytkownika i hasła. Inne kanały informacyjne wymagają tokenu dostępu, który jest zazwyczaj długą serią znaków określających, kim jesteś i do jakich zasobów masz dostęp. Tokeny dostępu można ustawić tak, aby wygasały po danym okresie.
W jaki sposób określane są wersje pakietów?
Schemat wersjonowania zależy od używanego systemu tworzenia pakietów.
Na przykład pakiety NuGet korzystają z wersjonowania semantycznego.
Wersjonowanie semantyczne jest popularnym schematem wersjonowania. Format jest następujący:
główna.pomocnicza.poprawka[-sufiks]
Oto, co oznacza każdy z tych parametrów:
- Nowa wersja główna oznacza wprowadzenie zmian powodujących niezgodność. Aplikacje zazwyczaj muszą aktualizować sposób używania pakietu do pracy z nową wersją główną.
- Nowa wersja pomocnicza wprowadza nowe funkcje, ale jest zgodna z poprzednimi wersjami.
- Nowa poprawka wprowadza poprawki błędów zgodne z poprzednimi wersjami, ale nie nowe funkcje.
- -sufiks jest opcjonalny i identyfikuje pakiet jako wersję wstępną. Na przykład 1.0.0.0-beta1 może zidentyfikować pakiet jako pierwszą kompilację wersji wstępnej w wersji beta dla wersji 1.0.0.
Odwołanie do pakietu powinno zawierać numer wersji.
Oto przykład instalowania pakietu przy użyciu programu PowerShell i określonego numeru wersji:
Install-Package Newtonsoft.Json -Version 13.0.1
Co się stanie w przypadku zmiany pakietu?
W przypadku odwołania się do pakietu z aplikacji zazwyczaj należy przypiąć lub określić wersję tego pakietu, której chcesz użyć.
Wiele platform umożliwia określenie dozwolonych zakresów wersji pakietów do zainstalowania. Niektóre umożliwiają również określenie symboli wieloznacznych, które nazywamy zmienną wersją.
Na przykład w pakiecie NuGet wersja 1.0 oznacza pierwszą wersję równą lub większą niż 1.0. [1.0] określa, że dozwolona jest instalacja tylko wersji 1.0, ale nie nowszych wersji.
Oto kilka innych przykładów:
Notacja: | Wybór: |
---|---|
(1.0,) | Pierwsza wersja większa niż 1 |
[1.0,2.0] | Pierwsza wersja, która jest większa lub równa 1.0, i mniejsza niż lub równa 2.0 |
(1.0,2.0) | Pierwsza wersja większa niż 1.0 i mniejsza niż 2.0 |
[1.0,2.0) | Pierwsza wersja, która jest większa lub równa 1.0, i mniejsza niż 2.0 |
Gdy każdy z opiekunów wyda nową wersję pakietu, możesz ocenić zmiany i przetestować aplikację. Gdy wszystko będzie gotowe, możesz zaktualizować numer wersji pakietu w konfiguracji i przesłać zmianę do potoku kompilacji.
Oto przykład sposobu uwzględnienia pakietu Newtonsoft.Json w projekcie aplikacji C# (csproj). W tym przykładzie określono wersję 13.0.1 tego pakietu:
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>