Jaki jest sens dzielenia jednej solucji na wiele projektów?

1

Ja chciałem, żeby w jednej solucji było tyle projektów, ile musi na koniec powstać exeków + 1 na bibliotekę przechowującą klasy współdzielone przez resztę projektów.

Szef postanowił, że projektów ma być dużo więcej - bo wtedy łatwiej wielu ludziom na raz pracować na różnych częściach kodu, bo wtedy mamy lepszy podział kodu, itp itd.

Szczerze mówiąc nie widzę, gdzie taka architektura pomaga.

Jeśli chodzi o 'tight coupling', to jedyna korzyść jest taka, że trzeba do osbobnego projektu ładować wiele klas służących do współdzielenia danych między licznymi bibliotekami. W jaki sposób to osłabia 'coupling' ponad takim rozwiązaniem, że owe współdzielone klasy są w plikach znajdujących się w tym samym projekcie, co wszystko, co musi z nich korzystać nie mam pojęcia.

Jeśli chodzi o współpracę wielu ludzi nad kodem jednocześnie, to to chyba tylko utrudnia, gdyż niektóre commity muszą modyfikować więcej plików.

W ogólności wydaje mi się, że podział na wiele projektów i mnożenie bibliotek ponad to, co wypływa z konieczności (czyli to, co musi być współdzielone przez wiele plików wykonywalnych) jest wyłącznie upierdliwością, natomiast nic nie daje.

Ja wiem, jak wiadomo z mojej forumowej historii moją cechą charakterystyczną chyba jest niezrozumienie zasad czystego kodu i ignorowanie ich (aczkolwiek akurat w tej pracy to chyba ja mam najbardziej rygorystyczne podejście do czystego kodu ze wszystkich, z tym jedynym wyjątkiem, o którym teraz piszę - co więcej mówi o podejściu innych do czystego kodu niż o moim), też zdążyłem już wyczytać w internecie chwalenie mnożenia projektów w jednej solucji celem osłabienia coupling, więc może to ja czegoś nie rozumiem?

Poczekałem parę miesięcy przed wysmażeniem niniejszego posta na forum celem zaznajomienia się z tym trybem pracy - może dotrze do mnie, jakie to ma zalety ponad ograniczaniem ilości projektów do niezbędnego minimum - niestety nie dotarło. Dalej zalet nie widzę, natomiast widzę utrudnienia.

Oświeci mnie ktoś?

2

Uswpolnanie kodu odrębnym projektem to jakas pomniejsza zaleta, czasami nawet wada. Po pierwsze projekt jest jednostką deploymentu, można wyodrębnić jakaś sensowna, samodzielna całość i opublikować jako paczkę na swoim Nugecie, jeśli coś jest faktycznie reuzywalne. Po drugie podział na projekty i używanie internal pozwalają na zmuszenie ludzi do nieuzywania rzeczy w miejscach, gdzie tego nie powinno się robić, bo nie ma referencji do projektu, a nawet jeśli jest to klasa jest ukryta.

Oczywiście nie musisz dzielić na projekty. Nie musisz nawet dzielić na klasy, ani na metody.

1

Dodam jeszcze do tego co @Saalin napisał, że jest jeszcze brak konieczności publikowania całej solucji, aby zmienić tylko jedną rzecz. Jeśli podzielisz solucje na projekty i każdy z nich będzie odpowiadał za swój zakres operacji to publikujesz tylko ten co poprawiasz. Na przykładzie systemów ERP jest to najlepiej zobrazować:

  1. Handel - ERP.Handel
  2. Kadry - ERP.Kadry
  3. CRM - ERP.CRM
    ERP = solucja, Handel, Kadry, CRM - projekty. Robisz poprawkę w CRM. Kompilujesz do .dll i wrzucasz update. Nie potrzebujesz robić reinstall całego oprogramowania.

Jeśli projekty w jednej solucji są od siebie zależne to to ma sens, oczywiście do pewnej granicy ale to moje zdanie. Jeśli to jest sposób "porządkowania" projektów, a nie mają ze sobą nic wspólnego, to jest to bardzo głupie.

2

Ja tam wole mieć kilka projektów, które mają po kilkanaście plików niż jeden gdzie jest ich ponad 100.

