Czy często stosuje się klasy częściowe w celu osiągnięcia „modułowości”?

24

Niedawno spotkałem się z sytuacją w naszej bazie kodu, w której inny zespół stworzył „klasę boską” zawierającą około 800 metod, podzieloną na 135 plików jako klasę częściową.

Zapytałem o to inny zespół. Chociaż moją reakcją było oderwanie go od orbity, twierdzą, że jest to dobry projekt, powszechna praktyka i że promuje „modułowość” i „łatwość implementacji”, ponieważ nowi programiści mogą polegać na funkcjonalności bez wiedzy o reszcie systemu.

Czy to rzeczywiście powszechna praktyka, czy w jakikolwiek sposób dobry pomysł? Skłaniam się do podjęcia natychmiastowych kroków w celu sprowadzenia tej bestii (a przynajmniej powstrzymania jej dalszego rozwoju), ale jestem skłonny uwierzyć, że się mylę.

Joshua Smith
źródło
6
Zabij to ogniem! Ale poważnie, czy drugi zespół może podać jakieś cytaty dotyczące tej rzekomej powszechnej praktyki?
MattDavey,
1
Żaden. Jestem pewien, że dmuchają dymem, ale staram się z należytą starannością, zanim upuszczę młot.
Joshua Smith,
Jaki jest ich powód, aby nie robić tego cały czas?
JeffO
3
Poproś ich, aby w jednym zdaniu opisali, co łączy ze sobą 800 metod w 135 plikach. Odpowiedź powinna być możliwa dla każdej rozsądnej i rozsądnej klasy.
Carson63000,
3
@ Carson63000 „Wykonuje wszystkie wymagane funkcje projektu.” jest twoje jedno zdanie.
Ryathal

Odpowiedzi:

39

To nie jest w żaden sposób dobry pomysł.

Istnieją częściowe klasy, które pomagają projektantowi formularzy. Używanie ich z jakiegokolwiek innego powodu (i prawdopodobnie do zamierzonego celu, ale to inna sprawa) jest złym pomysłem, ponieważ prowadzi do rozdętych klas, które są trudne do odczytania i zrozumienia.

Spójrz na to w ten sposób: jeśli klasa boga z 800 metodami w jednym pliku, w której wiesz, gdzie wszystko jest, jest złą rzeczą - i myślę, że wszyscy zgodziliby się, że tak jest - to w jaki sposób klasa boga z 800 metodami rozłożone na 135 plików, gdzie nie wiesz, gdzie wszystko może być dobrą rzeczą?

Mason Wheeler
źródło
1
W większości się z tym zgadzam, ale myślę, że mogą zdarzyć się rzadkie przypadki, w których partialmogą być przydatne nawet bez wygenerowanego kodu. Może kiedy masz coś w rodzaju zagnieżdżonej klasy?
sick
1
@svick: Zajęcia częściowe są interesujące, ale zwykle nie są potrzebne. Nie jestem pewien, dlaczego podział klasy na osobne pliki byłby przydatny, gdy istnieją klasy zagnieżdżone. Chyba że chcesz zagnieżdżoną klasę we własnym pliku fizycznym. W takim razie ... maaaaybe Jest OK. ;)
FrustratedWithFormsDesigner
5
Czasami używam klas częściowych do jawnych implementacji interfejsu - szczególnie coś takiego jak System.IConvertible. Jakoś wydaje się czystsze niż stawianie ogromnego #regionu w mojej klasie.
MattDavey,
1
Komentarz klasy zagnieżdżonej jest naprawdę dobrym pomysłem, nawet o tym nie myślałem. Chociaż ... to ma więcej wspólnego z organizacją niż z modułowością
Sheldon Warkentin,
1
„Istnieją częściowe klasy, które pomagają projektantowi formularzy”. Ogólnie poprawne, ale dodałbym „... i inne generatory kodu”. Zgadzam się z resztą twojej odpowiedzi;)
Silas
14

Pytanie brzmiało więc:

Czy to rzeczywiście powszechna praktyka, czy w jakikolwiek sposób dobry pomysł?

Wśród obecnie dostępnych odpowiedzi jest głośne „ nie” . Jest więc kilka innych rzeczy, w których mógłbym się w to wtrącić, takich jak; nawet kod proceduralny może być modułowy i zawierać wszystko, ale zlew kuchenny nie jest tym, w jaki sposób można uzyskać modułowość. Co robi jedna wielka klasa podzielona na częściowe, wszystko składa się na jeden wielki bałagan.

Jednak to pytanie jest czerwonym śledziem do prawdziwej części krytycznej, która została pominięta; ponieważ PO ma również do powiedzenia na temat tej sytuacji:

