Jakie jest najlepsze podejście do nazywania klas?

92

Wymyślenie dobrych, precyzyjnych nazw klas jest niezwykle trudne. Wykonane dobrze, sprawia, że ​​kod jest bardziej samodokumentujący i dostarcza słownictwa do rozumowania kodu na wyższym poziomie abstrakcji.

Klasom, które implementują określony wzorzec projektowy, można nadać nazwę opartą na dobrze znanej nazwie wzorca (np. FooFactory, FooFacade), a klasy, które bezpośrednio modelują koncepcje domeny, mogą wziąć swoje nazwy z domeny problemowej, ale co z innymi klasami? Czy jest coś takiego jak tezaurus programisty, do którego mogę się zwrócić, gdy brakuje mi inspiracji i chcę uniknąć używania ogólnych nazw klas (takich jak FooHandler, FooProcessor, FooUtils i FooManager)?

Henz
źródło
6
to jest doskonałe pytanie! Zamknięcie go jest nieuzasadnione IMHO, lepiej byłoby przenieść witrynę programistów.
Timofey
1
Zgadzam się, powinien zostać ponownie otwarty lub przeniesiony
ftl
Widziałem wiele z tych doskonałych pytań „zamkniętych przez casperOne”. Może mógłby służyć jako delecjonista w Wikipedii?
Perlator

Odpowiedzi:

59

Zacytuję kilka fragmentów z Implementation Patterns autorstwa Kenta Becka:

Prosta nazwa nadklasy

„[…] Nazwy powinny być krótkie i mocne. Jednak, aby nadać im precyzję, czasami wydaje się, że wymaga kilku słów. Wyjściem z tego dylematu jest wybranie mocnej metafory do obliczenia. Mając na uwadze metaforę, nawet pojedyncze słowa niosą ze sobą bogatą sieć skojarzeń, powiązań i implikacji. Na przykład we frameworku rysunkowym HotDraw moim pierwszym imieniem dla obiektu na rysunku było DrawingObject . Ward Cunningham pojawił się wraz z metaforą typograficzną: rysunek jest jak wydrukowana, rozłożona strona. Elementy graficzne na stronie to figury, więc klasa stała się Figure . W kontekście metafory Figure jest jednocześnie krótsza, bogatsza i dokładniejsza niż DrawingObject ”.

Kwalifikowana nazwa podklasy

„Nazwy podklas mają dwa zadania. Muszą komunikować, jaka jest klasa i czym się różnią. […] W przeciwieństwie do nazw u korzeni hierarchii, nazwy podklas nie są używane prawie tak często w rozmowie, dzięki czemu mogą być wyraziste kosztem zwięzłości. [...]

Nadaj podklasom, które służą jako korzenie hierarchii, własne proste nazwy. Na przykład HotDraw ma klasę Handle, która przedstawia operacje edycji figury, gdy figura jest zaznaczona. Nazywa się po prostu Handle, pomimo rozszerzenia rysunku . Istnieje cała rodzina uchwytów i najlepiej nadają się one do nazw takich jak StretchyHandle i TransparencyHandle . Ponieważ Handle jest korzeniem własnej hierarchii, zasługuje na prostą nazwę nadklasy bardziej niż kwalifikowaną nazwę podklasy.

Kolejnym problemem w nazewnictwie podklas są wielopoziomowe hierarchie. […] Zamiast ślepo dołączać modyfikatory do bezpośredniej nadklasy, pomyśl o nazwie z perspektywy czytelnika. Jakiej klasy powinien wiedzieć, że są takie zajęcia? Użyj tej nadklasy jako podstawy dla nazwy podklasy. "

Berło

Dwa style nazywania interfejsów zależą od tego, jak myślisz o interfejsach. Interfejsy jak klasach bez implementacji powinny być nazwane tak, jakby były zajęcia ( Proste Nadklasa Nazwisko , kwalifikowana Podklasa Nazwa ). Jednym z problemów związanych z tym stylem nazewnictwa jest to, że dobre nazwy są używane, zanim przejdziesz do nazewnictwa klas. Interfejs o nazwie File wymaga klasy implementacji o nazwie ActualFile , ConcreteFile lub (fuj!) FileImpl(sufiks i skrót). Ogólnie rzecz biorąc, ważne jest informowanie, czy mamy do czynienia z konkretnym, czy abstrakcyjnym obiektem, mniej ważne jest to, czy abstrakcyjny obiekt jest zaimplementowany jako interfejs, czy jako nadklasa. Odradzanie rozróżnienia między interfejsami i nadklasami jest dobrze> obsługiwane przez ten styl nazewnictwa, co pozwala na późniejszą zmianę zdania, jeśli okaże się to konieczne.

Czasami nazywanie konkretnych klas jest po prostu ważniejsze dla komunikacji niż ukrycie użycia interfejsów. W tym przypadku nazwy interfejsów należy poprzedzić literą „I”. Jeśli interfejs nosi nazwę IFile , klasę można po prostu nazwać File .

Aby uzyskać bardziej szczegółową dyskusję, kup książkę! To jest tego warte! :)

Marcio Aguiar
źródło
1
„Czasami nazywanie konkretnych klas jest po prostu ważniejsze dla komunikacji niż ukrycie korzystania z interfejsów. W tym przypadku nazwy interfejsów należy poprzedzić literą„ I ”. Jeśli interfejs nosi nazwę IFile, klasę można po prostu nazwać File”. To takie zabawne, ponieważ w książce Roberta C. Martina Clean Code dowiedziałem się, że wolelibyśmy nazwać implementacje jako FileImpl, zamiast nazywać interfejs jak IFile, ponieważ nie chcemy, aby klient wiedział, że obsługujemy je berło. A w książce ^ są cytaty z książki, do której się
odnosisz
39

