Видалення твердо кодованих значень та захисного дизайну проти YAGNI


10

Спочатку трохи тла. Я кодую пошук із Age -> Rate. Існує 7 вікових дужок, тому таблиця пошуку - 3 колонки (від | до | оцінювання) з 7 рядками. Значення рідко змінюються - це законодавчі норми (перший і третій стовпці), які залишаються однаковими протягом 3 років. Я зрозумів, що найпростіший спосіб зберігати цю таблицю без жорсткого кодування - це в базі даних в таблиці глобальної конфігурації, як єдине текстове значення, що містить CSV (так "65,69,0.05,70,74,0.06" - це як 65-69 та 70-74 рівні зберігатимуться). Порівняно простий розбір, а потім використання.

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

Під час розмови з користувачами (які в даний час використовують таблицю пошуку безпосередньо - дивлячись на паперовій копії), думка майже в тому, що "ставки ніколи не змінюються". Очевидно, що це насправді не правильно - ставки були створені лише три роки тому, і в минулому речі, які "ніколи не змінюються", мали звичку змінюватися - тому для мене, щоб захисно програмувати це, я точно не повинен зберігати таблицю пошуку в додаток.

За винятком випадків, коли я думаю про ЯГНИ . Функція, яку я реалізую, не вказує, що ставки будуть змінюватися. Якщо ставки змінюються, вони все одно змінюватимуться настільки рідко, що технічне обслуговування навіть не враховується, і ця функція насправді не є достатньо критичною, щоб на що-небудь вплинути, якщо буде затримка між зміною курсу та оновленим додатком.

Я майже вирішив, що нічого цінного не буде втрачено, якщо я жорстко кодую пошук, і я не надто стурбований своїм підходом до цієї особливості. Моє запитання: як професіонал я правильно обґрунтував це рішення? Значення жорсткого кодування - це погана конструкція, але проблематика видалення значень із програми, здається, порушує принцип YAGNI.

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

EDIT Хоча всі відповіді були дуже цікавими, тому що я думаю, що це зводиться до вибору дизайну індивідуума, я думаю, що найкращі відповіді були у @ Corbin та @EZ Hart, оскільки вони відображають речі, які я не враховував у питанні:

  • помилкова дихотомія "правильного видалення жорстко закодованих значень" шляхом переміщення її до бази даних проти "ефективного застосування YAGNI" за допомогою жорсткого кодування. Був третій варіант введення таблиці пошуку в конфігурацію програми, яка не несе накладні витрати правильним чином і без ефективності YAGNI. Ми, як правило, не обмежуємось чи /, ні рішеннями, і це зводиться до рішення витрат / вигод.
  • генерація коду може зменшити накладні витрати на переміщення твердо кодованих значень у базу даних, і таким чином, це також видалить моє надмірно розроблене рішення обробити CSV в таблицю. Потенційно це також додає проблему тривалого обслуговування згенерованого коду, якщо основні вимоги змінюються для методу пошуку. Все це впливає лише на аналіз витрат і вигод, і, ймовірно, що якби у мене була така автоматизація, я б навіть не вважав жорстким кодуванням щось подібне.

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


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

Відповіді:


6

Ви знайшли недолік у процесі свого розвитку. Коли боляче робити правильно (створювати таблицю, репо, тести репо, вирівнювати тести ...), розробники знайдуть шлях для цього. Зазвичай це стосується того, щоб робити неправильну справу. У цьому випадку спокушаєш ставитися до даних програми як до логіки програми. Не робіть цього. Натомість додайте в процес розробки корисні автоматизації. Ми використовуємо CodeSmith для створення нудного кодового коду, який ніхто не хоче писати. Після створення таблиці ми запускаємо CodeSmith, і вона генерує DAO, DTO, і вимикає блок тестів для кожного.

Залежно від технологій, якими ви користуєтесь, у вас повинні бути подібні варіанти. Багато інструментів ORM генерують моделі з існуючої схеми. Міграція рейок працює у зворотному напрямку - таблиці від моделей. Метапрограмування в динамічних мовах особливо сильне в усуненні кодового коду. Вам доведеться попрацювати трохи складніше, щоб створити все необхідне, якщо у вас є складний багаторівневий додаток, але воно того варте. Не дозволяйте відчуттю, "ух, це біль у шиї", що заважає вам робити правильно.

