Kiedy klasa lub moduł powinien znajdować się w osobnym zestawie / bibliotece DLL?

22

Czy istnieją jakieś wytyczne dotyczące decydowania, kiedy klasa powinna znajdować się we własnym zestawie / bibliotece DLL? Często widzę dwie szkoły myślenia:

1) Każda „grupa” klas należy do własnej biblioteki DLL, np. Repozytoria, usługi, DTO, infrastruktura itp.

2) Wszystko powinno znajdować się w jednej bibliotece DLL, ale oddzielone przez przestrzenie nazw / foldery, np. Mieć bibliotekę DLL „Core” z dodatkowymi przestrzeniami nazw, np. Core.Repositories, Core.Services, Core.DTO itp.

W pracy zbieramy wszystko w jednym Zgromadzeniu o nazwie „Biznes”. Istnieje kilka folderów, ale nie ma prawdziwej separacji - obiekty biznesowe (z logiką, z których niektóre nie powinny nawet być klasami) są beztrosko umieszczane w folderze „BusinessObjects”. Rzeczy używane w więcej niż jednej klasie znajdują się w folderze „Core”. Narzędzia znajdują się w folderze „Narzędzia”, infrastruktura dostępu do danych to folder „Dane” - masz pomysł.

W przypadku nowego modułu, nad którym pracuję, chcę / muszę mieć oddzielną warstwę dostępu do danych (pomyśl podstawową implementację repozytorium), ale nie chcę po prostu wrzucać jej do folderu „BusinessObjects” z innymi 160 (!) zajęcia tam. Jednocześnie martwię się o utworzenie nowej biblioteki klas, ponieważ wszyscy są przyzwyczajeni do upychania klasy w jednej bibliotece; folder / przestrzeń nazw może jednak działać.

Wayne Molina
źródło

Odpowiedzi:

12

Uważam, że lepiej jest mieć więcej projektów (tj. Zespołów) z klasami podzielonymi według kategorii w każdym projekcie niż jeden projekt ze wszystkimi tymi klasami w osobnych przestrzeniach nazw. Powinieneś dążyć do tego, aby twoje projekty były wielokrotnego użytku i reprezentowały różne warstwy w aplikacji. Następnie możesz ponownie wykorzystać te projekty w przyszłych aplikacjach bez konieczności dołączania całej masy niepotrzebnych klas.

Na przykład, w oparciu o to, o czym wspomniałeś, zdecydowanie miałbym następujące projekty:

  • Rdzeń
  • Dane
  • Domena (lub BusinessObjects)
  • Usługi
  • Narzędzia (lub pomocnicy)
Bernard
źródło
2
Niestety nie mogę głosować za odpowiedzią. Właśnie tego zaleca nasza firma. W rezultacie, mając około 6 projektów, np. Dla średniej wielkości strony internetowej, nie możesz utrzymywać hierarchii katalogów opartej na cechach itp. W rezultacie otrzymujesz sześć projektów, z których każdy jest dużym bałaganem niemożliwym do poruszania się po stosie plików. Zwykle ludzie, którzy to zalecają, nigdy nie wypróbowali opartej na cechach struktury projektów w relatywnie dużych projektach (przepraszam za bezpośredni osąd, ale radzenie sobie z rezultatami takiego przeciążenia jest prawdziwym bólem). Odpowiedź jammycakes zaleca prawidłowe podejście.
alehro
Podział klas według kategorii prowadzi do bałaganu w dużych projektach. Podziel je według funkcji / aspektu. Wtedy przestrzenie nazw będą po prostu odzwierciedlały ten podział. A cała struktura będzie odzwierciedlać leksykon ze specyfikacji. Podział klas według kategorii przypomina dodawanie skrótów typu do nazw zmiennych - zwykle jest to nieprzyjemny zapach.
alehro
Łatwo jest nadużywać obu proponowanych rozwiązań (tj. Zbyt wielu projektów lub zbyt niewielu). Znalezienie właściwej równowagi, w której należy pamiętać o możliwości ponownego użycia i niskim sprzężeniu, powinno prowadzić do czegoś bardziej testowalnego i łatwego w utrzymaniu.
Bernard
16

