Jak i dlaczego decydować między metodami nazewnictwa z prefiksami „get” i „find”

48

Zawsze mam problem z ustaleniem, czy powinienem nazwać określoną metodę zaczynającą się od getSomethingkontra findSomething.

Problem polega na tworzeniu pomocników dla źle zaprojektowanych interfejsów API. Dzieje się tak zwykle podczas pobierania danych z obiektu, który wymaga obiektu jako parametru. Oto prosty przykład:

public String getRevision(Item item) {
    service.load(item, "revision");
    // there is usually more work to do before getting the data..
    try {
        return item.get_revision();
    }
    catch(NotLoadedException exception) {
        log.error("Property named 'property_name' was not loaded", exception);
    }
    return null;
}

Jak i dlaczego decydować między nazwaniem tej metody jako getRevision()lub findRevision()?

znane
źródło
2
najlepszym pomocnikiem dla źle zaprojektowanego API jest nie zadzierać z trudnymi nazwami, ale ustanowić warstwę antykorupcyjną : „Jeśli Twoja aplikacja musi radzić sobie z bazą danych lub inną aplikacją, której model jest niepożądany lub nie ma zastosowania do modelu, który chcesz w swojej aplikacji, użyj AnticorruptionLayer, aby przetłumaczyć na / z tego modelu i twojego ”.
komara
1
Nigdy wcześniej nie słyszałem o tej koncepcji. Czy masz jakieś lepsze linki z przykładami?
knownasilya
1
Szukaj w Internecie, jest tam sporo informacji. Np. Anatomia warstwy antykorupcyjnej, część 1 „prawdopodobne jest, że ... nieuchronnie stajesz przed zadaniem interakcji z już istniejącym spaghetti. Wejdź do warstwy antykorupcyjnej ...”
gnat

Odpowiedzi:

83

Używam, Getgdy wiem, że czas pobierania będzie bardzo krótki (jak w przypadku wyszukiwania z tabeli skrótów lub btree).

Findimplikuje proces wyszukiwania lub algorytm obliczeniowy, którego wykonanie wymaga „dłuższego” okresu (dla pewnej dłuższej wartości).

Robert Harvey
źródło
3
+1 Korzystam z get podczas pobierania i znajduję, kiedy trzeba zrobić pracę, aby dostać.
Jim
5
Biorąc pod uwagę, że zmiany w kodzie (niektóre części ulegają optymalizacji i zmiany algorytmów) oraz zmiana API jest często niemożliwa, nie wygląda na właściwe kryteria. Co byś zrobił, gdybyś findpóźniej zastąpił algorytm tabeli skrótów?
meze
2
Zakładam również, że podczas czytania wywołania „find” może zostać wywołane, gdy szukanie się nie powiedzie, ponieważ kryterium wyszukiwania się nie powiedzie, podczas gdy „get” ma się powieść, chyba że wystąpi jakiś niezwykły problem.
gnasher729
Co jeśli funkcja akceptuje opcjonalny parametr do filtrowania wyników na podstawie pewnych warunków? Oba geti findmiałyby zastosowanie w zależności od tego, jak jest używany.
ESR
62

Powiedziałbym, że to findmoże zawieść, ale getnie powinno.

rdzeń rdzeniowy
źródło
25
Jeśli masz na myśli, że findmoże zwrócić NULL, a getnigdy nie zwróci NULL, ale może rzucić (lub potwierdzić), zgadzam się.
Sjoerd,
1
Całkowicie się z tym zgadzam z @Sjoerd.
2013
A co jeśli find()zwroty Optional<>? W takim przypadku findjest również nullbezpieczny.
TheCoder
42

Cytując rozmowę, którą często prowadzę z moimi dziećmi:

ja: hej dzieciaku! Znajdź mi baterie

dzieciak: Ale gdzie oni są?

ja: Właśnie dlatego kazałem ci je znaleźć . Gdybym wiedział, gdzie oni są, powiedziałbym, żebyś poszedł po nie. Lub możesz zapytać swoją matkę.

Ten sam pomysł dotyczy:

  • użyj „get” dla metody, która zwraca tanio dostępną informację (i prawdopodobnie może być wstawiona lub w inny sposób zoptymalizowana), lub dla informacji posiadanej wyłącznie przez ten obiekt.

  • użyj „find” dla metody, która działa, aby uzyskać kawałek informacji lub używa innych obiektów, aby go znaleźć.

