Natknąłem się na jakiś kod (C #, jeśli ma to znaczenie), który ma klasy o tej samej nazwie, ale różniące się przestrzenią nazw. Wszystkie zwykle przedstawiają tę samą logiczną rzecz, ale często są to różne „widoki” tego samego obiektu. Różne przestrzenie nazw są czasami częścią tego samego rozwiązania, a nawet tej samej biblioteki dll.
Mam swoje przemyślenia, ale nie mogłem znaleźć niczego ostatecznego w tej praktyce, co można by uznać za sprytne użycie dostępnych narzędzi lub wzorzec, którego należy unikać.
Pytanie na temat nazewnictwa smerfa dotyczy tego, ale z drugiej strony. Ujednoznacznienie nazw wymagałoby prawdopodobnie arbitralnego i wszechobecnego prefiksu, który to pytanie chciał wyeliminować.
Jakie są wytyczne dotyczące tej praktyki?
FooAdapter
,FooViewer
,FooCalculator
, itd., Ale na pewno nie nazwał to samo. Jednak bez dodatkowych informacji na temat konkretnych klas, o których mówisz, trudno jest udzielić odpowiedzi.Employee
jako przykład. Jest pracownik, który jest dla innych pracowników, jeden dla HR, jeden dla zewnętrznego narażenia. Wszyscy są nazywani „pracownikami” i wszyscy mają różne pomocniki (EmployeeRepository, EmployeeView itp.). Wszystkie są w tej samej bibliotece DLL i chociaż mają wspólne właściwości (nazwa, tytuł), wszystkie różnią się (numer telefonu, wynagrodzenie).Employee
kilkukrotnej pracy z systemami, które modelują , brzmi to tak, jakbyś potrzebował modelu z połączeniem wszystkich atrybutów i zawierał atrybuttype
lubdepartment
. W przeciwnym razie niepotrzebne jest powielanie kodu.Odpowiedzi:
Spróbuję udzielić odpowiedzi przeciwko takiemu użyciu, po obejrzeniu i pracowaniu nad tym również w jednym z moich projektów.
Czytelność kodu
Po pierwsze, należy wziąć pod uwagę, że czytelność kodu jest ważna i ta praktyka jest temu przeciwna. Ktoś czyta fragment kodu i powiedzmy, że ma on funkcję
doSomething(Employee e)
. Nie jest to już możliwe do odczytania, ponieważ ze względu na 10 różnychEmployee
klas istniejących w różnych pakietach będziesz musiał najpierw skorzystać z deklaracji importowej, aby dowiedzieć się, jakie są twoje dane wejściowe.Jest to jednak widok wysokiego poziomu i często mamy pozornie przypadkowe konflikty nazw, o które nikt się nie troszczy ani nawet nie znajduje, ponieważ znaczenie można wywnioskować z pozostałego kodu i pakietu, w którym się znajdujesz. Można by nawet argumentować że lokalnie nie ma problemu, ponieważ oczywiście, jeśli widzisz
Employee
whr
pakiecie, musisz wiedzieć, że mówimy o widoku HR pracownika.Wszystko się jednak rozpada, gdy tylko opuścisz te paczki. Kiedy pracujesz w innym module / pakiecie / etc i potrzebujesz pracy z pracownikiem, już tracisz czytelność, jeśli nie w pełni kwalifikujesz jego typ. Ponadto posiadanie 10 różnych
Employee
klas oznacza, że automatyczne uzupełnianie IDE nie będzie już działać i będziesz musiał ręcznie wybrać typ pracownika.Duplikacja kodu
Ze względu na naturę każdej z tych klas, które są ze sobą powiązane, Twój kod może ulec pogorszeniu z powodu dużej ilości powielania. W większości przypadków będziesz mieć coś takiego jak imię i nazwisko pracownika lub numer identyfikacyjny, który każda klasa musi wdrożyć. Chociaż każda klasa dodaje swój własny widok, jeśli nie będą dzielić podstawowych danych pracowników, skończysz z ogromną masą bezużytecznego, ale kosztownego kodu.
Złożoność kodu
Co może być tak złożone, że możesz zapytać? W końcu każda z klas może to zrobić tak prosto, jak chce. Tym, co naprawdę staje się problemem, jest sposób propagowania zmian. W rozsądnie bogatym w funkcje oprogramowaniu możesz zmieniać dane pracowników - i chcesz to odzwierciedlać wszędzie. Powiedz, że jedna dama właśnie wyszła za mąż i musisz zmienić jej nazwę od
X
naY
z tego powodu. Wystarczająco trudne, aby zrobić to dobrze w każdym miejscu, ale jeszcze trudniejsze, gdy masz wszystkie te odrębne klasy. W zależności od innych wyborów projektowych może to łatwo oznaczać, że każda z klas musi implementować własny rodzaj detektora lub być powiadamianym o zmianach - co w zasadzie przekłada się na współczynnik zastosowany do liczby klas, z którymi masz do czynienia . No i oczywiście więcej duplikacji kodu i mniejszej czytelności kodu. Tego typu czynniki mogą być nie do poznania w analizie złożoności, ale z pewnością są denerwujące, gdy zastosujemy je do rozmiaru bazy kodu.Komunikacja kodowa
Oprócz powyższych problemów ze złożonością kodu, które są również związane z wyborami projektowymi, zmniejszasz również przejrzystość projektu wyższego poziomu i tracisz zdolność do prawidłowej komunikacji z ekspertami w dziedzinie. Kiedy omawiasz architekturę, projekty lub wymagania, nie możesz już swobodnie tworzyć prostych stwierdzeń, takich jak
given an employee, you can do ...
. Deweloper nie będzie już wiedział, coemployee
tak naprawdę znaczy. Oczywiście ekspert w dziedzinie będzie o tym wiedział. Wszyscy robimy. raczej. Ale pod względem oprogramowania nie jest już tak łatwo się komunikować.Jak pozbyć się problemu
Po uświadomieniu sobie tego i jeśli twój zespół zgodzi się, że jest to wystarczająco duży problem do rozwiązania, będziesz musiał znaleźć sposób, aby sobie z nim poradzić. Zazwyczaj nie możesz poprosić swojego menedżera, aby dał całemu zespołowi tydzień wolnego, aby mógł wyrzucić śmieci. Zasadniczo będziesz musiał znaleźć sposób na częściowe wyeliminowanie tych klas, pojedynczo. Najważniejszą częścią tego jest decyzja - z całym zespołem - co
Employee
naprawdę jest. Czy nie integrować wszystkich poszczególnych atrybutów do jednego Boga-pracownika. Pomyśl bardziej o kluczowym pracowniku i, co najważniejsze, zdecyduj, gdzieEmployee
będzie przebywać ta klasa.Jeśli robisz recenzje kodu, szczególnie łatwo jest upewnić się, że problem przynajmniej nie narasta, tj. Zatrzymać wszystkich na właściwej drodze, gdy chcą
Employee
ponownie dodać kolejny . Należy również zadbać o to, aby nowe podsystemy przestrzegały uzgodnionych warunkówEmployee
i nie miały dostępu do starych wersji.W zależności od języka programowania możesz także oznaczyć klasy, które zostaną ostatecznie wyeliminowane, czymś w rodzaju
@Deprecated
pomocy dla zespołu w natychmiastowym uświadomieniu sobie, że pracują z czymś, co trzeba będzie zmienić.Jeśli chodzi o pozbycie się przestarzałych klas pracowniczych, możesz dla każdego indywidualnego przypadku zdecydować, jak najlepiej je wyeliminować, lub po prostu uzgodnić wspólny wzór. Możesz umieścić nazwę klasy i owinąć ją wokół prawdziwego pracownika, możesz użyć wzorów (przychodzi na myśl dekorator lub adapter), lub, lub.
Krótko mówiąc: ta „praktyka” jest technicznie słuszna, ale duszona jest pełnymi ukrytych kosztów, które pojawią się dopiero w dalszej części drogi. Chociaż możesz nie być w stanie natychmiast pozbyć się problemu, możesz od razu zacząć od ograniczenia jego szkodliwych skutków.
źródło
Scala Collection Framework jest tego dobrym przykładem. Istnieją kolekcje, które można modyfikować i niezmienne, a także kolekcje szeregowe i równoległe (aw przyszłości mogą być również dystrybuowane). Istnieją więc na przykład cztery
Map
cechy:plus trzy
ParMap
s:Jeszcze bardziej interesujące:
Zatem
ParMap
rozszerzaParMap
rozszerzaMap
iMap
rozszerzaMap
rozszerzaMap
.Ale spójrzmy prawdzie w oczy: jak inaczej byś je nazwał? To ma sens. Po to są przestrzenie nazw!
źródło
To naprawdę interesujące pytanie, w którym obie zasadniczo przeciwne odpowiedzi są poprawne. Oto prawdziwy przykład tej dyskusji na temat mojego projektu.
Myślę, że do tej pory istnieją dwa bardzo istotne względy, które sprawiłyby, że chcesz iść w jednym lub drugim kierunku, czerpiąc z dwóch odpowiedzi z @Jorg i @Frank:
hr.Employee
ale jednocześnie musisz spojrzeć na uprawnienia przezsecurity.Employee
, będzie to naprawdę denerwujące.Map
klasy implementują ten sam interfejs lub są wzajemnymi podklasami. W tym przypadku dwuznaczność lub „zamieszanie” można z pewnością nazwać dobrą rzeczą, ponieważ użytkownik słusznie może traktować wszystkie implementacje klasy lub interfejsu tak samo… co jest punktem interfejsów i podklas.źródło