1

W ogólności wydaje mi się, że podział na wiele projektów i mnożenie bibliotek ponad to, co wypływa z konieczności (czyli to, co musi być współdzielone przez wiele plików wykonywalnych) jest wyłącznie upierdliwością, natomiast nic nie daje.

Najlepiej to w ogóle trzymać wszystko w jednej klasie

1
var napisał(a):

Najlepiej to w ogóle trzymać wszystko w jednej klasie

Saalin napisał(a):

Oczywiście nie musisz dzielić na projekty. Nie musisz nawet dzielić na klasy, ani na metody.

Nie rozumiem tej argumentacji - przecież ona się do tego sprowadza, że nalezy dzielić w nieskończoność, bo przecież można w ogóle nie dzielić.

Analogicznie: Należy obżerać się bez końca i ważyć 500kg, bo przecież można popaść w anoreksję i nic nie jeść.

Rozumiem, że uważacie, że wszystko powinno opierać się o mikroserwisy?

UglyMan napisał(a):

Ja tam wole mieć kilka projektów, które mają po kilkanaście plików niż jeden gdzie jest ich ponad 100.

A podział na foldery nie wystarczy do utrzymania porządku?

AdamWox napisał(a):

Dodam jeszcze do tego co @Saalin napisał, że jest jeszcze brak konieczności publikowania całej solucji, aby zmienić tylko jedną rzecz. Jeśli podzielisz solucje na projekty i każdy z nich będzie odpowiadał za swój zakres operacji to publikujesz tylko ten co poprawiasz. Na przykładzie systemów ERP jest to najlepiej zobrazować:

No ale zaraz, jeśli projekt X zależy od projektu Y i modyfikujemy projekt Y, to czy nie trzeba przekompilować X?

Chyba nie ma gwaracji, że nowa dllka będzie kompatybilna z projektem skompilowanym pod starą?

Czy coś kręcę?

Saalin napisał(a):

Uswpolnanie kodu odrębnym projektem to jakas pomniejsza zaleta, czasami nawet wada.

Alternatywa to mnożenie struktur danych na zasadzie copy paste i uporczywe przepisywanie danych z jednej struktury do drugiej i na odwrót.

Przyznaję się szczerze, to własnie zmusiło mnie do korzystania z automappera.

3
kmph napisał(a):
UglyMan napisał(a):

Ja tam wole mieć kilka projektów, które mają po kilkanaście plików niż jeden gdzie jest ich ponad 100.

A podział na foldery nie wystarczy do utrzymania porządku?

Jednostki realizujące konkretne zadanie powinny być wydzielone do oddzielnych projektów tak, aby dało się je skompilować do oddzielnych dll - to co napisał @AdamWox. Ułatwia to pracę w przypadku deplojowania projektu, jak i trochę optymalizuje, bo system operacyjny może ładować to, co potrzeba.

7

Sens jest mniej więcej taki sam co w przypadku wydzielania kodu do innych klas na podstawie ich odpowiedzialności, grupowanie klas w przestrzeniach nazw itp. tylko że o poziom wyżej. Faktycznie, kiedy mowa o jakiejś małej aplikacji to wydzielanie wszystkiego do wielu projektów może być przerostem formy nad treścią. W większości projektów komercyjnych tak jednak nie jest bo siłą rzeczy będzie tam więcej kodu. Używanie oddzielnych projektów staje się tym bardziej przydatne, im bardziej chcemy właśnie stosować czysty kod i jakieś podejście architektoniczne w tym kierunku- np. onion architecture. Wtedy tymi warstwami w podejściu cebulowym stają się właśnie projekty, co znacznie ułatwia egzekwowanie zasad i pozwala szybko zauważyć ich łamanie. Bo w tym podejściu, stosując regułę że wewnętrzne warstwy nie powinny bezpośrednio zależeć od warstw zewnętrznych a operować na abstrakcjach, projekty odpowiedzialne za warstwy wewnętrzne nie powinny mieć referencji do projektów warstw zewnętrznych. Czyli np. projekt Domain zawierający logikę biznesową nie powinien mieć referencji do warstwy Infrastructure zawierającej implementację zależności, np. dostęp do baz danych, komunikacja z zewnętrznymi serwisami itp. Mając takie projekty od razu mamy czysty podział w solucji, gdzie już na pierwszy rzut oka widać co gdzie jest. Dodatkowo już na etapie kompilacji możemy zobaczyć kiedy złamaliśmy zasadę, bo np. chcemy użyć coś z warstwy infrastruktury w warstwie domeny, a kompilator rzuci nam błąd bo nie będzie miał dostępu do tej klasy- zapewne również da podpowiedź czy dodać referencję do innych projektu. Ale trzymając się zasad będziemy wiedzieć że robimy coś nie tak, nie możemy dodać tej referencji i musimy zrobić to inaczej- zastosować abstrakcję.

