Как и зачем выбирать между методами именования с префиксами «get» и «find»

48

Мне всегда трудно понять, стоит ли мне называть определенный метод, начиная с « getSomethingпротив» findSomething.

Проблема заключается в создании помощников для плохо разработанных API. Это обычно происходит при получении данных от объекта, который требует объекта в качестве параметра. Вот простой пример:

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;
}

Как и зачем выбирать между именованием этого метода как getRevision()или findRevision()?

knownasilya
источник
2
лучший помощник для плохо спроектированного API - не связываться с хитрыми именами, а создать антикоррупционный слой : «Если вашему приложению нужно иметь дело с базой данных или другим приложением, модель которого нежелательна или неприменима к модели, которую вы хотите в своем собственном приложении, используйте AnticorruptionLayer для перевода в / из этой модели и вашей. "
комнат
1
Я никогда не слышал об этой концепции раньше. Есть ли у вас лучшие ссылки с примерами?
известноасиля
1
Поиск в Интернете, там довольно много информации. Например, Анатомия уровня по борьбе с коррупцией, часть 1 «вероятно , что ... вы неизбежно сталкиваетесь с задачей взаимодействия с спагетти , которые уже есть Введите слой Антикоррупционного ....»
комар

Ответы:

83

Я использую, Getкогда знаю, что время поиска будет очень коротким (как при поиске из хеш-таблицы или btree).

Findподразумевает процесс поиска или вычислительный алгоритм, который требует «более длительного» периода времени для выполнения (для некоторого произвольного значения более длинного).

Роберт Харви
источник
3
+1 Я использую get при поиске и нахожу, когда нужно выполнить работу, чтобы получить get.
Джим
5
Принимая во внимание, что изменения кода (некоторые части становятся оптимизированными и изменения алгоритмов) и изменение API часто невозможно, это не выглядит как правильный критерий. Что бы вы сделали, если бы вы заменили findалгоритм хэш-таблицы позже?
мезе
2
Я также предположил бы, что при чтении вызова «find» может вызываться, когда поиск не удается, потому что критерий поиска не выполняется, в то время как «get», как ожидается, будет успешным, если не возникнет какая-либо необычная проблема.
gnasher729
Что если функция принимает необязательный параметр для фильтрации результатов на основе какого-либо условия? И то getи другое findбудет применяться в зависимости от того, как оно используется.
ESR
62

Я бы сказал, что findможет потерпеть неудачу, но getне должен.

CoreDump
источник
25
Если вы имеете в виду, что findможете вернуть NULL, а getникогда не вернет NULL, но могут выбросить (или утверждать), я согласен.
Sjoerd
1
Я полностью согласен с @Sjoerd в этом.
н
А что, если find()возвращается Optional<>? В этом случае findтакже nullбезопасно.
TheCoder
42

Процитирую разговор, который я часто имею со своими детьми:

я: Эй, малыш! Найди мне батарейки

Малыш: Но где они?

я: Вот почему я сказал вам, чтобы найти их. Если бы я знал , где они были, я сказал бы вам пойти получить их. Или вы могли бы спросить свою мать.

Та же идея имеет место:

  • используйте «get» для метода, который возвращает дешевую доступную часть информации (и, вероятно, может быть встроенной или иным образом оптимизированной), или для части информации, уникально принадлежащей этому объекту.

  • используйте «find» для метода, который работает, чтобы получить часть информации, или использует другие объекты, чтобы найти ее.

jimwise
источник
16
Только программист может вести этот разговор со своими детьми. "Вы хотите вынести мусор?" «Нет . » "Вы будете выносить мусор?" "Да."
Роберт Харви
@RobertHarvey Я думаю, у меня проблема с людьми. Всякий раз, когда кто-то пытается что-то объяснить или задает вопрос, я обычно задаю вопросы обратно и говорю им об этом прямо. В противном случае мы обычно сталкиваемся с проблемой XY. Если я этого не сделаю, я чувствую, как функция автозаполнения при ходьбе. Вы не знаете, что у вас на уме, вы не можете выразить это словами, вы лепете пару слов и ожидаете, что я сделаю все «размышления» за вас и помогу вам в этом? Нет, не происходит :)
akinuri
3

Поиск подразумевает отсутствие результата, например, при выполнении запроса к базе данных с некоторыми параметрами, которые могут изменяться между вызовами. Get, с другой стороны, подразумевает, что результаты известны методу заранее или не изменятся после того, как станут известны, что в вызове нет параметров.
Итак, я бы использовал, например, Customer findCustomerById (long customerId) и Customer getCustomer ()

jwenting
источник
3

Я применяю следующий шаблон:

  • Foo GetFoo() не может вернуть ноль, и его сложность равна O (log (n)) или меньше
  • bool TryGetFoo(out Foo) может вернуть ноль, и его сложность равна O (log (n)) или меньше
  • Foo FindFoo() не может вернуть ноль, и его сложность больше, чем O (log (n))
  • bool TryFindFoo(out Foo) может вернуть ноль, и его сложность больше, чем O (log (n))

Таким образом, код достаточно ясен в отношении намерений и сложности, которую вы можете ожидать.

Как правило, геттеры предназначены для прямого доступа к списку или словарю / набору.
Искатели - это глубокий поиск, полное сканирование списка и т. Д.

В твоем случае:

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;
    }
}
Кирилл Гандон
источник
+1 за try, коротко и точно
SpaceTrucker
2

getуместно в любом случае _ на самом деле часто предполагается, что для того, чтобы получить что-то, нужно сначала найти это. Так что, если вы не уверены, используйте get.

Я бы использовал findтакие методы, как findMinimum()или findOptimal(), т. Е. Где есть какой-то особый алгоритм, который вычисляет возвращаемое значение, а не просто делает запрос к БД, файловой системе, удаленному серверу и т. Д. Для получения некоторых данных.

superM
источник
1
Хорошие моменты. Лично я бы не использовал findпрефикс в приведенных вами примерах. Для вычислительных задач, таких как те, что в вашем примере, я бы использовал calculateили compute.
известноасиля
2

Не используйте префиксы find или get. Это нарушение UniformAccessPrinciple, придуманное Бертраном Мейером. Почему бы не создать метод, подобный следующему:

public String revision(Item item)
Георгий Двалишвили
источник
я полностью согласен с тобой, отлично !!!!
Ираклий Габисония
1

Обычно я буду использовать Getдля получения объекта / значения и Findдля определения его местоположения (например, в массиве).

Например:

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

integer i = somearray.Find( 'name');
GrandmasterB
источник
0

Для меня это findозначает, что может быть более одного результата. getподразумевает только одно.

Карл Билефельдт
источник
8
Похоже, у него такое чувство, но я не уверен, что полностью согласен. Подумайте об этом так: getCatпротив findCatпротив getCatsпротив findCats. find..По- прежнему представляет собой особые объекты возвращаются. Множественное число должно быть добавлено к существительному, по моему мнению.
известноасиля