Чи має рішення бути максимально загальним або максимально конкретним?


124

Скажіть, у мене є сутність, яка має атрибут "type". Можливо 20 можливих типів.

Тепер мене просять реалізувати щось, що дозволило б змінити тип з A-> B, що є єдиним випадком використання.

Тож чи слід реалізувати щось, що дозволяє довільні зміни типу, якщо вони є дійсними типами? Або я повинен ТОЛЬКО дозволити їй змінитись з A-> B відповідно до вимоги та відхилити будь-яку іншу зміну типу, наприклад B-> A або A-> C?

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

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

Редагувати:

Додавання більше деталей до мого не дуже конкретного прикладу: "Загальне" рішення в цьому випадку вимагає менше роботи, ніж "конкретне" рішення, оскільки конкретне рішення вимагає перевірки як старого, так і нового типу, в той час як загальне рішення потрібно лише підтвердити новий тип.


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

2
@ T.Sar додайте це як відповідь, і я піднесу заяву :-)
Крістоф

4
Що таке "загальне рішення" на ваш погляд? Також уточнюйте, що ви маєте на увазі під «випадком лише використання». Ви маєте на увазі, що дозволений лише перехід від A-> B або вказаний лише той перехід, і це не було б умовою помилки для переходу з будь-якого іншого стану в будь-який інший стан. Як розробник вам потрібно попросити автора справи про те, щоб уточнити. Якщо жоден інший перехід не дозволений і ваш код дозволяє це незалежно від того, хто керує абонентом, ваш код не відповідав вимогам.
RibaldEddie

5
Принцип, що якщо X - це гарна ідея, то лише X весь час повинен бути оптимальним, схоже, має особливе звернення до розробників (або принаймні вокальної групи серед них), але врахуйте це: правила програмування - як прислів’я, в тому, що часто можна зустріти пару з протилежними наслідками. Це знак того, що ви повинні використовувати своє судження (про що говорять відповіді тут) і остерігайтеся догми.
sdenham

2
Передчасна генералізація може викликати стільки печії, скільки передчасна оптимізація - ви закінчите писати багато коду, який ніколи не звикне. Спочатку вирішують конкретну проблему, а потім узагальнюють у міру виникнення потреби.
Джон Боде

Відповіді:


296

Моє правило:

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

Звичайно, це настанова, а не важке і швидке правило: справжня відповідь - використовувати найкраще судження у кожному конкретному випадку.


1
Чи можете ви пояснити, що таке YAGNI?
Бернхард

7
@ Бернхард Вам це не потрібно . Дуже корисний принцип розробки програмного забезпечення.
Анжей

4
thing1, thing2, подумайте, можливо, використовувати масив. У thing1, thing2, thing3, майже напевно, використовуйте thing[]масив замість цього." - аналогічне правило для вирішення між декількома змінними або одним масивом.
Joker_vD

15
Ще один спосіб постановити правило №1: "Ви не можете узагальнити одне".
Уейн Конрад

2
@SantiBailors: Як каже Док Браун у своїй відповіді, ми часто значно переоцінюємо кількість витрачених зусиль, які ми могли б витратити, створивши перший, хто викине. У "Міфічному чоловікові-місяці" Фред Брукс говорить: "Плануйте викинути одного - ви все одно". Це говорило: якщо ви негайно стикаєтеся з більш ніж одним використанням для чогось, наприклад, поставивши набір вимог, коли вам однозначно потрібно буде вирішити ту саму проблему не один раз, - у вас вже є більше одного випадку для узагальнення. з, і це абсолютно добре і не суперечить моїй відповіді.
Даніель Приден

95

Конкретне рішення [...] потребує більше роботи в майбутньому, якщо потрібна аналогічна вимога

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

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

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

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


2
Для мене ця відповідь не має сенсу в контексті ОП. Він каже, що зараз витратить менше часу на узагальнення, і менше часу в майбутньому, якщо тільки в майбутньому не буде необхідності конкретна реалізація. Ви заперечуєте проти "вкладення додаткових зусиль у узагальнення", тоді як ОП вкладе додаткові зусилля лише у тому випадку, якщо вони не узагальнить. (подумайте) .... дивно: $
msb

2
@msb: цей контекст був доданий після того, як я написав свою відповідь і суперечить тому, що говорив ОП раніше, особливо в частині, яку я цитував. Дивіться мою редакцію.
Док Браун

2
Також узагальнене рішення буде складнішим, тому до моменту, коли вам доведеться адаптувати його до другого випадку, знадобиться набагато більше часу, щоб його знову зрозуміти.
AndreKR

