Чи погана практика кодування створювати щось у випуску, якщо його не існує?


18

Тож у мене є веб-сервіс, який має щось на зразок, getAccountде він би повертав ідентифікатор до облікового запису, якби його отримав, інакше киньте виняток. Клієнт завжди захоче створити обліковий запис, якщо буде виняток з тією ж інформацією, з якою робиться отримання.

Я створюю бібліотеку зручностей для клієнтів, які будуть обробляти всі дзвінки веб-сервісу всередині, тому їм не потрібно знати, як робити дзвінки самі.

Мені цікаво, що в цій бібліотеці я створив getAccount(accountName)обліковий запис, який отримає обліковий запис, якщо він існує, і якщо він не створить його і поверне інформацію, це погано робити? Чи варто залишити його клієнтові для обробки винятків або просто назвати його чимось на зразок getOrCreateAccount? Це важливо?

Чи погана практика створювати щось в операції get?


9
Принаймні, я б назвав це getOrCreateAccountчи подібне.
Теластин

4
Це здається дійсним в умовах лінивої ініціалізації. Однак це залежить від того, чи є у вас потреба використовувати цей шаблон у вашій бібліотеці.
Кріс С

1
Мені подобається дієслово acquire, як acquireAccount. Він не має жодного значення в жодних основних протоколах, з якими я стикався, і він має імперативне кільце, яке йому добре підходить. "Зробіть все, що вам потрібно зробити, щоб придбати для мене одне з них. Запросіть його, побудуйте його, підробіть, викрадіть його, мені все одно, просто дістаньте мене або помріть, намагаючись".
Dan Ross

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

Згідно з javabean spec oracle.com/technetwork/articles/javaee/spec-136004.html getSomething() призначено для гетерів та setSomething()для сеттерів. Имо все , що робить що - то більш інтелектуальне має називатися що - то інше, тобто fetchSomething, obtainSomething, computeSomethingабо і doSomethingElseт.д.
ccpizza

Відповіді:


31

Так, це має значення. На мою думку, це взагалі погана практика створювати щось у процедурі, яка не документально підтверджена як така, що має повноваження щодо створення. Назвіть назву процедури getOrCreate...або отримайте окрему create...процедуру, і тоді, якщо ви дійсно хочете, зробіть getOrCreate...перші спроби get..., а якщо це не вдасться, дзвоніть, create...а потім дзвоніть get....

Користувач бібліотеки, ймовірно, не очікує, що get...процедура буде створена, якщо операція get не завершиться . Якщо вони раптом виявлять, що їх тестові дзвінки get...створили цілу тону даних, вони, ймовірно, будуть досить здивовані. І як вони це прибирають? Що робити , якщо вони пишуть код , думаючи , що вони будуть отримувати повідомлення про помилку , якщо get...не вдається , і вони хочуть , щоб впоратися з цим їх шляху?


Дякую, create фактично повертає ідентифікатор, що get також повернеться, тому мені не доведеться робити get... create... get...лише перші два. Я поговорю з клієнтом про те, чи буде їм коли-небудь потрібна можливість просто зателефонувати на телефон, getне бажаючи створювати
Майк

6
@Mike: Я все ще думаю, що це має бути createв назві, просто щоб бути 100% зрозумілим, що відбувається.
FrustratedWithFormsDesigner

Так, я погоджуюся, я планував зробити щось на зразок getOrCreate, тому що моя первісна думка полягала лише в тому, щоб отримати, але я зрозумів, що не відразу зрозуміло, що це також створює щось на задньому плані
Майк

1
Це дуже пізно, але getOrCreateмає перевагу в популярній веб-рамці: docs.djangoproject.com/en/1.10/ref/models/querysets/…
tex

18

Ні, це не «погана практика». Поки ви та інші розробники погоджуєтесь, як ви хочете, щоб це працювало, це просто чудово. Зрештою, це буде повернення акаунта, що ви хочете. Те, що обліковий запис створено "під капотом", для абонента не має значення.


10
Винятком є ​​лише якщо це загальнодоступний API. Ширша громада вже погодилася, що GET є невмілим та несамовитим; Іншими словами, щоразу виконуються одні й ті ж дії, і це безпечний метод, який не змінює стан сервера. Про це в REST Wiki . Крім цього, якщо API просто існує у вашому маленькому світі, зробіть все, що буде прийнято вашою групою.
jmort253

9
Я не погоджуюся, навіть для публічного API його штраф - якщо це має сенс у контексті того, що API повинен робити. Немало сенсу створювати кілька записів в API, коли одна з них зробить трюк.
гросмайстерB