„Wujek Bob” Martin z Clean Code, sława SOLID Principles przedstawiła tutaj trzy zasady :

  • Zasada równoważności ponownego użycia wydania: Granulatem ponownego użycia jest granulat wydania.
  • Wspólna zasada zamknięcia: Klasy, które zmieniają się razem, są pakowane razem.
  • Wspólna zasada ponownego użycia: Klasy używane razem są pakowane razem.

Ogólna zasada jest taka, że ​​liczba projektów w swoim rozwiązaniu powinna być jak najniższa. Podziel je tylko wtedy, gdy musisz to zrobić, aby zaimplementować jedną lub więcej konkretnych historii użytkowników lub jeśli posiadanie jednego zestawu powoduje mierzalne problemy z wydajnością (zazwyczaj gdy osiągną rozmiar kilku megabajtów).

jammycakes
źródło
2
+1 te zasady są dobrymi wytycznymi. Rozdzielenie klas na różne zespoły wprowadza dodatkowe rozważania projektowe (na przykład, które wersje każdego zestawu mogą ze sobą współpracować), zwiększając ogólną bazę kodu, zwiększając w ten sposób koszty utrzymania.
Ben
1
Jednak oprócz tych zasad dodam, że często dobrym pomysłem jest pakowanie kodu, który prawdopodobnie zostanie zastąpiony lub zamieniony w oddzielnym zestawie. Ten kod skorzysta z dodatkowych uwag potrzebnych do połączenia oddzielnych zespołów, a oddzielenie go ułatwi testowanie i porównywanie różnych wersji.
Ben
4
Tak, ale upewnij się, że istnieje prawdziwy wymóg jego wymiany lub wymiany. Na przykład frameworki i biblioteki stron trzecich - pakiety NuGet i tym podobne - zwykle muszą obsługiwać wiele kontenerów IOC i wiele ram rejestrowania. Z drugiej strony, w przypadku kodu obszaru użytkownika takie abstrakcje są zwykle czysto spekulacyjne, niepotrzebne i utrudniają, i nigdy nie sprawdzają się w rzadkich przypadkach, kiedy są rzeczywiście potrzebne.
jammycakes
„Podziel je tylko wtedy, gdy musisz to zrobić, aby zaimplementować jedną lub więcej konkretnych historii użytkowników lub jeśli posiadanie jednego zestawu powoduje mierzalne problemy z wydajnością (zwykle gdy osiągną rozmiar kilku megabajtów)”. - całkowicie przypadkowa i
nieuzasadniona
1
Przykro mi, ale co dokładnie jest w tym „całkowicie przypadkowe i nieuzasadnione”? Tę odpowiedź opublikowałem po latach pracy nad rozwiązaniami, które zostały podzielone na znacznie więcej projektów, niż to konieczne bez żadnego innego powodu, niż właśnie to, jak należy to robić. Wynik? Czasy kompilacji lodowców i piekielna zależność od piekła (szczególnie w czasach sprzed NuGet). Podział rzeczy na osobne zespoły wiąże się z pewnym kosztem, a jeśli nie ma żadnej korzyści, która zrównoważyłaby ten koszt, oznacza to jedynie kradzież z firmy.
jammycakes
4

Niektóre inne zasady przewodnie, z którymi pracuję:

  • Czy uważasz, że ponownie użyjesz tego kodu w innych projektach? W przypadku jednej grupy powiązanych aplikacji internetowych mieliśmy jeden moduł związany z kontem użytkownika, z którego korzystały wszystkie aplikacje, ponieważ wszystkie one używały tego samego modelu dla kont użytkowników i loginów. Zrobiłem podobne rzeczy z bibliotekami geometrii i matematyki i ponownie użyłem ich w wielu aplikacjach, po prostu włączając DLL.

  • Czy chcesz mieć możliwość modyfikowania / wdrażania tego kodu bez ponownego wdrażania / ponownej kompilacji całego projektu? Czasami przydało się po prostu przebudowanie modułu, wdrożenie i ponowne uruchomienie aplikacji internetowej.

Wygląda na to, że w Twoim przypadku podstawowe i ogólne Repozytorium może być ponownie przydatne w przyszłości, warto, jeśli to możliwe, podzielić je na nową bibliotekę DLL.

FrustratedWithFormsDesigner
źródło
Myślę, że twoja druga uwaga jest naprawdę rozsądna. Podział na moduły powinien pomóc w rozwoju / testowaniu i kompilacji.
WM