4
Док., Осторонь, але ніколи б не здогадався, що ти не є носієм мови. Ваші відповіді завжди добре написані та добре аргументовані.
user949300

2
Я уявляю ваш акцент, коли я читаю ваші майбутні відповіді. :-)
user949300

64

TL; DR: це залежить від того, що ви намагаєтеся вирішити.

Я мав подібну розмову з моїм Gramps про це, тоді як ми говорили про те, як Func та Action в C # є приголомшливими. My Gramps - дуже давній програміст таймерів, це було навколо вихідних кодів, оскільки програмне забезпечення працювало на комп’ютерах, які займали цілу кімнату.

Він кілька разів змінював техніку в своєму житті. Він написав код на C, COBOL, Pascal, BASIC, Fortran, Smalltalk, Java і врешті запустив C # як хобі. Я навчився програмувати з ним, сидячи на колінах, поки я був, але чортів, вирізавши свої перші рядки коду на синьому редакторі IBM SideKick. До мого 20 років я вже витрачала більше часу на кодування, ніж на гру.

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

Ось що він сказав мені:


"Чи варто нам поставитись до узагальнення проблеми чи вирішити її в конкретному обсязі? Ви питаєте? Ну, це ... питання".

Грампс взяв паузу, щоб на короткий момент подумати над цим, фіксуючи положення окулярів на обличчі. Він грав на своєму комп’ютері гру-матч-3, слухаючи LP Deep Purple на своїй старій звуковій системі.

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

"... Сир, Грампс?"

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

Я на мить розгублено моргнув, але, перш ніж я міг сказати що-небудь, продовжував Грампс.

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

"Я ... я думаю, це залежить від пов'язаних з вами витрат і того, що потрібно робити, я думаю."

"Це залежить від проблеми, яку намагається вирішити частина. Ви не будете робити шини зі сталі або лобове скло з шкіри. Ви вибираєте матеріал, який найкраще вирішує проблему, яку ви маєте під рукою. Тепер, що таке загальне рішення? Або конкретне? До якої проблеми, до якого випадку використання? Якщо ви хочете використовувати повний функціональний підхід, щоб надати максимальну гнучкість коду, який буде використаний лише один раз? Якщо вам слід написати дуже спеціалізований, неміцний код частина вашої системи, яка побачить багато і багато застосувань, і, можливо, багато змін? Вибір дизайну, як такий, як матеріали, які ви вибираєте для деталі в машині, або форма цегли Lego, яку ви вибрали, щоб побудувати будиночок. . Яка цегла Лего найкраща? "

Літній програміст дотягнувся до маленької моделі поїзда Лего, яку він має на своєму столі, перш ніж продовжувати.

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

".. Ви просто цитуєте " Матрицю " ? "

"Що?"

"Нічого, продовжуй".

"Ну, припустимо, ви намагаєтесь щось створити для Національної системи рахунків. Ви знаєте, як цей пекельний API і його тридцять тисяч рядків XML-файл виглядає зсередини. Як би виглядало" загальне "рішення для створення цього файлу. як? Файл переповнений необов'язковими параметрами, сповнений справ, якими мають користуватися лише дуже конкретні галузі бізнесу. У більшості випадків їх можна сміливо ігнорувати. Вам не потрібно створювати загальну систему рахунків, якщо єдине, що вам потрібно " Я завжди буду продавати взуття. Просто створіть систему продажу взуття і зробіть її найкращою системою рахунків-фактур, що продають взуття. Тепер, якщо вам довелося створити систему рахунків-фактур для будь-якого типу клієнтів, у більш широкому застосуванні - перепродаватися як незалежна, загальна система продажу,наприклад - зараз цікаво реалізувати ті варіанти, які використовуються лише для газу, їжі чи алкоголю.Зараз це можливі випадки використання. Раніше вони були лише гіпотетичними. Не використовуйте випадки, і ви не хочете реалізувати Не використовуйте випадки. Не користуйся маленьким братом Не потрібно ».

Грампс повернув поїзд лего на своє місце і повернувся назад до своєї гри-3.

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


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


14
Я впевнений, що в цій історії є щось корисне, але читати було занадто боляче, вибачте
GoatInTheMachine

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

16
@ T.Sar не слухайте ненависників, ваш пост - це дорогоцінний камінь корисної поради гуру. +1
LLlAMnYP

7
Частина "архітектура програмного забезпечення - як сир" була просто приголомшливою. Дійсно, ця відповідь - дорогоцінний камінь!
Матьє Гіндон