О, і не зберігайте свої дані у форматі, який потребує додаткової обробки (CSV). Це просто додає додаткові кроки, які потребують вашої уваги та тестування.


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

Це мене цікавить, я не розглядав питання автоматизації частин початкових зусиль до цього рівня. А мати цю автоматику означатиме, що я можу створити повну таблицю, а не використовувати CSV, щоб заощадити час. Що мене хвилює - це тривале підтримання створеного коду. Генеруючи це заздалегідь, я зробив раннє припущення, що метод здійснення пошуку ніколи не зміниться. Я думаю, що якщо це така можливість, я повинен просто взяти це до уваги як частину витрат / вигоди, враховуючи зменшену вартість котлоагрегату. +1
Ребекка Скотт

Питання полягало в тому, "чи варто твердо кодувати значення, коли мій клієнт каже, що вони не зміниться?" і ваша відповідь - «ні, і насправді ви повинні кинути ORM на проблему». Я не погоджуюсь. Є більш прості варіанти, які дозволять ОП уникати жорсткого кодування. Зробити великі доповнення до архітектури для підтримки речей, явно позначених непотрібними, неетично. Прикро, що багато розробників схильні робити такі речі. І мушу сказати, я не погоджуюсь на 100% з вашою пропозицією не «пускати почуття», ого, це біль у шиї «заважає вам робити правильно». Ці почуття мають значення!
користувач1172763

10

Щоб відключити та продовжити @ Thorbjørn відповідь Равна Андерсена: Утримання обчислення / пошуку в одному місці - хороший початок.

Ваш мислительний процес оборонного проти YAGNI - це поширена проблема. У цьому випадку я б запропонував про це повідомити ще дві речі.

По-перше - як була представлена ​​вимога користувача? Чи вказали вони редактивність ставок? Якщо ні, то додана складність є частиною того, за що можна виставити рахунок чи ні? (або якщо у вас є персонал, що ви можете витратити свій час, роблячи іншу роботу замість цього?) Якщо так, то обов'язково продовжуйте і доставляйте те, що було обгрунтовано просили.

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

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

Щасти


1
+1 для другого пункту. Я не намагаюся переконатись, що законодавчі органи можуть робити в майбутньому.
Девід Торнлі

Зробіть це у функції бібліотеки. Добре мати лише одного користувача. Коли і якщо вимоги змінюються, ви можете змінити одне місце. (Можливо, вам потрібно буде додати функцію для пошуку даних на значення станом на певну дату.)
BillThor

Найкраща та найповніша відповідь, +1
Енді

7

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


Пошук буде реалізований лише в одному місці ( PensionRateLookupможливо, на кшталт класу), який потім використовується в усьому світі. Я б зробив це незалежно від того, зберігається він поза додатком або жорстко кодується, таким чином потрібно підтримувати лише реалізацію PensionRateLookupкласу. Моя проблема полягає в тому, як я використовував YAGNI, щоб дійти висновку, що жорстке кодування таблиці пошуку прийнятне.
Ребекка Скотт

Дякую за вашу відповідь. Зберігаючи реалізацію пошуку в одному місці, безумовно, хороший дизайн.
Ребекка Скотт

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

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

Тоді в чому проблема? Коли тарифи змінюються, ви оновлюєте код і доставляєте всім клієнтам?

2

Дозвольте мені побачити, чи правильно я поставив ваше запитання. У вас є два варіанти впровадження функції: або ви жорстко вкажете значення, і вашу функцію легко реалізувати (btu вам не подобається частина жорсткого коду), або ви доклали великих зусиль, щоб "переробити" багато речей, що робляться тож ви зможете розвинути вашу функцію в чистому вигляді. Це правильно?

Перше, що мені спадає на думку, - «Найважливіше, що знати добрі практики - це знати, коли тобі краще без них».

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

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

Це був би мій підхід :)