(...) Podczas gdy moją reakcją jelita było oderwanie go od orbity, nalegają ...

(...) Skłaniam się do podjęcia natychmiastowych kroków w celu sprowadzenia tej bestii na ziemię (a przynajmniej powstrzymania jej dalszego rozwoju), ale jestem skłonny uwierzyć, że się mylę.

WSTRZYMAJ SIĘ!

To jest coś, co sprawi, że mój monokl w przenośni spadnie do mojej figuratywnej filiżanki herbaty.

Byłem w podobnych sytuacjach i powiem ci: NIE . Jasne, możesz rzucić Nuke Hammer of Justice na drużynę, ale zanim to zrobisz, prosimy o humor z następującą zagadką:

Co się stanie, jeśli powiesz zespołowi, że jego kod jest do kitu i odpieprzasz ?

(... lub coś w tym rodzaju, ale mniej obraźliwie, to tak naprawdę nie ma znaczenia, ponieważ będą obrażeni bez względu na to, co zrobisz, jeśli zdecydujesz się na nich w pełni wykorzystać)

Jaka jest obecna sytuacja z bazą kodu? Czy to działa? Wtedy będziesz miał duże problemy z wyjaśnieniem klientom, że ich kod jest do kitu . Bez względu na to, jakie mają powody: dopóki działa, większość klientów nie dba o to, jak zorganizowany jest kod.

Postawcie się także na ich miejscu, co by zrobili? Pozwól, że cię rozbawię następującym możliwym rezultatem:

Członek zespołu nr 1: „Więc ten facet mówi nam, że robiliśmy to źle przez ostatnie lata”.

Członek zespołu nr 2 i nr 3: „Co za palant”.

Wpływowy członek zespołu nr 4: „Nie martw się, po prostu pójdę do kierownictwa i zgłosię to jako prześladowanie”.

Zobacz, co zrobił tam wpływowy członek zespołu nr 4 ? Poszedł do kierownictwa i zmniejszył twoją karmę w towarzystwie. Mógł być Amerykaninem-Włochem, mówiąc wszystkim, żeby się tym nie martwił, ale wtedy byłbym rasistą.

Umieszczenie drużyny, która popełniła błąd, w kącie, pozwalając mu przyznać, że tak długo popełniali błąd, jest również złym pomysłem i prowadzi do tego samego. Stracisz szacunek i odrobinę karmowej polityki biurowej.

Nawet jeśli udało ci się skłonić grupę ludzi do podpisania się na tym, aby „nauczyć zespół lekcji”, pamiętaj, że robisz to dość inteligentnym ludziom, którzy najwyraźniej wykonują pewne czynności. Gdy kod zostanie przepisany / zreformowany / przetworzony / z czymkolwiek, powstają problemy, że będziesz odpowiedzialny za to, jak byłeś strażakiem .

Przeciwstawianie się takim sytuacjom to przede wszystkim gra typu przegrana / przegrana, ponieważ grozi im zaklęcie błędnego kręgu obwiniania. Jest to wynik nieoptymalny dla tej sytuacji. Nawet jeśli wygrasz, nagle przekazujesz bałagan, który zrobił ktoś inny.

Istnieją inne (dużo dojrzałe) sposoby

Byłem kiedyś w podobnej sytuacji, ale potem wziąłem strzałę w kolano. Więc po chwili z tą nagłą strzałką zmieniającą karierę w mojej głowie, dostałem książkę Driving Technical Change autorstwa Terrence'a Ryana . Wymienia kilka wzorców sceptyków, ludzie nie działają na dobre pomysły. Wszystkie najprawdopodobniej mają zastosowanie w przypadku PO:

  • Niedoinformowani - oni naprawdę nie wiedzieli, że istnieją inne sposoby lub po prostu nie rozumieli. Młodsi programiści zwykle pasują do tej kategorii, ale niekoniecznie. (Szczerze mówiąc: spotkałem młodszych programistów, którzy byliby jaśniejsi niż to.)
  • Stado - znali lepsze techniki niż stosowanie klas częściowych, ale nie wiedzieli, że są dozwolone.
  • Cynik - po prostu lubią argumentować, że posiadanie częściowych zajęć jest lepsze niż twój pomysł tylko ze względu na kłótnie. Łatwo to zrobić w tłumie zamiast stać przed tłumem.
  • The Burned - Z jakiegoś dziwnego powodu nie lubią tworzyć nowych klas, najprawdopodobniej uważają to za zbyt trudne.
  • The Time Crunched - Są tak zajęci, że nie mogą zadać sobie trudu, aby naprawić swój kod.
  • Szef - myślą: „Cóż, działa; więc po co zawracać sobie głowę?”
  • Irracjonalni - Ok, są kompletnie szaleni.