3
Може, ця відповідь схожа і на сир? ;) Але будь ласка, "SmallTalk" має бути "Smalltalk", і так, я, цей хлопець, вибачте.
федерація.

14

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

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


13

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

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


Питання зрозуміло щодо конкретної проблеми.
RibaldEddie

4
Відповідь є загальною для вирішення цієї конкретної проблеми. І питання недостатньо конкретне, щоб отримати конкретну квитанцію: як ви бачите, у запитанні не вказано жодної інформації про домен. Навіть імена класів не вказані (A і B не враховуються).
Західло

7
"Чи повинна відповідь stackoverflow бути максимально загальною або якомога конкретнішою?"
Ліндон Уайт

@LyndonWhite, чи запитання про stackoverflow має бути максимально загальним (занадто широким!) Або максимально конкретним (як би це не було названо!)? Ха.

4

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

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

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

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


"Ви пропускаєте всі помилки, які не кодуєте." (з баскетбольного плаката: ви пропускаєте всі кадри, які не приймаєте)

3

Важко дати загальну відповідь на цю конкретну проблему ;-)

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

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

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


3
  1. Гібридний. Це не повинно бути жодним / або питанням. Ви можете розробити API для конверсій загального типу, застосовуючи лише конкретну конверсію, яка вам потрібна зараз. (Переконайтеся, що якщо хтось називає ваш загальний API з непідтримуваною конверсією, він не працює зі статусом помилки "не підтримується".)

  2. Тестування. Для перетворення A-> B мені доведеться написати один (або невелику кількість) тестів. Для загального перетворення x-> y, можливо, мені доведеться написати цілу матрицю тестів. Це набагато більше роботи, навіть якщо всі конверсії мають спільну реалізацію.

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

  3. Зчеплення. Конвертору від А до В, можливо, потрібно знати деталі реалізації про А і В (щільне з’єднання). Якщо A і B все ще розвиваються, це означає, що, можливо, мені доведеться продовжувати перегляд конвертера (і його тестів), який висмоктує, але, принаймні, він обмежений A та B.

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

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


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

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

3

Чи має рішення бути максимально загальним або максимально конкретним?

Це не відповідне питання.

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

  1. Наближення першого порядку: звичайне правило YAGNI з трьох, як описано Даніелем Приденом, Док Браун та ін .

    Це загально корисний евристик, оскільки це, мабуть, найкраще, що ви можете зробити, що не залежить від домену та інших змінних.

    Отже, початкова презумпція така: ми робимо найбільш конкретне.

  2. Наближення другого порядку: ви говорите, виходячи з ваших експертних знань щодо області рішення

    "Загальне" рішення в цьому випадку вимагає менше роботи, ніж "конкретне" рішення

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

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

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

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

  4. Наближення четвертого порядку: чи ваші знання про поведінку замовника, або як ця особливість стосується інших, чи пріоритети управління проектами, або ... будь-які інші не суворо технічні міркування змінюють ваше поточне робоче рішення?


2

На це непросте питання відповісти простою відповіддю. Багато відповідей дали евристику, побудовану навколо правила 3, або щось подібне. Вийти за рамки таких великих правил важко.

Щоб дійсно реально відповісти на ваше запитання, ви повинні враховувати , що ваша робота, швидше за все , не реалізували то , що зміни A-> B. Якщо ви підрядник, можливо, це є вимогою, але якщо ви працівник, вас найняли робити багато багатьох менших завдань для компанії. Зміна A-> B - лише одне із цих завдань. Ваша компанія піклується про те, наскільки вдалі можуть бути внесені майбутні зміни, навіть якщо це не зазначено в запиті. Щоб знайти "TheBestImplementation (tm)", вам слід переглянути більшу картину того, що вас насправді просять зробити, а потім використати це для інтерпретації невеликого запиту, який вам було надано, щоб змінити A-> B.

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

Я можу навести кілька конкретних прикладів, коли ваше запитання має остаточну відповідь на основі контексту. Розглянемо випадок, коли ви пишете програмне забезпечення, що критично важливе для безпеки. Це означає, що у вас є команда для тестування, щоб забезпечити ефективність продукту, як обіцяли. Деякі з цих тестових команд повинні перевірити кожен можливий шлях через код. Якщо ви поговорите з ними, ви можете виявити, що якщо узагальнити поведінку, ви додасте 30 000 доларів до витрат на тестування, оскільки їм доведеться перевірити всі ці додаткові шляхи. У цьому випадку не додайте узагальненої функціональності, навіть якщо вам доведеться дублювати роботу 7 або 8 разів через це. Збережіть гроші компанії та зробіть саме те, що вказано у запиті.