Дякую @Oscar. Технічна частина цього проекту - def. правильно. І я погоджуюся з тим, як би ви підходили до проблеми, рефакторингуючи лише тоді, коли це потрібно. Отже, ви говорите, що ми, як професіонал, можемо і повинні вибирати наші принципи дизайну, виходячи виключно з вартості / вигоди? Має сенс.
Ребекка Скотт

@Ben Scott: Вітаємо вас :). Так, на мою точку зору, принципи дизайну були створені / каталогізовані не тому, що вони виглядають красиво, а тому, що вони приносять такі переваги, як код "чистота", гнучкість, надійність і т. Д. Але завжди є 2 питання: 1- Чи мені це потрібно? ? 2) Чи дозволяють мої обмеження (часові, технічні тощо) реалізовувати це? Це, як правило, те, що призводить мене до вибору принципу дизайну. Надмірна інженерія також погана;) ps: якщо ви думаєте, що це цікава відповідь, будь ласка, проголосуйте її, щоб інші люди також читали її з більшою ймовірністю. Дякую! :)
JSBach


2

Це пункт, який "не зміниться", поки це не зробиться. Це неминуче зміниться, але цей час може бути трохи далеко.

Ваше обґрунтування правильне. Наразі замовник не просив можливості легко змінювати ці тарифи. Як такий, YAGNI.

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

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

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


Дякую @berin, я не згадував SRP у питанні, але це було в плані. Хороший момент повернути право власності на проблему клієнту.
Ребекка Скотт

Покладати провину на те, що в майбутньому все піде не так, мені не здається професійним.
Енді

@Andy, яка частина цього покладається на провину? Представлення клієнтовим обмеженням дизайну дає їм можливість або визначити пріоритетну складну роботу зараз, і зняти інші речі зі столу, відсунути термін виконання або прийняти обмежений дизайн зараз, оскільки інші речі на столі для них важливіші. Ви надаєте своїм клієнтам можливість вибору щодо їх продукту. Повідомлення вашого клієнта про ризик / винагороду виборів, які ви хочете зробити в їх інтересах, зробить проект більш легким.
Берін Лорич

@ BerinLoritsch Але це конкретне дизайнерське рішення є подібним із використанням нестандартних деталей, які говорять: "Я можу використовувати сантехніків шпаклівку, щоб підключити цю непрохідну трубу, це ваш найдешевший варіант!" Ставки будуть змінюватися. Це дано, і професіонал безвідповідально будувати систему, яка цього не дозволяє. А економія, ймовірно, незначна у грандіозній схемі вартості проекту. Помістіть дані в таблицю; код, який отримує дані пошуку, дещо відрізняється, логіка з'ясування того, яку швидкість використовувати однаково в будь-якому випадку. Єдине інше рішення - як обробити історичні дані після ...
Енді

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

2

Розділіть різницю і введіть дані про швидкість у налаштування конфігурації. Ви можете використовувати формат CSV, який ви вже отримали, ви уникнете зайвих накладних баз даних, і якщо будь-яка зміна буде колись необхідною, це буде зміна, яку повинен зробити клієнт без необхідності перекомпілювати / перевстановити та без збитків навколо в базі даних - вони можуть просто редагувати файл конфігурації.

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

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


Я розглядав можливість встановити його в налаштуваннях конфігурації, але відклав це, оскільки користувачі не дуже технічні, як щодо редагування рядка CSV, тому я би був тим, що оновлював конфігурацію для N користувачів (як я роблю всю підтримку ІТ в Орган також), з точки зору зусиль було б простіше виконати попередню роботу, щоб потрапити в базу даних, яку я можу адмініструвати з одного місця. Я думаю, якби це не було врахуванням (якщо користувачі могли керувати їх індивідуальною конфігурацією), я б не мав цієї проблеми. Тож дуже вдалий момент, дякую.
Ребекка Скотт

