Sugestia modelu rozgałęzienia dla tego samego projektu dla wielu klientów

11

Mamy bardzo duży projekt, który obejmuje kilka aplikacji, które stanowią bazę dla różnych klientów.

Każdy klient ma własną personalizację produktu, różne kamienie milowe, różne wymagania itd., Dzięki czemu każdy projekt będzie ewoluował niezależnie w zależności od własnych potrzeb.

Rdzeń projektu jest podobny (ale nie równy) w każdym projekcie, a organizacja jest tworzona tak, że istnieją zespoły, które obsługują każdego klienta niezależnie (ale w razie potrzeby z komunikacją między nimi). Do tej pory nie byłem w stanie znaleźć żadnego schematu, który odpowiadałby naszym potrzebom, przeszukując internet lub wpadając na genialny pomysł :)

Do tej pory pracowaliśmy nad tym, aby produkt był odpowiedni dla wszystkich potrzeb, z określonymi gałęziami dla potrzebnych zmian, ale chociaż produkt ma dobrą architekturę, powoli staje się dużym problemem. Oto główne problemy, przed którymi stoimy:

  • Różne kamienie milowe dla każdego klienta: co oznacza, że ​​każdy zespół musi produkować wersje w różnym czasie, bez reszty zmian wpływających na stabilność lub ich produkt.
  • Różne wymagania, które mogą, ale nie muszą, wpływać na rdzeń systemu w niektórych przypadkach.
  • Duże zespoły (ponad 20 członków zespołu)
  • Obsługa błędów w systemie: Co robisz, jeśli zespół wykryje błąd w swoim projekcie, który może wpłynąć na innych klientów?

Uwaga: mówimy o projekcie, który ma 10 + M LOC.

Uwaga: używamy Team Foundation System, Visual Studio 2008 i C # (głównie).

Wszelkie sugestie, źródła lub pomysły dotyczące rozwiązania tej sytuacji? Czy jest jakiś model na rynku, który ma podobny problem?

Jorge Córdoba
źródło

Odpowiedzi:

9

W rzeczywistości sugerowałbym, że nie potrzebujesz modelu rozgałęziającego, a raczej kompletne kompleksowe podejście do radzenia sobie z wielowymiarowymi ograniczeniami w odniesieniu do systemu bez rozgałęziania. W praktyce uważam, że zawsze będzie problem z utrzymaniem wielu systemów, które mają pewne podobieństwa, ale będą ewoluować inaczej w gałęziach, więc lepiej jest przekształcić wszystko w jeden system, który ewoluuje jako całość, ale składa się z różnych konfiguracji. Może się to wydawać zbyt uproszczone, ale w tej dziedzinie prowadzone są szeroko zakrojone badania z wieloma udanymi zastosowaniami przemysłowymi.

Nazwą tego podejścia jest Software Product Lines, a czasem Inżynieria linii produktów . Na stronie linii produktów oprogramowania CMU SEI :

Linia oprogramowania (SPL) to zestaw systemów intensywnie korzystających z oprogramowania, które mają wspólny, zarządzany zestaw funkcji spełniających określone potrzeby określonego segmentu rynku lub misji i które zostały opracowane ze wspólnego zestawu podstawowych zasobów w określony sposób .

Kluczową ideą jest to, że każde wymaganie, każdy kamień milowy, każda funkcja (kluczowy termin w tej dziedzinie) jest częścią kompletnego systemu na najwyższym poziomie. Rzeczywiste systemy wdrożone u różnych klientów są zasadniczo zbiorem funkcji. Każda funkcja nie jest jednak tylko fizycznym komponentem wtłoczonym w system, jest zdefiniowana jako zależna od innych funkcji lub włączona przez inne funkcje (tak, że wybierając funkcję, możesz automatycznie uwzględnić jej zależności itp.)

Zamiast utrzymywać wszystkie te gałęzie, ostatecznie utrzymujesz jeden system wraz z zestawem konfiguracji specyficznych dla klienta.

W praktyce migracja do takiego podejścia z bardzo dużym systemem może być trudna, a nawet niemożliwa, ale nawet wtedy przydatne będzie zbadanie metod zastosowanych w SPL, aby ocenić, jakie mogą być zastosowane metody (przynajmniej częściowo) zintegrowane z twoją pracą.

Niektóre dodatkowe przydatne linki:

Deckard
źródło
11

