Чи слід уникати використання моделей дизайну в проектах, що постійно змінюються?


32

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

Він розповів мені історію, яка змусила мене задуматися про доцільність моделей дизайну в таких проектах. Ось історія.

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

Іноді в продуктах бракувало інформації: наприклад, купка з них не мала жодної ціни, коли продукт був створений, але ціна ще не була вказана. Деякі не мали опису (опис є складним об'єктом з історією модифікації, локалізованим вмістом тощо). Деякі бракували інформації про відвантаження.

Надихнувшись своїми останніми читаннями про дизайнерські шаблони, я подумав, що це чудова можливість використовувати магічний візерунок Null Object . Так я це і зробив, і все було гладко і чисто. Треба було просто зателефонувати, product.Price.ToString("c")щоб показати ціну, або product.Description.Currentпоказати опис; не потрібні умовні речі. Поки одного разу зацікавлена ​​сторона не попросила відобразити її по-різному в API, маючи nullJSON. А також по-різному для контент-менеджерів, показуючи "Не визначено ціну [Змінити]". І мені довелося вбити мого улюбленого зразка Null Object, бо в ньому вже не було потреби.

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

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

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

Яке було б рішення у цьому випадку?

  • Не використовуючи жодних моделей дизайну, перестаньте думати і писати код безпосередньо?

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

  • Зберігайте модель дизайну, яка вже не має сенсу, і намагайтеся додати більше моделей для новоствореної ситуації?

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

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

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

Отже, якісь пропозиції?


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

5
Крім того, FWIW, будь-який клієнт, який не має певної толерантності до дрейфуючих витрат, мабуть, не повинен робити Agile, якщо не передбачено надбавки, вкладені у витрати на зміну вимог.
Роберт Харві

5
я підозрюю, що без моделей дизайну код набагато швидше дійшов до неможливого стану
Стівен А. Лоу

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

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

Відповіді:


86

Я бачу помилкові припущення в цьому питанні:

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

Шаблони дизайну не є самоціллю, вони повинні вам служити, а не навпаки. Якщо модель дизайну не полегшує реалізацію коду або, принаймні, краще розвивається (це означає: простіше адаптуватися до змін, що змінюються), тоді шаблон не вистачає свого призначення. Не застосовуйте шаблони, коли вони не полегшують "життя" для команди. Якщо новий шаблон об’єкта Null обслуговував вашого друга за той час, як він його використовував, то все було добре. Якби це було усунено пізніше, то це теж може бути нормально. Якщо шаблон об'єкта Null сповільнив (правильну) реалізацію, то його використання було неправильним. Зауважте, з цієї частини історії поки що не можна зробити висновок про будь-яку причину "коду спагетті".

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

Це ні його робота, ні його вина! Ваше завдання - піклуватися про згуртованість та злагодженість. Коли вимоги змінюються двічі на день, ваше рішення не повинно жертвувати якістю коду. Просто скажіть замовнику, скільки часу займає, і якщо ви думаєте, що вам потрібно більше часу для отримання дизайну «правильно», тоді додайте достатньо великий запас безпеки для будь-якої оцінки. Особливо, коли у вас є клієнт, який намагається чинити тиск, використовуйте "Принцип Скотті" . І, сперечаючись з нетехнічним замовником про зусилля, уникайте таких термінів, як "рефакторинг", "тестові одиниці", "дизайнерські шаблони" або "кодова документація" - це речі, які він не розуміє і, ймовірно, вважає "непотрібними" нісенітниця », бо він не бачить в цьому ніякої цінності. або принаймні зрозумілі для замовника (функції, підфункції, зміни поведінки, документи користувачів, виправлення помилок, оптимізація продуктивності тощо).

  • рішенням для швидких змін вимог є швидка зміна коду

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


30
+1 - ви не можете вирішити проблеми людей технічними рішеннями.
Теластин

1
+1, але "або, принаймні, краще розвиваються (це означає: легше адаптуватися до мінливих вимог)" - Я б кваліфікував це з розумно мінливими вимогами, правда?
Фурманатор

1
@Fuhrmanator: Я думаю, що це важко обговорити в загальних рисах. ІМХО очевидно, що жодна модель дизайну не допоможе вам, коли ваша перша вимога - «нам потрібен текстовий процесор», і це змінюється на «нам потрібен тренажер польоту». Для менш кардинальних змін вимог не завжди легко вирішити, що допоможе вам зберегти ваше програмне забезпечення еволюціонувати. Найкраще, щоб IMHO не застосовував занадто багато моделей, а деякі принципи - переважно принципи SOLID та YAGNI. І я погоджуюсь на 100% з "Теластином", коли вимоги змінюються занадто часто, це, мабуть, не є технічною проблемою.
Док Браун

4
+1 - "Чесно кажучи, якщо" основні інтерфейси змінюються двічі на день протягом трьох місяців ", тоді рішення не повинно бути реагувати, змінюючи код двічі на день. Справжнє рішення - запитати, чому вимоги змінюються так часто, і якщо можна змінити в тій частині процесу. "Якщо вам постійно дають нові вказівки, краще сісти з усіма зацікавленими сторонами і підтвердити, які очікування є. Опрацюйте свої відмінності, і, сподіваємось, не витрачайте час і гроші кожного, даючи проекту чіткішу мету.
krillgar

1
@Cornelius Док Браун сказав, що важко без конкретності. Вимоги, що переходять від текстового процесора до симулятора польоту, не були б розумними; жодна модель дизайну не допомогла б. Між його прикладом існує велика кількість сірої області, скажімо, додавання нового формату файлів до функції збереження текстового процесора (що дуже розумно). Без конкретики важко обговорити. Крім того, це не те, що не хотілося б змінити. Ось такі зміни важкі, якщо ви вже зробили вибір дизайну на основі вимоги. Словопроцесор у порівнянні з політним симом є чудовим прикладом раннього вибору.
Фурманатор

43

Моя скромна думка: ви не повинні уникати чи не уникати використання дизайнерських моделей.

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

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

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


13
+1 "Шаблони дизайну - це просто добре відомі та надійні рішення загальних проблем, які отримали назви. Вони технічно не відрізняються від будь-якого іншого рішення чи дизайну, про який ви можете придумати." Саме так. Люди настільки захоплюються названими моделями дизайну, що вони забувають, це не що інше, як імена, присвоєні різним стратегіям, щоб полегшити нам програмістам спілкування один з одним про наш код та наш вибір дизайну. Таке ставлення дуже часто асоціюється із спробою насильницьких невідповідних «зразків» на проблеми, які не обов'язково приносять користь - великий безлад.
Джейсон C

14

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

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


9

Здавалося б, помилкою було більше видаляти об’єкти візерунка, ніж використовувати їх. У початковому дизайні, здається, Null Object вирішив проблему. Це, можливо, не було найкращим рішенням.

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

Встановлення посилань у формі product.Price.toString ('c') порушує Закон Деметера . Я бачив всілякі проблеми з цією практикою, багато з яких стосуються нулів. Такий метод, як product.displayPrice ('c') міг внутрішньо обробляти нульові ціни. Так само product.Description.Current може оброблятися product.displayDescription (), product.displayCurrentDescription (). або product.diplay ("Поточний").

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

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


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

7

Питання здається помилковим у стільки моментів. Але кричущими є:

  • Для згаданого вами шаблону Null Object після зміни вимог ви змінюєте трохи коду. Це добре, але це не означає, що ви «вбивали» Нульовий об’єктний зразок (доречно, будьте обережні у своїй формулюванні. Це звучить занадто екстремально; деякі люди занадто параноїк не бачать цього зовсім смішним).

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

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

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


7

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

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

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

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

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

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

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

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

Редагувати

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


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

4

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

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

Міжособистісне

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

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

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

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

Технічні

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

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

Принцип, що стоїть за нульовим об'єктом, - це ідея інкапсуляції того, що змінюється . Ми приховуємо які зміни, тому нам не доводиться мати справу з цим скрізь. Тут нульовий об'єкт інкапсулював дисперсію в product.Priceекземплярі (я назву це Priceоб'єктом, і нульова ціна об'єкта буде NullPrice). Price- це доменний об’єкт, бізнес-концепція. Іноді в нашій бізнес-логіці ми ще не знаємо ціни. Це трапляється. Ідеальний випадок використання для нульового об’єкта. Prices мають ToStringметод, який виводить ціну або порожню рядок, якщо вона не відома (або NullPrice#ToStringповертає порожню рядок). Це розумна поведінка. Тоді вимоги змінюються.

Ми повинні вивести a nullна перегляд API або інший рядок у подання менеджерів. Як це впливає на нашу логіку бізнесу? Ну, це не так. У наведеному вище твердженні я два рази вживав слово 'view'. Це слово, мабуть, не було сказано прямо, але ми повинні навчити себе чути приховані слова в вимогах. То чому ж "погляд" має велике значення? Тому що це говорить нам, де зміни повинні насправді відбутися: на наш погляд.

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

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

if(product.Price.ToString("c").Length == 0) { // one way of many
    writer.write("Price unspecified [Change]");
} else {
    writer.write(product.Price.ToString("c"));
}

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

Можна сказати, що наша бізнес-логіка трохи змінилася, оскільки ми хочемо вивести рядки за замовчуванням, якщо не встановлена ​​ціна. Ми можемо зробити незначний підхід до нашого Price#ToStringметоду (фактично створити перевантажений метод). Ми можемо прийняти повернене значення за замовчуванням і повернути його, якщо ціна не встановлена:

class Price {
    ...
    // A new ToString method
    public string ToString(string c, string default) {
        return ToString(c);
    }
    ...
}

class NullPrice {
    ...
    // A new ToString method
    public string ToString(string c, string default) {
        return default;
    }
    ...
}

Тепер наш код перегляду стає:

writer.write(product.Price.ToString("c", "Price unspecified [Change]"));

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

Замість цього ми могли б створити IsSetметод, Priceякий повертає булевий:

class Price {
    ...
    public bool IsSet() {
        return return true;
    }
    ...
}

class NullPrice {
    ...
    public bool IsSet() {
        return false;
    }
    ...
}

Перегляд логіки:

if(product.Price.IsSet()) {
    writer.write(product.Price.ToString("c"));
} else {
    writer.write("Price unspecified [Change]");
}

Ми бачимо повернення умовного в огляді, але випадок є більш сильним для логіки бізнесу, яка визначає, чи встановлена ​​ціна. Ми можемо використовувати в Price#IsSetіншому місці зараз, коли у нас це є в наявності.

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

class PriceStringHelper {
    public PriceStringHelper() {}

    public string PriceToString(Price price, string default) {
        if(price.IsSet()) { // or use string length to not change the Price class at all
           return price.ToString("c");
        } else {
            return default;
        }
    }
}

Перегляд логіки:

writer.write(new PriceStringHelper().PriceToString(product.Price, "Price unspecified [Change]"));

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


3

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

Точки зміни документа (вони є ризиками) у вимогах

Багато складніших моделей дизайну (Null Object не так багато) містять концепцію захищених варіацій , тобто "Визначте точки передбачуваної зміни чи нестабільності; призначте відповідальність за створення стабільного інтерфейсу навколо них". Адаптер, відвідувач, фасад, шари, спостерігач, стратегія, декоратор тощо застосовують цей принцип. Вони «окупаються», коли програмне забезпечення потрібно розширити в розмірі очікуваної варіабельності, а «стабільні» припущення залишаються стабільними.

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

Крейг Ларман говорить про дві можливості застосувати захищені варіанти:

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

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

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

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

CONSTANTS у вихідному коді - проста форма ПВ

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


2

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

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

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

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

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