Якщо ви поєднали це з іншими пропозиціями централізованої логіки, то це чудова відповідь. Це чисто зло справді жорсткого пошуку, а не розміщення таким чином, що дозволяє змінити його через config. Щоразу, коли будь-який інший розробник стикається з ним, він буде ненавидіти вас за це. Навіть магазин для розробок чоловіків повинен розглянути, що станеться, якщо їх потрапить автобус, і слід спростити наступному розробнику змінити значення без повного випуску програмного забезпечення. Тільки якщо ви ненавидите клієнта і ненавидите всіх інших розробників, ви повинні жорстоко вчинити його. Так в основному ніколи.
simbo1905

2

Я зрозумів, що найпростіший спосіб зберігати цю таблицю без жорсткого кодування - це в базі даних в таблиці глобальної конфігурації, як єдине текстове значення, що містить CSV (так "65,69,0.05,70,74,0.06" - це як 65-69 та 70-74 яруси будуть зберігатися.

Щойно створена таблиця БД. (Ви де думаєте зберігати цілий стіл в одній поданій, ви з’їхали з розуму?)

У таблиці потрібно 2 поля НЕ 3. Вік та коефіцієнт. Наступний рядок містить верхнє значення! Ви денормалізуєтесь, навіть не підозрюючи про це!

Ось Sql, щоб отримати ставку для когось із віку 67 років.

Select * from RateTable where Age in (Select max(age) from RateTable where age <=67) 

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

EDIT: Як вже говорили інші, зберігайте код, і ставка стає централізованою, якщо вся структура курсу змінюється.


Привіт @Morons, дякую за вашу відповідь. Таблиці насправді знадобляться 3 стовпчики. Це єдина ставка в діапазоні віку, хв віці до максимального віку ( від 65 до 69 - літніх знаходяться на 5%). І я зберігаю лише невелику кількість даних з обмеженою метою, тож що поганого в тому, щоб зробити припущення про структуру та перейти на CSV замість цілої спеціальної таблиці? Я б, мабуть, додав роздільник рядків і розділяв на рядки, потім стовпці та перетягував стовпці на необхідні поля. Це завжди буде читати набагато більше, ніж написано, тому я не надто переживаю за повний стіл.
Ребекка Скотт

Наступний рядок містить верхнє значення діапазону ... Це дублювання даних. Сказання <69 і> 7 - те саме. Єдина причина мати обидва значення - це якщо діапазон може мати отвори. ... Я кажу, щоб використовувати таблицю, тому що це простіше (і краще дизайн). Я не розумію, чому ви думаєте, що зберігання csv у таблиці допоможе вам заощадити будь-який час чи зусилля. Вам все ще потрібен дзвінок DB, щоб отримати цю рядок, тоді вам доведеться її розібрати. Як я вам показав вище, ви можете отримати тариф за один виклик БД.
Морон

Ах правда. Я тримав саму таблицю подібною до вихідного матеріалу ... і я пропустив, що вік є верхньою межею у вашій відповіді, тому що у мене були сумки, які я дав вам сумки.
Ребекка Скотт

1
"Ви деморалізуєтесь, навіть не знаючи про це!" - спочатку я подумав, що це помилка, і що ти маєш на увазі «денормалізацію», але чим більше я думав про це, тим більше здавалося, що тобі так і не вдається :)
EZ Hart

@ez hart LOL правда.
Ребекка Скотт

1

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

Я маю віддалену пам'ять, коли я читав добре відомого хлопця / OOP (наприклад, Дейва Томаса або Кента Бека чи когось), який сказав, що їхнє правило для дублювання коду було двічі і лише два рази: не рефактор, коли ви вперше щось дублюєте ви можете коли-небудь писати це два рази у своєму житті. Але втретє ...

Це не точно стосується питання, оскільки ви допитуєтесь до YAGNI, але я думаю, це говорить про загальну гнучкість спритних правил. Суть спритного - пристосуватися до ситуації і рухатися вперед.


Дякую @Dave, це корисно. Я єдиний обслуговуючий персонал з самого початку, але це велика, відносно стабільна база коду (тисячі файлів, понад 100 таблиць тощо), і я все ще постійно здивований (і зляканий). Послідовність, безумовно, одна з моїх цілей, що рухаються вперед.
Ребекка Скотт

0

Жорсткий код у функції.

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

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