jimwise
źródło
16
Tylko programista przeprowadziłby tę rozmowę ze swoimi dziećmi. „Czy chcesz wynieść śmieci?” "Nie." „Czy wyniesiesz śmieci?” "Tak."
Robert Harvey
@RobertHarvey Myślę, że mam ten problem z ludźmi. Ilekroć ktoś próbuje coś wyjaśnić lub zadaje pytanie, zwykle odpowiadam na pytania i mówię im o tym wprost. W przeciwnym razie zwykle pojawia się problem z XY. Jeśli tego nie zrobię, poczuję się jak chodząca funkcja autouzupełniania. Nie wiesz, co masz na myśli, nie możesz tego wyrazić słowami, bełkotasz kilka słów i oczekujesz, że zrobię dla ciebie całe „myślenie” i ci w tym pomogę? Nie, nie dzieje się :)
akinuri,
3

Znajdź oznacza brak wyniku, na przykład podczas wykonywania zapytania do bazy danych z niektórymi parametrami, które mogą się zmieniać między wywołaniami. Z drugiej strony, uzyskanie sugeruje, że wyniki są znane metodzie wcześniej lub nie zmienią się, gdy zostaną poznane, że nie ma parametrów wywołania.
Więc użyłbym na przykład Customer findCustomerById (długi customerId) i Customer getCustomer ()

jwenting
źródło
3

Stosuję następujący wzór:

  • Foo GetFoo() nie może zwrócić wartości null, a jego złożoność wynosi O (log (n)) lub mniej
  • bool TryGetFoo(out Foo) może zwrócić null, a jego złożoność wynosi O (log (n)) lub mniej
  • Foo FindFoo() nie może zwrócić null, a jego złożoność jest większa niż O (log (n))
  • bool TryFindFoo(out Foo) może zwrócić null, a jego złożoność jest większa niż O (log (n))

W ten sposób kod jest dość jasny pod względem intencji i złożoności, jakiej można się spodziewać.

Zazwyczaj Gettery są przeznaczone do bezpośredniego dostępu do listy lub słownika / zestawu.
Findery to dokładne wyszukiwanie, pełne skanowanie listy itp.

W Twoim przypadku:

public bool TryGetRevision( Item item, out String revision ) 
{
    service.load( item, "revision" );
    // there is usually more work to do before getting the data..
    try 
    {
        revision = item.get_revision();
        return true;
    }
    catch( NotLoadedException exception )
    {
        log.error( "Property named 'property_name' was not loaded", exception );
        revision = "";
        return false;
    }
}
Cyril Gandon
źródło
+1 za try, krótki i precyzyjny
SpaceTrucker
2

getjest odpowiednie w każdym przypadku _ w rzeczywistości często zakłada się, że aby coś uzyskać, musisz to najpierw znaleźć. Więc jeśli nie jesteś pewien, użyj get.

Użyłbym finddo metod takich jak findMinimum()lub findOptimal(), tj. Tam, gdzie istnieje jakiś specjalny algorytm, który oblicza wartość zwracaną, a nie po prostu wysyła do DB, systemu plików, zdalnego serwera itp. Żądanie otrzymania danych.

superM
źródło
1
Słuszne uwagi. Osobiście prawdopodobnie nie użyłbym findjako prefiksu w podanych przez ciebie przykładach. Do zadań obliczeniowych, takich jak te w twoim przykładzie, użyłbym calculatelub compute.
knownasilya
2

Nie używaj znajdź ani nie otrzymuj prefiksów. Jest to naruszenie zasady UniformAccessPrinciple wymyślonej przez Bertranda Meyera . Dlaczego nie stworzyć metody takiej jak poniżej:

public String revision(Item item)
Giorgi Dvalishvili
źródło
całkowicie się z tobą zgadzam, świetnie !!!!
Irakli Gabisonia
1

Zasadniczo będę używać Getdo pobierania obiektu / wartości i Finddo wyszukiwania jego położenia (na przykład w tablicy).

na przykład:

object o = obj.GetItem( 'name');

integer i = somearray.Find( 'name');
Grandmaster B.
źródło
0

Dla mnie findoznacza to, że może być obecny więcej niż jeden wynik. getimplikuje tylko jeden.

Karl Bielefeldt
źródło
8
Wygląda na to, że ma takie odczucie, ale nie jestem pewien, czy całkowicie się z tym zgadzam. Pomyśl o tym w ten sposób: getCatvs findCatvs getCatsvs findCats. find..Nadal reprezentuje zwracane pojedyncze obiekty. Liczba mnoga powinna być dodana do rzeczownika, moim zdaniem.
knownasilya