Kiedy zaczynałem przy pierwszej pracy, pracowałem nad podobnymi projektami (ale na mniejszą skalę) i napotkaliśmy te same problemy. Zaczęliśmy od ogólnych wymagań dotyczących obsługi rozwiązań dla wszystkich klientów, ale było to możliwe tylko w tym samym punkcie, w którym wymagania stały się sprzeczne. Zrobiliśmy to, co sugerujesz i uruchomiliśmy oddzielną wersję dla każdego klienta. Nawet to rozwiązało problem z wymaganiami i dostosowaniem, staje się koszmarem konserwacyjnym przy rozwiązywaniu problemów i zmian globalnych.

Ponieważ kod w aplikacji był tylko podobny, scalanie zmian z jednej wersji klienta do drugiej było bardzo złożone i wymagało ponownego przetestowania każdej wersji osobno (nie mieliśmy automatycznych testów!). Często powodował błędy regresji w różnych wersjach. W twoim scenariuszu może być jeszcze gorzej, ponieważ jeden zespół rozwiąże błąd w swojej wersji, a drugi będzie musiał połączyć tę zmianę z wersji, której nie w pełni rozumieją (byliśmy jednym zespołem pracującym nad wszystkimi wersjami).

Jeśli nie masz wspólnego globalnego rdzenia, będziesz mieć takie same problemy. Zanim opuściłem firmę, stwierdziliśmy, że nasze podejście było nieprawidłowe. Aby wesprzeć taki scenariusz programowania, potrzebowaliśmy wspólnego rozszerzalnego rdzenia i modelu danych, który będzie konfigurowalny z górnych, dostosowywalnych warstw aplikacji. Taki rdzeń powinien być wykorzystywany jako podstawa do indywidualnych dostosowań każdego klienta i utrzymywany przez oddzielny zespół. Będzie to wiązało się z pewnymi komplikacjami w zakresie zarządzania, ponieważ wielu menedżerów projektów będzie potrzebowało zasobów od tego samego zespołu, ale jest to jedyny sposób na spójność architektury, kontrolę całego procesu i synchronizację wersji.

Ladislav Mrnka
źródło
2

Mogę być podstawą, ale myślę, że to, z czym masz do czynienia w jądrze twojego systemu, to ten sam problem, z którym wszyscy spotykają się, kto używa komponentów i musi utrzymywać i obsługiwać różne wersje ich oprogramowania, a każda z tych wersji wymaga innego zestawu wersji komponentów.

Na przykład

  • wersja 1.0 wymaga biblioteki A 1.0, biblioteki B 2.0, biblioteki C 5.6
  • wersja 2.0 wymaga biblioteki A 1.0, biblioteki B 3.7, biblioteki C 5.7
  • wersja 3.0 wymaga biblioteki A 1.2, biblioteki B 3.7, biblioteki C 5.8

Sposób rozwiązania problemu z komponentami polega na posiadaniu wszystkich wersji bibliotek w naszym systemie kontroli wersji (budujemy je na źródle) oraz na zmuszaniu każdego projektu do używania odpowiedniej wersji biblioteki poprzez zmianę ścieżki wyszukiwania (ścieżka odniesienia?).

W Delphi można to łatwo zrobić za pomocą pliku konfiguracyjnego projektu (pod kontrolą źródła), jeśli nie potrzebujesz bibliotek w czasie projektowania, w przeciwnym razie jest to wykonalne, ale staje się nieco trudniejsze, ponieważ musisz zmienić IDE Delphi, aby użyć poprawna wersja również (pliki rejestracyjne (.reg) pod kontrolą wersji mogą przyjść tutaj na ratunek).

Rozwiązaniem dla twojego podstawowego systemu może być traktowanie go jako biblioteki, dla której utrzymujesz różne wersje. Co w istocie oznacza, że ​​musisz skonfigurować różne gałęzie dla każdej wersji. Aplikacja klienta może następnie użyć właściwej „wersji” systemu podstawowego, odwołując się do odpowiedniego folderu oddziału systemu podstawowego.

Tam, gdzie zależności dla twojego systemu podstawowego byłyby podobne do powyższego przykładu, zależności dla twoich aplikacji klienckich wtedy „po prostu” mają dodatkowe odniesienie: wersję twojego podstawowego systemu.

Dodatkową zaletą wielu aplikacji klienckich jest to, że możesz wybrać, kiedy zacząć korzystać z konkretnej wersji systemu podstawowego i że nie wpływają na ciebie zmiany w systemie podstawowym, których nie jesteś jeszcze gotowy do użycia dla określonej aplikacji klienckiej.

Marjan Venema
źródło