З іншого боку, врахуйте, що ви створюєте API, щоб дозволити клієнтам отримувати доступ до даних у програмі бази даних, яку створює ваша компанія. Клієнт просить дозволити зміни A-> B. API зазвичай мають золоті наручники до них: щойно ви додаєте функціональність в API, зазвичай не слід видаляти цю функціональність (до наступного основного номера версії). Багато ваших клієнтів, можливо, не будуть готові оплачувати витрати на оновлення до наступного основного номера версії, тому ви можете затриматися з будь-яким рішенням, яке ви вирішите надовго. У цьому випадку я настійно рекомендую створити загальне рішення з самого початку. Ви дійсно не хочете розробляти поганий API, повний разової поведінки.


1

Хм ... не так багато контексту для продовження відповіді ... повторення попередніх відповідей: "Це залежить".

У певному сенсі ви повинні відкинути свій досвід. Якщо не ваш, то хтось старший у цій галузі. Ви можете посперечатися з тим, які критерії прийняття визначено. Якщо це щось по рядках "користувач повинен мати можливість змінити тип з" A "на" B "" проти ", користувач повинен мати можливість змінити тип з його поточного значення на будь-яке дозволене альтернативне значення".

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

Чи існують обмеження щодо домену, які не дозволяють переходити з "A" на "C" або будь-який інший варіант, а лише з "A" на "B"? Або це лише вузько визначена вимога, яка не є "мисленням вперед"?

Якби загальний випадок був складнішим, я б попросив запитати перед початком роботи, але у вашому випадку, якщо я можу "передбачити", що в майбутньому надходять інші запити на зміну "типу", я б спокусився: a) напишіть щось для багаторазового використання для загального випадку, і б) загорніть його в умовне, що дозволяє лише A -> B поки що.

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


1

Для мене настанова, яку я створив деякий час тому: "Для гіпотетичних вимог пишіть лише гіпотетичний код". Тобто - якщо ви передбачите додаткові вимоги, вам варто подумати про те, як їх реалізувати, і структурувати свій поточний код так, щоб він не блокував цей шлях.

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

Ваш чотири приклади: якщо у вас є всі звичаї методу перетворення під вашим контролем, ви можете просто зараз назвати його convertAToB і планувати використовувати в методі перейменування "ID методу" перейменування в IDE, щоб перейменувати його, якщо пізніше вам потрібна загальна функціональність. Однак, якщо метод перетворення є частиною загальнодоступного API, це може бути зовсім інакше: будучи таким конкретним, згодом блокуватиме узагальнення, оскільки важко перейменувати речі в цьому випадку.


0

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

В принципі, так. Але це не обов'язково призводить до загальних рішень.

Що стосується мене, у розробці програмного забезпечення є два типи тем, де ви повинні передбачити майбутні зміни:

  • Бібліотеки, призначені для використання третьою стороною, та
  • загальна архітектура програмного забезпечення.

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

У вашому випадку ви вимагаєте конкретного вирішення конкретної проблеми, яка не має ніякого передбачуваного впливу на майбутнє. У цьому випадку YAGNI і DRY є хорошими девізами для зйомки для:

  • YAGNI (вам це не знадобиться) пропонує вам реалізувати абсолютно мінімальний, базовий матеріал, який вам потрібен і використовувати зараз . Це означає реалізувати мінімум, завдяки якому ваш поточний тестовий набір перетвориться з червоного на зелений, якщо ви використовуєте розробку стилів TDD / BDD / FDD. Ні на один рядок більше.
  • DRY (не повторюйте себе) означає, що якщо ви знову виникнете подібну проблему, тоді ви добре подумайте, чи потрібне вам загальне рішення.

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

яке звучить як загальне рішення - це шлях?

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

Погляньте на сучасні системи ORM або MVC, наприклад Ruby on Rails; на рівні додатків вся увага зосереджена на виконанні незагальної роботи. Самі бібліотеки рейок, очевидно, майже на 100% загальні, але доменний код (про який йдеться у вашому питанні) повинен робити мінімальні шнанігани в цьому аспекті.


0

Інший спосіб подумати над проблемою - розглянути, що має сенс.

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

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

Очевидно, має сенс здійснити конверсію конкретного типу. Чи також має сенс робити додаткові перетворення типу?

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

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

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