Czy wystarczy, aby metody można było rozróżnić tylko według nazwy argumentu (a nie typu), czy lepiej nazwać ją bardziej jednoznacznie?
Na przykład T Find<T>(int id)
vs T FindById<T>(int id)
.
Czy jest jakiś dobry powód, aby nazwać go bardziej jawnie (tj. Dodając ById
), zamiast utrzymywać tylko nazwę argumentu?
Jednym z powodów, o których mogę myśleć, jest to, że podpisy metod są takie same, ale mają inne znaczenie.
FindByFirstName(string name)
i FindByLastName(string name)
T Find<T>(string name)
lub(int size)
jak planujesz rozwiązać nieuniknione problemy?ID
przedmiotem, a nie tylkoint
. W ten sposób uzyskaj sprawdzenie czasu kompilacji, czy nie używasz identyfikatora dla int lub viceversa w jakiejś części kodu. I dzięki temu możesz miećfind(int value)
ifind(ID id)
.Odpowiedzi:
Pewnie, że istnieje dobry powód, aby nazwać to bardziej jednoznacznie.
To nie jest przede wszystkim metoda definicja , która powinna być oczywista, ale metoda wykorzystanie . I choć
findById(string id)
ifind(string id)
to zarówno oczywiste, istnieje ogromna różnica pomiędzyfindById("BOB")
afind("BOB")
. W pierwszym przypadku wiesz, że literał losowy jest w rzeczywistości Id. W tym drugim przypadku nie jesteś pewien - może to być imię lub coś zupełnie innego.źródło
findById(id)
vsfind(id)
. Możesz przejść w obie strony.double Divide(int numerator, int denominator)
wykorzystywane w metodzie:double murdersPerCapita = Divide(murderCount, citizenCount)
. Nie można polegać na dwóch metodach wykorzystujących tę samą nazwę zmiennej, ponieważ istnieje wiele przypadków, w których tak nie jest (lub gdy tak jest, jest to złe nazewnictwo)Zalety FindById () .
Future pokryć : Jeśli początek
Find(int)
, a później trzeba dodać inne metody (FindByName(string)
,FindByLegacyId(int)
,FindByCustomerId(int)
,FindByOrderId(int)
, etc), ludzie tacy jak ja spędzają wieki szukającFindById(int)
. Naprawdę nie jest to problem, jeśli możesz i zmieniszFind(int)
go,FindById(int)
gdy stanie się to konieczne - w przyszłości sprawdzimy, czy jest to konieczne .Łatwiejszy do odczytania .
Find
jest całkowicie w porządku, jeśli wygląda na to połączenierecord = Find(customerId);
JeszczeFindById
jest nieco łatwiejszy do odczytania, jeśli tak jestrecord = FindById(AFunction());
.Spójność . Możesz konsekwentnie stosować wzór
FindByX(int)
/FindByY(int)
wszędzie, aleFind(int X)
/Find(int Y)
nie jest możliwe, ponieważ powodują konflikty.Zalety Find ()
Find
jest prosty i jednoznaczny, a obokoperator[]
tego jest jedną z 2 najbardziej oczekiwanych nazw funkcji w tym kontekście. (Niektóre popularne alternatywy byciaget
,lookup
lubfetch
, w zależności od kontekstu).FindById(int id)
, możemy łatwo usunąć redundancję, zmieniając ją naFind(int id)
, ale istnieje kompromis - tracimy trochę przejrzystości.Alternatywnie możesz uzyskać zalety obu , używając silnie napisanych identyfikatorów:
Implementacja
Id<>
: Mocne wpisywanie wartości identyfikatora w C #Komentarze tutaj, a także w powyższym linku, wzbudziły wiele obaw związanych z
Id<Customer>
tym, co chciałbym rozwiązać:CustomerId
iOrderID
są różnymi typami (customerId1 = customerId2;
=> dobra,customerId1 = orderId1;
=> zła), ale ich implementacja jest prawie identyczna, więc możemy zaimplementować je za pomocą kopiowania wklej lub metaprogramowania. Podczas gdy dyskusja na temat ujawniania lub ukrywania generyków ma wartość, o tyle metaprogramowanie jest tym, do czego służą.DoSomething(int customerId, int orderId, int productId)
. Silnie wpisane identyfikatory zapobiegają również innym problemom, w tym zapytaniu o OP.int aVariable
. Łatwo jest stwierdzić, że identyfikator jest przechowywanyId<Customer> aVariable
, a nawet możemy stwierdzić, że jest to identyfikator klienta.String
to tylko opakowaniebyte[]
. Zawijanie lub enkapsulacja nie stoi w sprzeczności z silnym pisaniem na klawiaturze.operator==
aoperator!=
także, jeśli nie chcesz polegać wyłącznie naEquals
:.
źródło
Innym sposobem myślenia na ten temat jest użycie bezpieczeństwa typu języka.
Możesz zaimplementować metodę taką jak:
Gdzie FirstName jest prostym obiektem, który otacza ciąg zawierający imię i oznacza, że nie może być pomyłki co do tego, co robi metoda, ani argumentów, z którymi jest wywoływana.
źródło
string name = "Smith"; findById(name);
jest możliwe, jeśli używasz ogólnych typów nieopisowych.DWORD
LPCSTR
klony itp. i myśli „to int / string / itp.”, dochodzi do momentu, w którym spędzasz więcej czasu na rozwijaniu swoich narzędzi niż na projektowaniu kodu .int
S są często sumowane, mnożone itp., Co nie ma znaczenia dla identyfikatorów; tak bym zrobićID
odrębny odint
. Może to uprościć interfejs API, zawężając to, co możemy zrobić, biorąc pod uwagę wartość (np. Jeśli mamyID
, będzie działać tylko zfind
, a nie np.age
Lubhighscore
). I odwrotnie, jeśli przekonamy się, że dużo konwertujemy lub piszemy tę samą funkcję / metodę (np.find
) Dla wielu typów, to znak, że nasze rozróżnienia są zbyt dobreGłosuję za wyraźną deklaracją, taką jak FindByID .... Oprogramowanie powinno być tworzone na potrzeby zmian. Powinien być otwarty i zamknięty (SOLID). Tak więc klasa jest otwarta na dodanie podobnej metody find, np. FindByName .. itd.
Ale FindByID jest zamknięty, a jego implementacja jest testowana jednostkowo.
Nie będę sugerować metod z predykatami, są one dobre na poziomie ogólnym. Co zrobić, jeśli na podstawie pola (ByID) masz pełną inną metodologię.
źródło
Dziwi mnie, że nikt nie sugerował użycia predykatu, takiego jak:
Dzięki takiemu podejściu nie tylko zmniejszasz powierzchnię swojego API, ale także dajesz większą kontrolę użytkownikowi, który go używa.
Jeśli to nie wystarczy, zawsze możesz rozszerzyć go na swoje potrzeby.
źródło