Чи є виняткові випадки, коли ми можемо прийняти повторюваний код?


57

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

API агентства є найповнішим, оскільки він має всі функціональні можливості. Потім трохи менший Home API, а потім мобільний API.

Тут архітектори створили загальний рівень (міжканальні послуги EJB, якими користуються всі API). Але тоді API відрізняються.

Зараз немає великої різниці між API. Велика команда почала з агентського каналу, і ми зараз адаптуємо її для домашнього каналу. Ми просто збагачуємо об’єкти спеціально для домашнього додатка. В іншому випадку код на 95% схожий між API. API створений на базі Spring MVC , і він має (контролери, моделі та деякі утиліти).

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

Чи є випадок, коли нам слід прийняти повторюваний код?


22
І якщо три завтра вниз, вони вирішать, що хочуть послідовного доступу до даних та представлення між усіма API-програмами ... ну ... "Боріться!"
Becuzz

26
Дублікат коду не обов'язково поганий. Приказка "DRY - ворог роз'єднання" не може бути наголошена достатньо. Говорив, що проектування на майбутнє, а не зараз, насправді дуже погана річ. Це майбутнє майже ніколи не збудеться. Натомість спроектуйте дуже розв'язане рішення, охоплене хорошими автоматизованими тестами для того, що потрібно зараз. Тоді, в майбутньому, якщо потрібно щось інше, змінити буде простіше.
Девід Арно

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

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

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

Відповіді:


70

Дублювання може бути правильним, але не з цієї причини.

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

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

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


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

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

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

Приклад , де дублювання корисно (і «видалення його yould бути в цілому більш дорогим підприємством ») вводиться valdation в веб - додатках: Ми використовуємо перший (можливо спрощену) перевірку на клієнті , так що користувач отримує негайну зворотний зв'язок про проблеми; і тоді ми робимо таку ж (або більш ретельну) перевірку на сервері, оскільки клієнтам не можна довіряти.
Хаген фон Ейтцен

3
@HagenvonEitzen Але це навіть не потрібно дублювати, залежно від технічного стеку. Наприклад, у браузері може бути вхід перевірки JavaScript, а потім перевірка Java на сервері, щоб у вас є дублюється функціональність. Але якщо ви запустили Node.js на сервері, ви можете використовувати ту саму перевірку JavaScript у браузері та на сервері, виключаючи дублювання. Ви все ще хочете, щоб код працював у кількох місцях (довірене та ненадійне середовище), але код не обов'язково повинен бути дублювати.
Джошуа Тейлор

87

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

дублювання набагато дешевше, ніж неправильна абстракція

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

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


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

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

34

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

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

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

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

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


3
Ще більший попереджувальний знак, ніж "якби завтра" для мене - це "Це ніколи не зміниться".
abuzittin gillifirca

@abuzittingillifirca: і що це стосується питання чи моєї відповіді?
Док Браун

1
Я оскаржую ваш перший абзац.
abuzittin gillifirca

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

13

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

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


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

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