Jaki jest najskuteczniejszy sposób udostępniania kodu między aplikacjami .NET?

15

W naszej pracy mamy kilka różnych aplikacji .net, które mają wiele podstawowych funkcji. Zbudowaliśmy te aplikacje przy użyciu czystej architektury n-tier, ale osiągnęliśmy ten moment, kiedy zdajemy sobie sprawę, że kilkakrotnie zaimplementowaliśmy te same funkcje. Oczywiście narusza to OSUSZANIE i chcielibyśmy to poprawić. Już teraz używamy Nuget do osiągania sukcesów w zakresie powszechnego kodu kleju (podłączanie IoC, rejestrowanie, ustawienia), ale chcielibyśmy również udostępniać nasze dane i warstwy biznesowe między wszystkimi naszymi aplikacjami. Chodzi o to, że interfejs użytkownika będzie obsługiwał tylko te części warstwy biznesowej, których faktycznie potrzebuje.

Z początku wydaje się to prostym problemem, ale ciągły rozwój może spowodować pewne pułapki i nie jesteśmy pewni, jak postępować. Powiedzmy, że tworzymy naszą Jedną warstwę biznesową, aby rządzić nimi wszystkimi. Dla zwięzłości nazywam to „Fundacją”. Przenosimy nasze aplikacje do korzystania z Fundacji i wszystko działa świetnie. Fundacja jest dystrybuowana do lekkich warstw interfejsu użytkownika za pośrednictwem nugetu, a my dobrze wyglądamy. Ale potem zaczynamy dodawać funkcje do naszych aplikacji i wpadamy w kłopoty.

Powiedzmy, że pracujemy nad Projektem A i dodajemy nową funkcję, która wymaga zmian w Foundation. Wprowadzamy zmiany w fundamencie (Foundation-A) i wypychamy je do kanału nuget jako niestabilny pakiet. Projekt A otrzymuje najnowszy pakiet nugetów i wszystko jest w porządku. Tymczasem inny programista pracuje nad Projektem B. Pobiera najnowszą Fundację z kontroli źródła, ale pobiera ją ze stabilnej gałęzi, aby nie zawierała zmian w Projekcie A. Dokonuje zmian i stworzył Foundation-B. I wszystko jest dobrze. Ale potem odkrywamy, że funkcjonalność implementacji Foundation-A i Foundation-B, która faktycznie może współdzielić kod, łączymy je. Tymczasem Foundation-C unosi się tam z własnymi zmianami. W końcu Foundation-B jest gotowa do produkcji, więc ją wypychamy. Ale potem musimy zaktualizować produkcję A, B,

Wydaje się, że to może działać, ale martwimy się pracą z różnymi schematami baz danych i utrzymywaniem synchronizacji między różnymi gałęziami repozytorium Foundation, a także repozytoriami Project A, B i C. Wygląda na to, że prawdopodobnie zajmie to dużo pracy ręcznej, co otwiera możliwość błędów. Chciałbym, aby było to jak najbardziej zautomatyzowane.

Oto stos, którego używamy: C #, TFS z Continuous Integration, Nuget. Nasze aplikacje to różnego rodzaju aplikacje ASP.NET. Jesteśmy gotowi spojrzeć na różne SCM, jeśli to ułatwi sprawę.

Szukam sposobów na utrzymanie rozsądku w Nuget dzięki różnym gałęziom kodu źródłowego. Nie chcemy przypadkowo wypchnąć kodu programistycznego do produkcji, ponieważ odwołujemy się do niewłaściwego pakietu Nuget.

Josh
źródło
Ponadto, jeśli nie jest to dobre forum dla takiej dyskusji, czy ktoś może zaproponować lepsze?
Josh

Odpowiedzi:

9

Wprowadzamy zmiany w fundamencie (Foundation-A) i wypychamy je do kanału nuget jako niestabilny pakiet.

Tutaj zaczyna się twój problem ... Nie rób tego.

Wszelkie zmiany w Foundation v1.0 z natury powinny być cenne dla wszystkich konsumentów Foundation, w przeciwnym razie nie należy ona do Foundation. Tak więc, tworząc pakiet nuget, zrób to jako oficjalną, stabilną wersję Foundation (tj. V1.1), lub w ogóle go nie rób.

Projekt B powinien budować ulepszenia Fundacji w normalny sposób, ale (w dobry sposób zarządzania źródłami) powinien łączyć się ze zmianami łącza (v1.1) przed wypchnięciem stabilnej Fundacji (v1.2) do nugetu.

Inne projekty, które mogą korzystać z ulepszeń Foundation, mogą w razie potrzeby zaktualizować odwołania do modeli użytkowych lub w razie potrzeby trzymać się starszych wersji.

