Pytanie Bezbolesny rozwój lokalny, jednocześnie odwołując się do pakietów NuGet


Próbuję publikować i konsumować pakiety pakietów bibliotek klasowych NuGet, jednocześnie unikając problemów związanych z rozwojem lokalnym. Oto przykładowy układ rozwiązania Visual Studio:

| Libraries
  | LibraryA
  | LibraryB
  | LibraryC
| Applications
  | ApplicationD
  | ApplicationE

Jest to pojedyncze rozwiązanie zawierające zarówno biblioteki klas współużytkowanych, jak i wiele aplikacji. Obecnie odniesienia do bibliotek klas przez aplikacje są odniesieniami do lokalnego rozwiązania.

Chciałbym opublikować biblioteki (A, B, C) jako wersjonowane pakiety NuGet, które są następnie przywoływane przez aplikacje w razie potrzeby (D, E). Dzięki temu zmiana na współdzieloną bibliotekę może być niezależna od aktualizacji wdrożonej aplikacji. Bez tego zmiana jednej biblioteki mogłaby spowodować zmianę plików binarnych w kilkunastu lub więcej aplikacjach, które technicznie powinny być przetestowane. Jest to niepożądane, a wersja z NuGet naprawia to.

Powiedzmy jednak, że chcę aktualizować zawartość LibraryA i ApplicationD w tym samym czasie. Aby to zrobić po przejściu na NuGet, będę musiał wprowadzić zmiany w LibraryA, zatwierdzić je, poczekać na utworzenie pakietu, powiadomić ApplicationD, aby zaktualizował swoje odniesienie do LibraryA, a następnie przetestować lub rozwinąć w ApplicationD. Jest to o wiele bardziej skomplikowane niż zwykła praca z obydwoma przy użyciu lokalnych referencji w rozwiązaniu.

Jaki jest lepszy sposób na uzyskanie zarówno solidności wersjonowanych pakietów NuGet dla bibliotek współużytkowanych klas, jak i utrzymanie prostoty programowania, nawet jeśli obejmuje on wiele projektów i aplikacji? Jedyne inne znalezione przeze mnie rozwiązania wiążą się ze zbyt dużym obciążeniem lub bólem głowy, takim jak konieczność ciągłej zmiany odniesień dla ApplicationD między pakietem NuGet a projektem lokalnym.

EDYTOWAĆ: Aby wyjaśnić założenie, pytanie to zakłada:

  • Architektura (rozwiązanie i organizacja projektu) nie może zostać znacząco zreorganizowana
  • Współużytkowane biblioteki zmienią się na nietrywialną częstotliwość
  • Zmiana współużytkowanej biblioteki nie może wymuszać aktualizacji żadnej aplikacji
  • Aplikacje mogą odwoływać się do różnych wersji bibliotek współdzielonych

32
2017-12-30 19:30


pochodzenie


"powiedzmy, że chcę aktualizować zawartość LibraryA i ApplicationD w tym samym czasie" Jeśli jest to problem, zdecydowanie nie polecam używania pakietów NuGet. Zespoły powinny zostać przekształcone w pakiety NuGet, gdy są wystarczająco stabilne, aby rzadko się zmieniać, a proces ich zmiany jest oddzielony od reszty systemu. - Euphoric
@Egohoric Czy masz jakieś rekomendacje dotyczące tego, jak mogę zaktualizować udostępnioną bibliotekę LibraryA, która może być używana przez 50 oddzielnych aplikacji, bez konieczności wymuszania nowej wersji na wszystkich 50 aplikacjach i wywoływania wielu testów regresji? Stabilność, o której wspominasz, jest dobrym ideałem, do którego możesz dążyć, ale nie jest praktyczna w tym przypadku. Jestem oczywiście otwarty na inne podejścia / narzędzia. - jmsb
Myślę, że problemem jest fakt, że masz bibliotekę, która nie jest stabilna i jest zależna od 50 innych. Najlepszym sposobem jest przebudowanie architektury w celu zwiększenia stabilności, a następnie stworzenie osobnego rozwiązania, z własnymi wymaganiami, żądaniami zmian i planem rozwoju. A jeśli naprawdę masz 50 aplikacji, które zależą od tego, to nie będzie to wielki wysiłek. - Euphoric
Możesz mieć referencje NuGet specyficzne dla wersji. Użytkownik powinien upewnić się, że współużytkowany obiekt LibraryA ma rozsądny schemat wersjonowania, a każda z aplikacji, które go używają, może zostać uaktualniona (lub nie), gdy będzie gotowa. Musisz tylko upewnić się, że wszystkie wydania są dostępne, tak jak robi to nuget.org. - Andrew
@Andrew Yep! Możliwość odwoływania się do konkretnych wersji jest po to, dlaczego używam NuGet, aby rozwiązać ten problem w pierwszej kolejności. - jmsb