Jeśli chodzi o 'tight coupling', to jedyna korzyść jest taka, że trzeba do osbobnego projektu ładować wiele klas służących do współdzielenia danych między licznymi bibliotekami. W jaki sposób to osłabia 'coupling' ponad takim rozwiązaniem, że owe współdzielone klasy są w plikach znajdujących się w tym samym projekcie, co wszystko, co musi z nich korzystać nie mam pojęcia.

Tight coupling pozbywamy się operując na abstrakcjach. Wydzielanie konkretnych implementacji które i tak będziemy używać bezpośrednio do innych projektów w niczym tu nie pomaga, ponieważ kiedy trzeba podmieć implementację to trzeba również zmienić kod który z tego korzysta. W przypadku operowania na abstrakcjach podmieniamy tylko implementację- użytkownik abstrakcji nie musi nic zmienić. Także masz tutaj rację co do wątpliwości- sam fakt że przesuniemy klasę do innego projektu nie sprawia że nagle nie mamy tight coupling.

Jeśli chodzi o współpracę wielu ludzi nad kodem jednocześnie, to to chyba tylko utrudnia, gdyż niektóre commity muszą modyfikować więcej plików.

Nie uważam żeby współpraca wielu ludzi to był argument za albo przeciw- tak czy inaczej pliki trzeba zmieniać, a to że dodatkowo zmieni nam się plik .csproj to żaden problem tak naprawdę. Natomiast również nie widzę jak stosowanie wielu projektów ma tutaj w czymkolwiek pomagać. Więc znów masz rację w swoich wątpliwościach.

Brzmi to tak jakby osoby z którymi masz do czynienia stosowały puste slogany jako argumenty, zamiast naprawdę uzasadnić stosowanie takiego a nie innego podejścia. Tak więc zgadzam się z Tobą w kwestii użytych argumentów, nie zgadzam się natomiast w tym że wydzielaniu kodu do projektów nie pomaga. Powód podałem w pierwszym akapicie.

4

Nie rozumiem tej argumentacji - przecież ona się do tego sprowadza, że nalezy dzielić w nieskończoność, bo przecież można w ogóle nie dzielić.

Trzeba dzielić, ale z głową. Nie ma np sensu wydzielanie routingu od kontrolerów ale domenę od infrastruktury warto wydzielić. Tak samo z modułem realizującym jakiś konkretny wycinek logiki biznesowej czy też stanowiący jakiś kawałek odpowiedzialny za integrację z zewnętrznym komponentem

Rozumiem, że uważacie, że wszystko powinno opierać się o mikroserwisy?

Absolutnie nie, mikroserwisy to chyba ostateczność i one nie sprawdzają się w każdym przypadku.

A podział na foldery nie wystarczy do utrzymania porządku?

Załóżmy, że masz solucję z web API. Dlaczego twoje web API zamiast zajmować się tylko i wyłącznie odbieraniem/ wstępną walidacją/przekazywaniem głębiej requestów i zwracaniem odpowiedzi ma wiedzieć o tym czy pod spodem działa jakieś źródło danych i persystencja oraz mieć wiedzę na temat domeny, integracji z innymi systemami itd?

Nie, foldery do tego nie wystarczają. To przepis na katastrofę typu użycie DbContextu bezpośrednio w widoku.

1
kmph napisał(a):

No ale zaraz, jeśli projekt X zależy od projektu Y i modyfikujemy projekt Y, to czy nie trzeba przekompilować X?

No właśnie niekoniecznie -- zależy jak zależy. :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1