Zgadzam się z @Giedrius ; wydaje mi się, że jest to bardziej kwestia kontroli źródła / rozgałęzienia w tym sensie, że jeśli rozgałęzienie / połączenie Fundacji jest obsługiwane poprawnie, problemy z zarządzaniem pakietami stają się dyskusyjne.

Eric King
źródło
Tak, to ma sens. Problem tkwi w praktycznym zastosowaniu. Podczas aktualizowania programu Foundation for v1.1 chcesz używać tych zmian w Projekcie B podczas opracowywania. Jeśli sposób udostępniania tego kodu odbywa się za pośrednictwem programu Nuget, masz następujące opcje: 1) Opublikuj nowy pakiet Nuget lub 2) Ręcznie skopiuj pliki DLL. Żaden z nich nie wydaje się dobrym wyborem.
Josh
Niektóre z tych problemów można złagodzić dzięki efektywnemu pakietowi testowemu, ale wciąż będzie do przodu i do tyłu w miarę dodawania funkcji.
Josh
@Josh Tak, aktualizacje Fundacji powinny być kompletne i możliwe do przetestowania niezależnie od tego, w jaki sposób Projekt B je wykorzysta (ponieważ przechodzą do wspólnej biblioteki), więc „opublikuj nowy pakiet nuget” jest naturalną drogą. Nie importuj i nie używaj Foundation v.Next w Projekcie B, dopóki nie będzie to stabilny pakiet w nugecie. To wymaga trochę dyscypliny, ale jest o wiele lepsze niż bałagan robienia tego inaczej.
Eric King,
1
Całkowicie rozumiem, co mówisz, ale nie sądzę, żeby to było bardzo realistyczne. W miarę opracowywania funkcji, nawet jeśli cała logika biznesowa i warstwa dostępu do danych są w pełni przetestowane, przed wprowadzeniem do produkcji zostaną wprowadzone modyfikacje. Może zdajesz sobie sprawę, że musisz dodać kolejną właściwość do logiki biznesowej lub właściciel produktu powraca ze zmianami lub wyjaśnieniami. Być może niektóre z twoich uproszczeń były błędne. Takie rzeczy dzieją się cały czas. Jeśli jesteś ograniczony do zablokowania uwolnionej podstawowej logiki, wydaje się to bardzo ograniczone.
Josh
2
Ponieważ robimy to od kilku miesięcy, na tym właśnie się zdecydowaliśmy. Myślę, że zbyt martwiłem się formalnym procesem. Kiedy już zaczęliśmy nad tym pracować, sprawy potoczyły się naprawdę płynnie. Dzięki za wkład.
Josh
4

Zmień swój zduplikowany kod na funkcje, które można zastosować w bardziej abstrakcyjny sposób, i umieść je we własnych bibliotekach lub ramach. Spraw, by były luźno sprzężone i agnostyczne dla architektury, a nigdy nie powinieneś mieć problemu. Jeśli potrzebujesz inspiracji, przestudiuj, w jaki sposób .NET Framework wyodrębnia pojęcia, wykorzystując takie elementy, jak interfejsy, rodzaje i wzorce oprogramowania, takie jak Dispose().

Pamiętaj też, że nie cały zduplikowany kod jest naprawdę powielony; niektóre z nich to kod kleju lub kod, który w przeciwnym razie jest niezbędny do utrzymania architektury, więc nie obawiaj się, że jesteś zbyt SUCHY.

Robert Harvey
źródło
Może nie byłem tak jasny, jak mogłem zadać pytanie. Chodzi o to, co będzie dalej. Zrobiłeś to wszystko, a teraz musisz skutecznie współdzielić kod między różnymi projektami. Ktoś mówi „po prostu użyj do tego nugetu” i brzmi świetnie, dopóki nie przejdziesz do szczegółów i nie napotkasz problemów - na przykład jak zsynchronizować różne zmiany z różnych gałęzi i aplikacji.
Josh
Cóż, zgadzam się z Erikiem Kingiem. Kod fundamentowy należy wypchnąć jako wersję stabilną, a nie niestabilną. Kluczem jest utrzymanie stabilnego API: jeśli wiesz, że podpisy Twoich metod fundamentowych nie zmienią się, możesz bezpiecznie przesłać metody do Fundacji i przefakturować je później, nie niszcząc niczego.
Robert Harvey
4

Ponowne użycie kodu