Для запису це повністю внутрішня бібліотека, і я маю можливість просто розповісти команді, використовуючи її,
Майк

1
@ jmort253: Послуга є неправомірною, якщо вона не має побічних ефектів, видимих ​​для клієнта . Сервер може робити, як заманеться.
кевін клайн

1
@kevincline, я думаю, я думав про це з точки зору, скажімо, стягнення моєї кредитної картки. Якщо сервер стягує плату з моєї картки на основі GET-запиту, але все ж дає мені такий результат, як "відхиляється" щоразу, коли я запускаю її, то відчувається, що це суперечить духу GET. З урахуванням сказаного, я бачу вашу думку. Сервер міг підрахувати кількість GET-запитів і заблокувати мене після 3 запитів, тим самим обмежуючи швидкість, але не змінюючи жодних деталей мого облікового запису. Я думаю, що це важлива відмінність, коли можна сказати, що стан сервера не змінено. Можливо, замість цього я повинен сказати "стан клієнта на сервері"
jmort253

10

Якщо getAccount()ви завжди можете повернути рахунок, тоді, з точки зору абонента, рахунок існує і існує. Не потрібно getAccount()нічого "створювати". Обліковий запис не потрібно зберігати ніде, поки він не буде відрізнятися від облікового запису за замовчуванням.


+1 Як правило, GetOrCreateце неправильне семантичне значення, але отримати об'єкт, який може "логічно" існувати, незалежно від того, чи існує він фізскально, це добре. Наприклад, розрізнений масив змінних елементів може не мати жодного сховища, виділеного для елемента 1,841,533, але все ж дозволяють "отримати" цей елемент, створивши новий об'єкт, зберігаючи його та повертаючи посилання.
supercat

4

Найбільш сенс створити 3 методи:

getAccount -> Що тільки отримує рахунок.

createAccount -> Створює обліковий запис.

getAccountAndCreateIfNeeded -> Оберіть власну назву;)

Чому розділення: у вас простий метод отримання та створення. Це чіткий тестований метод для обох. Для getAccount не є винятком не знайти обліковий запис. Тож просто повертайте помилкове чи щось подібне, очікується.

Тоді ви можете використовувати це повернене значення у групуваній функції: getAccountAndCreateIfNeeded, яка тепер також перевіряється, вона повинна повертати рахунок завжди. Що б ви не попросили.

Всі ці 3 методи зрозумілі, точно зрозуміло, що вони роблять і до чого повертаються. Ви можете зараз домовлятися зі своєю командою, але подібні винятки з часом страшні. Просто зробіть їх чіткими, і у вас не виникне жодних проблем.


Також з чистого коду: "Якщо ваш метод не може виконати те, що означає його ім'я, тоді киньте виняток". У мене буде блок "Try / Catch" всередині "GetOrCreateIfneeded", який викидає невдалий GET, а потім має "createAccount" всередині Throw за будь-який тип винятку, який повертається за невдале отримання.
Грем

Я можу запропонувати четвертий метод:, getAccountIfExistsякий або отримає обліковий запис, або вкаже, що його не існує без створення нового. Сам getAccountметод повинен припускати, що обліковий запис існує, і викидати виняток, якщо ні.
supercat

2

Це залежить від обставин.

Наприклад, ви можете використовувати його для ледачого завантаження / інстанції, відстрочення завантаження даних або створення екземпляра, поки це фактично не потрібно. Це зазвичай розумно, оскільки це економить ресурси, які вам можуть не знадобитися (якщо клас / дані ніколи не потрібні, вони ніколи не завантажуються).

Однак у цьому конкретному випадку я б сказав, що використання методу під назвою getAccount, який створив би новий обліковий запис, якщо його не існувало, не буде хорошою практикою. Якщо користувач надав деякі дані для ідентифікації конкретного облікового запису, і цей обліковий запис не вдалося знайти, чи це означає, що користувач ще не є клієнтом і має створити для них обліковий запис, чи це означає, що облікові дані були введені неправильно а користувача потрібно попросити перевірити, чи ввели вони те, що мали намір ввести?

Якщо у вас є метод getAccount, який створює новий обліковий запис, якщо він не міг його ідентифікувати, то у вас немає вибору в цьому питанні. Якщо ви розділите створення облікового запису та випуск облікового запису на окремі методи, ви маєте набагато більшу гнучкість у вирішенні питання, що робити, якщо спроба отримати рахунок не вдасться.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.