Odpowiedzi:


Niestety, tak naprawdę nie ma sposobu, aby mieć najlepsze z obu światów. Wewnętrznie w mojej firmie, udało nam się go nieco złagodzić szybkim procesem budowania / wdrażania, który przeciwdziała większości obciążeń, zawsze odwołując się do pakietu NuGet. Zasadniczo wszystkie nasze aplikacje używają innej wersji tej samej biblioteki hostowanej w lokalnym repozytorium NuGet. Ponieważ używamy własnego oprogramowania do budowania, wdrażania i hostowania pakietów, to dość szybko aktualizujemy bibliotekę, a następnie aktualizujemy pakiet NuGet w innym rozwiązaniu. Zasadniczo najszybszy przepływ pracy, jaki znaleźliśmy, jest następujący:

  1. Wprowadź zmiany w bibliotece
  2. Automatycznie twórz i wdrażaj wersję biblioteki zwiększoną o 1 do wewnętrznego kanału NuGet
  3. Zaktualizuj pakiet NuGet w aplikacji konsumenckiej

Cały proces od odprawy do aktualizacji zużywającego się projektu zajmuje około 3 minut. Repozytorium NuGet ma również serwer symbol / źródło, który pomaga ogromnie przy debugowaniu.


3
2017-12-30 21:23



używasz 1.2.3-pre <Build> do tego, lub znaleźć, że najłatwiej trzymać się z 1.2. <kompilacji> i być mniej surowo o tym wszystkim? - steve
Nigdy nie używamy wersji przedpremierowej, która w przeszłości powodowała problemy. Jednak aby poradzić sobie z podobnym przypadkiem, alternatywą byłoby promowanie pakietu z kanału rozwojowego do kanału produkcyjnego lub coś podobnego. - John Rasch


Mimo że wymaga to trochę pracy, możliwe jest ręczne edytowanie plików .csproj w celu skonfigurowania referencji warunkowych poprzez dodanie Condition atrybut do odpowiednich odniesień.

EDYTOWAĆ Przeniosłem te warunki do ItemGroups, ponieważ wygląda na to, że działa mój wspomniany kod produkcyjny, i wspomniano o tym, że jest to możliwy problem w VS 2013.

<ItemGroup Condition="'$(Configuration)' == 'Debug Local'">
    <!-- Library A reference as generated by VS for an in-solution reference, children unmodified -->
    <ProjectReference>...
</ItemGroup>

<ItemGroup Condition="'$(Configuration)' == 'Debug NuGet'">
    <!-- Library A reference as generated by NuGet, child nodes unmodified --> 
    <Reference Include="LibraryA">...
</ItemGroup>

Umożliwiłoby to w przypadku projektów D & E konfigurację "Debug NuGet" kontra "Debug Local", które odwołują się do bibliotek w różny sposób. Jeśli masz wiele plików rozwiązania, które mają swoje konfiguracje odwzorowane na odpowiednie konfiguracje w projektach w obrębie, użytkownik końcowy nigdy nie zobaczy więcej niż "Debugowanie" i "Zwolnij" dla większości operacji, ponieważ są to konfiguracje rozwiązania, i tylko trzeba otworzyć pełne rozwiązanie do edycji projektów A, B i C.

