Як і чому вирішити між методами іменування з префіксами «дістати» та «знайти»


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()?


2
найкращий помічник для погано розробленого API - це не возитися з хитрими іменами, але встановити антикорупційний шар : "Якщо вашій програмі потрібно мати справу з базою даних або іншою програмою, модель якої небажана або не застосовується до тієї моделі, яку ви хочете використовувати у власній програмі, використовуйте антикорупційний шар для перекладу на / з цієї моделі та вашої ".
гнат

1
Я ніколи раніше не чув про цю концепцію. Чи є якісь кращі зв’язки із прикладами?
knownasilya

1
Шукайте в Інтернеті, на ньому досить багато інформації. Наприклад, Анатомія антикорупційного шару, частина 1 "цілком ймовірно, що ... перед вами неминуче стоїть завдання взаємодіяти зі спагетті, яке вже є. Введіть антикорупційний шар ..."
gnat

Відповіді:


83

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

FindМає на увазі процес пошуку або обчислювальний алгоритм, для виконання якого потрібен "більший" проміжок часу (для деякого довільного значення довшого).


3
+1 Я використовую get під час пошуку і знаходжу, коли потрібно виконати роботу, щоб зробити дістатися.
Джим

5
Враховуючи те, що зміни коду (деякі частини оптимізуються та алгоритми змінюються) та зміна API часто неможлива, це не схоже на правильні критерії. Що б ви зробили, якщо findпізніше замінили алгоритм хеш-таблиці?
мезе

2
Я також припускаю, що читаючи дзвінок, що "знайти" може бути викликано, коли пошук не вдається, оскільки критерій пошуку не вдається, тоді як очікується, що "отримати" буде успішним, якщо не виникне якась незвичайна проблема.
gnasher729

Що робити, якщо функція приймає необов'язковий параметр для фільтрації результатів на основі якоїсь умови? І те, getі findінше застосовуватиметься залежно від способу його використання.
ESR

62

Я б сказав, що це findможе не вдатися, але getне повинно.


25
Якщо ви маєте на увазі, що ви findможете повернути NULL, але getніколи не поверне NULL, але може кинути (або затвердити), я згоден.
Sjoerd

1
Я повністю погоджуюсь з цим щодо @Sjoerd.
1313

А що робити, якщо find()повертається Optional<>? У цьому випадку findтакож nullбезпечно.
TheCoder

42

Цитувати розмову, яку я часто маю зі своїми дітьми:

я: Ей, дитино! Іди, знайди мені акумулятори

дитина: Але де вони?

я: Ось чому я сказав вам піти їх знайти . Якби я знав , де вони були, я сказав би вам піти отримати їх. Або ви могли запитати у своєї матері.

Така ж ідея:

  • використовувати "get" для методу, який повертає недорогий доступний фрагмент інформації (і, ймовірно, може бути накреслений або іншим чином оптимізований), або для інформації, яка однозначно належить цьому об'єкту.

  • використовувати "find" для методу, який працює, щоб отримати частину інформації, або використовує інші об'єкти для її пошуку.


16
Тільки програміст мав би цю розмову зі своїми дітьми. "Ви хочете вивезти сміття?" "Немає." "Ви виймете сміття?" "Так."
Роберт Харві

@RobertHarvey Я думаю, що у мене виникають проблеми з людьми. Кожен раз, коли хтось намагається щось пояснити чи задає запитання, я, як правило, задаю запитання назад і кажу їм, щоб вони були явними щодо цього. Інакше ми зазвичай стикаємося з проблемою XY. Якщо я цього не роблю, я відчуваю себе функцією автозаповнення, що йде. Ви не знаєте, що вам на думці, ви не можете сказати це словами, ви гриміть пару слів і очікуєте, що я зроблю для вас все "мислення" і допоможу вам у цьому? Ні, не відбувається :)
akinuri

3

Значення має на увазі відсутність результату, як, наприклад, при виконанні запиту до бази даних з деякими параметрами, які можуть змінюватися між викликами. Отримати, з іншого боку, означає, що результати відомі методу заздалегідь або не змінюватимуться колись відомо, що немає жодних параметрів для виклику.
Отже, я б використав, наприклад, клієнт findCustomerById (довгий customerId) та клієнт getCustomer ()


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))

Таким чином код досить чіткий щодо намірів та складності, яку ви можете очікувати.

Як правило, Getters - це прямий список або доступ до словника / набору.
Finders здійснюють глибокий пошук, повне сканування списку тощо ...

У вашому випадку:

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(), тобто там , де є якийсь - то спеціальний алгоритм , який обчислює значення, що повертається, а не просто зробити запит до БД, файлова система, віддалений сервер і т.д. , щоб отримати якісь - то дані.


1
Хороші бали. Особисто я, мабуть, не використовував би findяк префікс у наданих вами прикладах. Для обчислювальних завдань, таких як у вашому прикладі, я б використовував calculateабо compute.
knownasilya


1

Я, як правило, використовую Getдля отримання об'єкта / значення та Findдля пошуку його місця (наприклад, у масиві).

для:

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

integer i = somearray.Find( 'name');

0

Для мене, findмається на увазі, може бути, що існує більше ніж один результат. getпередбачає лише одне.


8
Здається, це має таке відчуття, але я не впевнений, що повністю згоден. Подумайте про це так: getCatпроти findCatпроти getCatsпроти findCats. Зображення find..все ще представляє особливі об'єкти, що повертаються. Множину слід додати до іменника, на мою думку.
knownasilya
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.