Istnieje wiele podejść do ponownego użycia kodu, które zyskały przychylność na przestrzeni lat. Każde podejście ma swoje miejsce, a co ważniejsze, jego problemy , ale realne sposoby ponownego wykorzystania kodu w .NET to:

  1. Wspólna biblioteka. Kod, który jest potrzebny w więcej niż jednym miejscu, jest umieszczany we wspólnej bibliotece, a wszystkie inne części bazy kodu mają wówczas pojedyncze odniesienie do tego kodu. Zasadniczą wadą jest to, że kończy się większość projektu w zależności od biblioteki, która zawiera wiele niezwiązanych funkcji. To zły pomysł z punktu widzenia zapewnienia jakości.

  2. Wspólny kod źródłowy. Kod potrzebny w więcej niż jednym miejscu jest zapisywany raz i umieszczany w pliku źródłowym we wspólnej strukturze katalogów. Wszystkie projekty, które potrzebują tego kodu, dołączają ten plik jako jeden ze swoich plików źródłowych. Zapewnia to ponowne użycie kodu, a zalety jednokrotnego zapisu wymagają wielu. Jednak. Jego wadą jest to, że możliwe staje się kompilowanie różnych części projektu z różnymi wersjami tego kodu - co może powodować pewne subtelne wady, które mogą być bardzo trudne do wykrycia i zidentyfikowania przez zapewnienie jakości.

  3. Usługa. Wspólny kod jest implementowany jako usługa, do której mają dostęp inne aspekty. Ma to tę zaletę, że we wdrożeniu będzie pojedyncza usługa i pozwala uniknąć zależności. Wprowadzi jednak opóźnienia i awarie. Takie podejście działa dobrze w dużych rozproszonych produktach, w których wysoka dostępność i odporność na uszkodzenia są już zrozumiane i zarządzane.

Zarządzanie NuGET

Tutaj masz o wiele bardziej interesujący problem. Zarządzanie wieloma konfiguracjami. Radzę tutaj, aby nie zarządzać zróżnicowaną bazą klientów z różnymi wersjami kodu, ale z plikami konfiguracyjnymi. Do zarządzania są co najmniej 3 warstwy danych konfiguracyjnych. Podstawowa (wewnętrzna) konfiguracja produktu, której klient nigdy nie widzi. Domyślne opcje konfiguracji, które klient może zmienić, i ostatnia warstwa opcji konfiguracji, które klient zmienił. Oddzielając te różne warstwy, będziesz mógł wdrażać aktualizacje bez niszczenia konfiguracji klientów.

Michael Shaw
źródło
1

Myślę, że problemem nie jest nuget / kontrola źródła / rozgałęzienie, ale to, co wpada w kod klejenia.

Robert ma miłą odpowiedź, aby zobaczyć cały obraz, polecam zastanowić się, jakie zależności te wspólne narzędzia wprowadzą do każdego projektu:

http://ayende.com/blog/3986/let-us-burn-all-those-pesky-util-common-libraries http://blog.jordanterrell.com/post/CommonUtility-Libraries-Dead.aspx

Najlepszym sposobem na uniknięcie piekła jest otwarcie kodu źródłowego. W ten sposób zaczniesz się martwić, że żadna logika biznesowa nie zostanie upubliczniona, więc żadne konkretne zależności projektowe nie zmienią się w kod kleju, że byłby wystarczająco abstrakcyjny, aby mógł być ponownie użyty przez kogokolwiek, nawet poza twoją firmą - i jeśli to klejenie kod będzie wystarczająco dobry - dostaniesz również wkład społeczności.

Giedrius
źródło
Nie mówię o zarządzaniu kodem kleju. Mamy już na to rozwiązanie i działa dobrze. Mówię o udostępnianiu logiki biznesowej. Na przykład nasze aplikacje zajmują się zarządzaniem organizacjami i ludźmi. Musimy więc stworzyć osobę, a istnieje szereg reguł biznesowych związanych z tym, jak osoba powinna zostać stworzona. Zamiast tworzyć ją kilka razy, chcemy mieć jeden pakiet, który obsługuje wszystko, od budowy obiektu po utrwalenie go, które dzielimy między różnymi projektami które muszą tworzyć ludzi
Josh
0

Rozwiązanie jest proste: stwórz dla niego osobny projekt i zarządzaj nim jako osobną rzecz: własne wymagania, testy, konwencje, dokumentacja, planowanie, ludzie itp. W ten sposób zapewniasz wysoką jakość i możliwe przełomowe zmiany oceniane najpierw, zanim stworzą problem.

Lub jeszcze lepiej: uczyń go „otwartym oprogramowaniem” w swojej organizacji. Tak więc każdy może zmienić kod, ale tylko kilka wybranych osób będzie miało pełne prawa do zatwierdzania. Ci ludzie będą odpowiedzialni za zapewnienie jakości i poprawności funkcji.

Euforyk
źródło