Teraz, jeśli chodzi o usuwanie projektów A, B i C z drogi, możesz ustawić je w folderze oznaczonym jako subrepo (zakładając, że używasz SCM, który obsługuje to, na przykład Git). Większość użytkowników nigdy nie musiałaby pobierać subrepo, ponieważ nie mają dostępu do projektów ABC, a zamiast tego chwyta się z NuGet.

Utrzymanie mądry, mogę zagwarantować, że VS nie będzie edytować odniesienia warunkowe i będzie ich przestrzegać podczas kompilacji - przeszedłem zarówno VS 2010 i 2013 (EDYTOWAĆ: Wersja profesjonalna, chociaż robiłem to samo z ekspresowym) z tymi samymi referencyjnymi projektami referencyjnymi w pracy. Miejcie na uwadze, że w VS można wprowadzać odwołania do wersji, co czyni NuGet jedynym miejscem, z którego należy utrzymywać wersję, i że można to zrobić jak każdy inny pakiet NuGet. Chociaż mam nadzieję, NIE przetestowałem, czy NuGet będzie walczył z referencjami warunkowymi.

EDYTOWAĆ Warto też zauważyć, że referencje warunkowe mogą powodować ostrzeżenia o brakujących bibliotekach DLL, ale w rzeczywistości nie utrudniają kompilacji ani uruchamiania.


16
2017-12-30 19:42



Dzięki, te referencje warunkowe są przydatne, o których warto wiedzieć. Jednak po przekonwertowaniu istniejących odniesień, wszystkie przyszłe odniesienia do bibliotek będą musiały być ręcznie skonfigurowane przy użyciu tego samego podwójnego podejścia, prawda? Obawiam się, że trudno byłoby to utrzymać. - jmsb
To możliwe przerwanie strony NuGet, ale łatwe w VS. Włączę tę informację do mojej odpowiedzi. - David
Wiem, że po prostu zrobił coś podobnego w VS2013, że przynajmniej dla <Reference> elementy, IDE nie obsługuje z wdzięcznością wielu odniesień do tej samej biblioteki, nawet jeśli tylko jedno odwołanie jest aktywne z powodu Condition atrybuty. Nie wiem, czy posiadanie obu <ProjectReference> i a <Reference> przedstawia ten sam problem. Jeśli tak, można temu zapobiec, tworząc właściwości specyficzne dla konfiguracji i używając wartości właściwości w tagu zamiast tworzenia wielu znaczników. - Andrew
@Andrew, patrząc na to, wygląda na to, że różne referencje w projekcie produkcyjnym są w środku <ItemGroup Consition=...> elementy, więc odpowiednio zaktualizuję swoją odpowiedź - David
Wydaje mi się, że pamiętam, próbując tego samego, i to nie pomogło. Ale znowu nie wiem, czy ProjectReference będzie wykazywać to samo zachowanie, i to było tylko uciążliwe ostrzeżenie. - Andrew


Wiem, że to jest dwuletni post, ale znalazłem go w tej samej sytuacji. Również znalazłem to dla VS2015, jestem w trakcie testowania tego. Wrócę i odpowiednio poprawię swoją odpowiedź.

https://marketplace.visualstudio.com/items?itemName=RicoSuter.NuGetReferenceSwitcherforVisualStudio2015


6
2018-05-09 14:25



Udało nam się wykorzystać ten moduł do naszych celów. Tworzy plik odwzorowania dla każdego csproj (MyProj.nugetreferenceswitcher), który zasadniczo zawiera listę różnych odniesień z ich mapowaniem projektu / nugetu. Pozwala na łatwe przełączanie się między trybami, ale zajmuje to kilka sekund / minut. - JayR
chcę to zrobić więcej niż raz :) - ironic
Ta wtyczka nie działa, nawet ta dla VS2017 - Jeremy F.