Książka zawiera listę strategii i tak dalej, ale w przypadku PO jest to kwestia perswazji. Mocne podejście z faktami na temat anty-wzoru nie wystarczy.

Jeśli w twoim interesie jest podniesienie jakości kodu, przynajmniej daj drużynie obrażającej szansę powtórzyć i naprawić swój bałagan . Osobiście starałbym się ich przekonać, słuchając i zadając wiodące pytania, pozwól im opowiedzieć swoją historię:

  • Co dokładnie robi ich klasa boga?
  • Czy napotkali jakieś problemy? Czy mają jakieś błędy? Zaproponuj rozsądne poprawki, nie każąc im tego robić.
  • Jeśli jesteś użytkownikiem tej klasy boga jako interfejsu API: Czy istnieją prostsze sposoby korzystania z kodu niż całego? Zaproponuj prostsze przykłady, zobacz jak reagują.
  • Czy możesz zamienić niektóre funkcje na inne, bez konieczności pisania funkcji?
  • Czy potrzebują szkolenia? Czy potrafisz przekonać kierownictwo, żeby im to wykonało, lub zorganizował lunch na temat wzorców i praktyk?

... i tak dalej. Daj im małe sugestie, aby mogli iść naprzód. To wymaga czasu i będzie wymagało smaru na łokieć klasy biurowej, ale cierpliwość i ciężka praca to zaleta, prawda?

Łup
źródło
To bardzo wnikliwa odpowiedź. Jeśli jesteś nowym programistą, musisz to zrozumieć. Większość doświadczonych programistów zdaje sobie z tego sprawę po kilku latach, niektórzy nigdy tego nie robią.
FishySwede
6

Strona MSDN Częściowe klasy i metody sugeruje dwie sytuacje do zastosowania klas częściowych:
1. Aby podzielić gigantyczną klasę na wiele oddzielnych plików.
2. Aby mieć miejsce na umieszczenie automatycznie generowanego kodu źródłowego.

2 jest intensywnie wykorzystywany przez Visual Studio (np. Do plików aspx i winforms). Jest to rozsądne użycie klas częściowych.

1 to, co robi twój zespół. Powiedziałbym, że użycie klas częściowych jest całkowicie rozsądnym sposobem na osiągnięcie modułowości, gdy masz klasy gigantyczne, ale posiadanie klas gigantycznych jest samo w sobie nierozsądne. Innymi słowy, posiadanie gigantycznej klasy jest złym pomysłem, ale jeśli zamierzasz mieć gigantyczną klasę, klasy częściowe są dobrym pomysłem.

Chociaż jeśli potrafisz inteligentnie podzielić klasę na osobne pliki, nad którymi mogą pracować różni użytkownicy, czy nie możesz po prostu podzielić jej na osobne klasy?

Brian
źródło
+1 za „czy nie możesz po prostu podzielić go na osobne klasy?”. Właśnie to sugerujemy. Wydaje się, że to zdrowy rozsądek, że pierwotnie tak powinno być.
Joshua Smith
4

W końcu robią normalny rozwój proceduralny bez żadnego OOP. Mają jedną globalną przestrzeń nazw ze wszystkimi metodami, zmiennymi i tym podobne.

Przekonaj ich, że robią to źle, albo stamtąd wynoś się.

Euforyk
źródło
1

Klasa użyteczności zawiera metody, których nie można rozsądnie łączyć z innymi metodami w celu utworzenia klasy. Jeśli masz ponad 800 metod podzielonych na 135 plików, wydaje się prawdopodobne, że ktoś zdołał znaleźć kilka typowych metod ...

To, że masz jedną klasę narzędzi, nie oznacza, że ​​nie możesz mieć innej klasy narzędzi.

Nawet jeśli masz 800 głównie niepowiązanych metod, rozwiązaniem nie jest jedna duża klasa i wiele plików. Rozwiązaniem jest przestrzeń nazw, niektóre podprzestrzenie nazw i wiele małych klas. To trochę więcej pracy (musisz wymyślić nazwę klasy, a także metodę). Ale ułatwi ci życie, gdy nadejdzie czas, aby posprzątać ten bałagan, a tymczasem ułatwi korzystanie z inteligencji (tj. Łatwiejsze określenie, gdzie metoda ma go użyć).

I nie, to nie jest powszechne (większa liczba plików niż liczba bezpłatnych funkcji).

jmoreno
źródło
0

