Що повинно мати перевагу: YAGNI чи хороший дизайн?


76

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

Ось конкретний приклад того, що я маю на увазі: у мене є шар доступу до даних, який охоплює набір збережених процедур, який використовує рудиментарний шаблон стилю репозиторію з основними функціями CRUD. Оскільки існує декілька методів, необхідних усім моїм сховищам, я створив загальний інтерфейс для моїх сховищ, званий IRepository. Однак я створив інтерфейс "маркера" (тобто інтерфейс, який не додає нових функціональних можливостей) для кожного типу сховища (наприклад ICustomerRepository) і конкретний клас реалізує це. Я зробив те саме, що і з реалізацією Factory, щоб створити бізнес-об’єкти з DataReaders / DataSets, повернуті за збереженою процедурою; підпис мого класу сховища має вигляд приблизно так:

public class CustomerRepository : ICustomerRepository
{
    ICustomerFactory factory = null;

    public CustomerRepository() : this(new CustomerFactory() { }

    public CustomerRepository(ICustomerFactory factory) {
        this.factory = factory;
    }      

    public Customer Find(int customerID)
    {
        // data access stuff here
        return factory.Build(ds.Tables[0].Rows[0]);
    }
}

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

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


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

10
Навіть незважаючи на те, що Google це тривіально, хтось повинен згадати, що YAGNI означає "вам це не потрібно"
thedaian

1
Я думаю, що якщо ви писали такі нові класи, ви хочете додати кілька одиничних тестів. Навіть якщо ваші колеги не будуть керувати ними. Принаймні пізніше ви можете сказати: "Подивіться! Мої одиничні тести застали це, коли ви порушили мій код! Подивіться, наскільки чудові одиничні тести!" У такому випадку зробити так, як зробити його макетом, варто тут. (Хоча я вважаю за краще, якщо об’єкт можна буде глузувати без визначення інтерфейсу)
Winston Ewert

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

3
@Anthony А чи глузування завжди виправдовує додаткову складність, яку він тягне за собою? Знущання - це чудовий інструмент, але його корисність теж повинна бути зважена з витратами, а іноді масштаб нахиляється в інший бік через надлишок непрямості. Звичайно, є інструменти, які допоможуть отримати додаткову складність, але вони не зроблять складність. Здається, зростає тенденція трактування «тестування за будь-яку ціну» як даного. Я вважаю, що це помилково.
Конрад Рудольф

Відповіді:


75

Чи є хороший спосіб досягти компромісу між належним дизайном програмного забезпечення та не переробляти рішення?

ЯГНІ.

Я міг би пожертвувати трохи гарним дизайном

Неправдиве припущення.

і базовий інтерфейс, а потім єдиний бетон,

Це не "жертва". Те є хороший дизайн.


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

5
@Newtopian: люди мають неоднозначні почуття щодо цього щодо останніх продуктів Apple. :)
Roy Tinker

14
У мене величезна проблема з таким видом відповідей. Чи "X правдиво, тому що Y каже це, а Y добре підтримується спільнотою"? Якби хтось у реальному житті змагався проти ЯГНІ, ви б показали йому цю відповідь як аргумент?
vemv

2
@vemv. Ніхто тут не б’є проти ЯГНІ. Все, що Л.Лотт сказав, було те, що сприйняте протиріччям ОП між двома гідними цілями є помилкою. BTW, чи знаєте ви будь-якого активного розробника в сучасному світі програмного забезпечення, який би гнівався проти YAGNI? Якщо ви працюєте над реальними проектами, ви знаєте, що вимоги постійно змінюються і що користувачі та менеджери, як правило, не знають, що вони роблять чи не хочуть, поки ви не поставите це перед ними. Виконувати необхідне РОБОТИ роботи - навіщо витрачати час, енергію та витрачати гроші (або ризикувати своєю роботою), написавши код, який намагається передбачити майбутнє?
Вектор

6
Моя думка не про YAGNI - це про якість відповідей. Не хочу сказати, що хтось, зокрема, робив рейтинг, це було частиною моїх міркувань. Прочитайте ще раз.
vemv

74

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

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