Zawsze wybieraj MyClassA, MyClassB - pozwala to na ładne sortowanie alfa.

Żartuję!

To dobre pytanie i coś, czego nie tak dawno temu doświadczyłem. Reorganizowałem swoją bazę kodów w pracy i miałem problemy z tym, gdzie umieścić, co i jak to nazwać.

Prawdziwy problem?

Zajęcia robiłem za dużo. Jeśli spróbujesz zastosować się do zasady pojedynczej odpowiedzialności , wszystko zbiegnie się w całość o wiele ładniej. Zamiast jednej monolitycznej klasy PrintHandler , możesz podzielić ją na PageHandler , PageFormatter (i tak dalej), a następnie utworzyć główną klasę Printer, która łączy to wszystko razem.

W mojej ponownej organizacji zajęło mi to trochę czasu, ale skończyło się na binowaniu wielu zduplikowanych kodów, uzyskałem znacznie bardziej logiczną bazę kodu i nauczyłem się piekielnie dużo, jeśli chodzi o myślenie przed wrzuceniem dodatkowej metody do klasy: D

Chciałbym nie zaleca jednak oddanie rzeczy jak nazwy wzorca do nazwy klasy. Interfejs klas powinien to uczynić oczywistym (jak ukrycie konstruktora dla singletona). Nie ma nic złego w nazwie ogólnej, jeśli klasa służy celowi ogólnemu.

Powodzenia!

Rob Cooper
źródło
Zgadzam się nie umieszczać nazw wzorców w nazwie klasy. Co się stanie, jeśli wzorzec zmieni się później, gdy zmieni się implementacja?
thegreendroid
2
Wolałbym raczej umieścić w nazwie nazwę wzoru. Czemu? Ponieważ jeśli muszę spojrzeć na szczegóły implementacji (jak prywatny konstruktor), aby dowiedzieć się, że jest to singleton, to spowalnia mnie jako czytelnika i w zależności od mojego poziomu umiejętności, mogę nie dowiedzieć się, że to tak naprawdę część klasowa ogólnego wzoru. Pojedynczy i prywatny konstruktor jest wątpliwym przykładem, ale w przypadku bardziej skomplikowanych wzorców (Visitor, Adapter itp.) Staje się to dość skomplikowane. Jeśli wzór się zmieni, istnieje
podejrzenie,
28

Doskonała mowa Josha Blocha o dobrym projekcie API zawiera kilka dobrych rad:

  • Zajęcia powinny robić jedną rzecz i robić to dobrze.
  • Jeśli klasa jest trudna do nazwania lub wyjaśnienia, prawdopodobnie nie jest to zgodne z radą zawartą w poprzednim podpunkcie.
  • Nazwa klasy powinna natychmiast komunikować, czym jest klasa.
  • Dobre nazwy prowadzą do dobrych projektów.

Jeśli Twoim problemem jest nazwanie ujawnionych klas wewnętrznych, być może powinieneś skonsolidować je w większą klasę.

Jeśli twoim problemem jest nazwanie klasy, która wykonuje wiele różnych rzeczy, powinieneś rozważyć podzielenie jej na wiele klas.

Jeśli to dobra rada dla publicznego API, to nie zaszkodzi żadnej innej klasie.

Josh Segall
źródło
1
link do filmu na youtube youtube.com/watch?v=aAb7hSCtvGw
Andrew Harry,
12

Jeśli utkniesz z nazwą, czasem dobrą strategią jest nadanie jej jakiejś na wpół rozsądnej nazwy z zobowiązaniem do jej późniejszej zmiany.

Nie daj się nazwać paraliżowi. Tak, imiona są bardzo ważne, ale nie są na tyle ważne, by tracić na nie ogromne ilości czasu. Jeśli nie możesz wymyślić dobrego imienia w 10 minut, przejdź dalej.

Simon Johnson
źródło
9

Jeśli nie przychodzi mi na myśl dobre imię, prawdopodobnie zadałbym pytanie, czy istnieje głębszy problem - czy zajęcia służą jakiemuś celowi? Jeśli tak, nazwanie go powinno być dość proste.

Luke Halliwell
źródło
3

Jeśli twój "FooProcessor" naprawdę przetwarza foos, nie wahaj się nadać mu tej nazwy tylko dlatego, że masz już BarProcessor, BazProcessor itp. W razie wątpliwości, oczywiste jest najlepsze. Inni programiści, którzy muszą odczytać Twój kod, mogą nie używać tego samego tezaurusa, co Ty.

To powiedziawszy, bardziej szczegółowość nie zaszkodzi w tym konkretnym przykładzie. „Proces” to dość szerokie słowo. Czy to naprawdę jest na przykład „FooUpdateProcessor” (który może się zmienić na „FooUpdater”)? Nie musisz być zbyt "kreatywny", jeśli chodzi o nazewnictwo, ale jeśli napisałeś kod, prawdopodobnie masz dość dobre pojęcie o tym, co robi, a czego nie.

Na koniec pamiętaj, że sama nazwa klasy to nie wszystko, co ty i czytelnicy kodu musicie kontynuować - zwykle w grze są również przestrzenie nazw. Często mogą one zapewnić czytelnikom wystarczający kontekst, aby wyraźnie zobaczyć, do czego służy Twoja klasa, nawet jeśli jej nazwa jest dość ogólna.

McKenzieG1
źródło