W ogóle mi się to nie podoba. Być może jednak klasy cząstkowe miały sens dla programistów podczas programowania, ponieważ umożliwiały równoczesne opracowywanie tak dużej liczby metod, szczególnie jeśli nie ma między nimi dużej zależności.

Inną możliwością jest zbudowanie tych klas częściowych w celu zmiany automatycznie generowanej klasy podstawowej. W takim przypadku nie należy ich dotykać, w przeciwnym razie niestandardowy kod zostałby usunięty podczas ponownego generowania.

Nie jestem pewien, czy ktokolwiek może to z łatwością utrzymać bez odrobiny nauki. Teraz, jeśli go zabijesz, liczba metod nie spadnie. Dla mnie problemem jest liczba metod i złożoność. Jeśli metody naprawdę należą do klasy, to posiadanie 1 dużego pliku nie ułatwi twojego życia, szczególnie w konserwacji, w rzeczywistości może być bardziej podatne na błędy, aby ujawnić cały ten kod dla głupich błędów, takich jak wyszukiwanie z użyciem dzikiej karty i zamień.

Bądź więc ostrożny i uzasadnij decyzję zabicia. Zastanów się także, jakie testy będą wymagane.

Bez szans
źródło
0

Jest idealnie w porządku z praktycznego punktu widzenia, zakładając, że 135 plików faktycznie grupuje metody podobnie jak tradycyjne klasy. To tylko średnio 6 metod na plik. To zdecydowanie nie jest najpopularniejszy ani tradycyjny sposób projektowania projektu. Próba zmiany spowoduje po prostu mnóstwo problemów i zła sytuacja bez rzeczywistej korzyści. Dostosowanie projektu do standardów OO stworzy tyle problemów, ile rozwiąże. Zupełnie inną sprawą jest to, że wiele plików nie zapewnia żadnych znaczących separacji.

Ryathal
źródło
3
Przeformułowanie kodu proceduralnego w OO generalnie ma ten problem - myślę, że naprawienie tego będzie ogromnym zadaniem i nauczenie zespołu poprawnego kodowania nawet hugera, a ponadto Joshua będzie obwiniony za wszystko, co wydarzy się w przyszłym roku (i później ), jeśli przekona ich do refaktoryzacji. Dlatego nikt nigdy nie naciska zbyt mocno, aby zrobić takie refaktory (przynajmniej nie raz, gdy zobaczy wyniki). Także jeśli uważasz, że to dobry projekt - cóż - ponownie przyjrzyj się tej odpowiedzi za 5 lat i daj nam znać, co myślisz (wydaje mi się, że uczę się wszystkiego, co wiem o projektowaniu co około 5 lat).
Bill K
@BillK, jeśli poczekasz dziesięć lat, prawdopodobnie wiesz, że będzie to obecna filozofia projektowania „w”.
Ryathal
135 plików ogólnie grupuje metody powiązane, ale to (dla mnie) nadal nie czyni tego dobrym pomysłem. Chcę przetestować ten system, ale stukanie / kpowanie z 800-metrowej hydry będzie brzydkim bólem w dupie.
Joshua Smith
@Ryathal nie jest tym, co jest „w środku”, jest to, co uważasz za dobry projekt (z dobrych powodów), a następnie, gdy ćwiczysz i doskonalisz, zdajesz sobie sprawę, że nie jest to tak dobry pomysł, jak myślałeś. Wydaje się, że zdarza się to co około 5 lat, a kiedy zdałem sobie sprawę, że to łagodzi moją reakcję na komentarze niektórych osób, ponieważ zdaję sobie sprawę, że tak naprawdę są doskonałymi projektantami, którzy (podobnie jak my wszyscy) są w trakcie ciągłego doskonalenia naszych praktyk. Jedyny programista, o który się martwię, to taki, który nie sądził, że mógłby poprawić kod napisany 5 lat temu.
Bill K
0

Poza wskazanymi już odpowiedziami, częściowe klasy mogą być przydatne w projektowaniu warstwowym, w którym chcesz zorganizować funkcjonalność, która przecina hierarchię klas w osobne pliki specyficzne dla warstw. Dzięki temu można korzystać z eksploratora rozwiązań do nawigacji po funkcjach poszczególnych warstw (według organizacji plików) oraz widoku klasy do nawigacji po funkcjach poszczególnych klas. Wolałbym używać języka, który obsługuje mixiny i / lub cechy, ale klasy częściowe są rozsądną alternatywą, jeśli są używane oszczędnie i nie powinny zastępować dobrego projektu hierarchii klas.

Sean McDirmid
źródło