8
Я вважаю, що "уникнення коду YAGNI" є неоднозначно неоднозначним. Це може означати код, який вам не знадобиться, або код, який дотримується принципу YAGNI . (Порівняй 'ПОЦЕЛУЙ код')
sehe

2
@sehe: Це зовсім не неоднозначно (тоді як "дотримується принципу YAGNI" відверто самопоперечне), якщо ви його промовляєте: що може означати "код, який вам не знадобиться", але це означає, але код, який вам не знадобиться?
Майкл Боргвардт

1
Я збираюся надрукувати цю відповідь великим шрифтом і повісити її там, де її можуть прочитати всі космонавти архітектури. +1!
kirk.burleson

1
+1. Я все ще пам'ятаю свій перший корпоративний проект, який мені дали підтримку та додали нові функції. Перше, що я зробив - це видалити 32 000 рядків непотрібного коду з 40 000 лінійної програми, не втрачаючи жодної функціональності. Оригінальний програміст був звільнений незабаром після цього.
EJ Brennan

4
@vemv: читати "непотрібно" як "в даний час не використовується, крім тривіального", тобто випадку YAGNI. А "перенапружений" є дещо більш специфічним, ніж "поганий". Зокрема, це означає "складність, зумовлену теоретичними концепціями чи уявними можливими вимогами, а не конкретними сучасними вимогами".
Майкл Боргвардт

62

YAGNI і SOLID (або будь-яка інша методологія проектування) не є взаємовиключними. Однак вони є майже полярними протилежностями. Вам не доведеться дотримуватися 100% жодного з них, але буде деякий прийом і отримання; чим більше ви дивитесь на сильно абстрагований візерунок, який використовує один клас в одному місці, і кажете YAGNI та спрощуєте його, тим менш ТВОРНИМ стає дизайн. Зворотний може бути і правдою; багато разів у розробці проект реалізовується СОЛІДНО "на віру"; ви не бачите, як вам це знадобиться, але у вас просто є уявлення. Це може бути правдою (і все більше шансів бути правдою, чим більше досвіду ви набудете), але це також може поставити вас у стільки технічного боргу, як і шахрайський підхід "зроби це легкий"; замість бази коду DIL "спагетті-код", ви можете отримати "код лазаньї", маючи стільки шарів, що просто додавання методу чи нового поля даних стає щоденним процесом проходження через проксі-сервіси та слабко пов'язані залежності лише однією реалізацією. Або ви можете отримати "код равіолі", який випускається такими невеликими шматками, що рухаються вгору, вниз, вліво або вправо в архітектурі, проводять 50 методів з 3 рядками в кожному.

Я говорив це в інших відповідях, але ось так: На першому ж шляху, змусьте це працювати. По другому проходу зробіть його елегантним. На третьому проході зробіть це ТВЕРДО.

Порушення цього:

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

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

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

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


Я другий дивовижний.
Філіп Дупанович

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

На четвертому переході зробіть це ДУЖЕ.
Річард Ніл Ілаган

@KeithS: Схоже, Джон Кармак зробив щось подібне: "вихідний код Quake II ... об'єднайте Quake 1, Quake World і QuakeGL в одну прекрасну архітектуру коду". fabiensanglard.net/quake2/index.php
13

+1 Думаю, я назву правило ур: "Практичний рефакторинг" :)
Сонго

31

Замість будь-якого з них я віддаю перевагу WTSTWCDTUAWCROT?

(Що найпростіше, що ми можемо зробити, це корисно, і ми можемо випустити в четвер?)

Простіші абревіатури є в моєму списку справ, але вони не є пріоритетними.


8
Ця абревіатура порушує принцип YAGNI :)
riwalk

2
Я використовував саме потрібні мені листи - не більше і не менше. У такий спосіб я схожий на Моцарта. Так. Я Моцарт акронімів.
Майк Шеррілл 'Відкликання котів'

4
Я ніколи не знав, що Моцарт був жахливим у створенні абревіатур. Я щодня дізнаюся щось нове на сайті SE. : P
Камерон Макфарланд

3
@Mike Sherrill 'CatRecall': Можливо, варто поширити це на WTSTWCDTUWCROTAWBOF = "Що найпростішого, що ми можемо зробити, це корисно, ми можемо випустити в четвер і не зламаємось у п’ятницю?" ;-)
Джорджіо

1
@ Stargazer712 ні :) це порушує POLA.
v.oddou

25

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

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

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


15

Вони не конфліктують, ваші цілі неправильні.

Що ви намагаєтеся зробити?

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

Тепер ми доходимо до конфлікту, як ми покриваємо всі випадки, якщо ми не пишемо справ, які ми не збираємося використовувати?

Ось як виглядає ваша проблема.

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

Отже, що це рухає?

  1. Ви не знаєте, що вам не потрібно
  2. Ви не хочете витрачати час і розмивати свій код

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

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

Давайте переосмислимо все це

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

Чи є хороший спосіб досягти компромісу між належним дизайном програмного забезпечення та не переробляти рішення?

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

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


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

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

Ем ..... Я думаю, що головною метою було б "ти хочеш мати гарний, цінний продукт"?
sehe

@sehe, це не його рішення: с.
інкогніто

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

10

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


1
+1 за корисний коментар щодо актуальної проблеми, а не лише про космічну битву та / або кохання між хорошим дизайном та YAGNI.
пср

10

Питання ставить помилкову дилему. Належне застосування принципу ЯГНІ не є якоюсь непов'язаною річчю. Це один з аспектів хорошого дизайну. Кожен із принципів SOLID - це також аспекти хорошого дизайну. Ви не завжди можете повністю застосовувати кожен принцип у будь-якій дисципліні. Проблеми в реальному світі накладають багато сил на ваш код, а деякі з них підштовхують до протилежних напрямків. Принципи дизайну повинні враховувати все це, але жодна жменька принципів не може відповідати всім ситуаціям.

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

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

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

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

Існує 5 принципів СОЛІД, які слід переглянути. S - єдина відповідальність. Це нічого не говорить про інтерфейс, але це може сказати щось про ваші конкретні класи. Можна стверджувати, що обробка самим доступом до даних може бути відповідальною за один або декілька інших класів, тоді як відповідальність репозиторіїв полягає в перекладі з неявного контексту (клієнтський сховище неявно для суб'єктів Замовника) в явні виклики до узагальнений API доступу до даних із зазначенням типу юридичної особи Замовника.

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

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

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

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

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

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

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


Я думаю, що більшість дискусій на цій сторінці виключає 2 великих претендентів на "низьку зв'язок" та "високу згуртованість" принципів GRAS. Дорожчі дизайнерські рішення випливають із принципу "низької муфти". Як і коли "активувати" SRP + ISP + DIP заради низької зв'язку. Приклад: один клас -> 3 класи за схемою MVC. Або навіть дорожче: розділити на .dll / .so модулі / збірки. Це дуже дорого через наслідки побудови, проектів, складання списків, побудови сервера, доповнень до файлів з джерелами ...
v.oddou

6

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

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


2

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

Ще одна думка, можливо, іноді те, що вам потрібно, - це не хороший дизайн, а достатній дизайн. Ось дуже цікава послідовність дописів на тему:


Ваше перше та третє посилання переходять на одне й те саме місце.
Девід Торнлі

2

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

Що забороняє вам CustomerFactoryспочатку бути класом, а пізніше змінювати його на інтерфейс, який буде реалізований DefaultCustormerFactoryабо UberMegaHappyCustomerPowerFactory3000? Єдине, що вам потрібно буде змінити - це місце, де реалізація отримує екземпляри. А якщо у вас є менш менш хороший дизайн, то це максимум місця.

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

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

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

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


0

Ви створюєте interfaceпередбачувані кілька впроваджень у майбутньому. Ви також можете мати I<class>для кожного класу у своїй кодовій базі. Не варто.

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

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

YAGNI каже, що не писати код, перш ніж його потрібно записати.

Хороший дизайн говорить про використання абстракції.

Ви можете мати і те, і інше. Клас - це абстракція.


0

Чому інтерфейси маркера? Мене вражає те, що він робить не що інше, як "маркування". З різним "тегом" для кожного типу заводу, який сенс?

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

Інтерфейси призначені для обробки речей на основі спільного. Але інтерфейси спеціальних маркерів a) не додають поведінки. і б) змусити вас впоратися з їх унікальністю.

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

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


0

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

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

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