Захист котла?


15

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

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

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


7
Аргументи проти дублікату коду (якщо припустити, що копіювальна табличка буде скопійована / вставлена): stackoverflow.com/a/2490897/1583
Oded

1
@Oded: Це правильно. Але ви неправильно прочитали питання. :) Він намагається подивитися, чи є що сказати за кодовою табличкою. Думаю, він дуже добре поінформований про недоліки.
Стівен Євріс

3
@StevenJeuris - я прекрасно прочитав питання. Ось чому я не опублікував відповіді. Я лише додаю до іншої сторони аргументу. Просто так в ОП є "легко сформований, добре продуманий аргумент минулого часу, який я розвинув для нього",
Одід,

2
Котельня може бути з естетичного вигляду: en.wikipedia.org/wiki/This_Is_the_House_That_Jack_Built
SK-логіка

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

Відповіді:


15

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

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

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

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


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

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

1
@Giorgio: Навпаки, це набагато більше, ніж просто моя думка; це думка переважної більшості людей, які коли-небудь намагалися її вивчити. І коли "важко читати" по суті є питанням думки, то факт, що ця думка настільки широко поділяється, робить її фактом.
Мейсон Уілер

1
@ Mason Wheeler: На те, як люди сприймають мови програмування, часто впливає їхній минулий досвід. Люди, які навчилися програмувати за Схемою, вважають, що С або Паскаль незграбні і важко читаються. З іншого боку, переважна більшість людей навчилася програмувати основними мовами.
Джорджіо

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

7

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

Скажімо, у вас є фрагмент коду, який говорить

public ForTheBar(Foo foo)
{
    Bar bar = foo.bar();
    return bar.BeFooed();
}

Це використовується приблизно у двох місцях у вашому коді.

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

І ти думаєш, "ну це просто".

public ForTheBar(Foo foo, bool shouldIGrommit)
{
    Bar bar = foo.bar();

    if (shouldIGrommit)
    {
        bar.BeGrommitted();
    }

    return bar.BeFooed();
}

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

Отже, ви просто зателефонували вищевказаному методу

Але тоді ваш користувач каже "добре, зачекайте, в третьому випадку ми хочемо, щоб ви Doodle Bar перед тим, як зателефонувати в BeFooed".

Без проблем, ти думаєш, я можу це зробити.

public ForTheBar(Foo foo, bool shouldIGrommit, bool shouldIDoodle)
{
    Bar bar = foo.bar();

    if (shouldIGrommit)
    {
        bar.BeGrommitted();
    }

    if (shouldIDoodle)
    {
        bar.BeDoodled();
    }

    return bar.BeFooed();
}

Раптом ваш код стає менше котлован. Можливо, ви мали б прийняти повторювані два рядки коду. На сьогоднішній день у вас було б три фрагменти коду, кожні 2-3 рядки довгі і вже не виглядають дуже повтореними.

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

Ще один аргумент, який я недавно чув, - це те, що код котла може іноді допомогти вам орієнтуватися в коді. Приклад, який ми обговорювали, - це, де ми видалили тонни кодового картографічного коду та замінили його на AutoMapper. Тепер це було аргументовано, оскільки все засноване на конвенції, ви не можете сказати IDE "Де встановлено цю властивість", і очікувати, що вона знатиме.

Я бачив, як люди сперечаються подібні речі щодо контейнерів IoC.

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


2
Я віддав перевагу другій частині вашої відповіді. ; p +1
Стівен Євріс

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

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

6

Еволюція ефективності

Ви починаєте з цього:

<p>
    <label for="field">My field</label>
    <input type="text" id="field">
</p>

тоді ви позбудетеся від усієї набридливої ​​котлової панелі і введете її у функцію:

  1. createFieldHtml( id, label )

    це добре, я рятую собі стільки рядків!

  2. createFieldHtml( id, label, defaultValue )

    Так, мені також потрібне значення за замовчуванням, яке було легко додати.

  3. createFieldHtml( id, label, defaultValue, type )

    круто, я можу використовувати його і для прапорців зараз

  4. createFieldHtml( id, label, defaultValue, type, labelFirst )

    Дизайнер UX сказав, що ярлик повинен бути після прапорця.

  5. createFieldHtml( id, label, defaultValue, type, labelFirst, isDate )

    тепер він надає інструмент вибору дати за потреби. Гм .. парами трохи виходять з рук

  6. createFieldHtml( id, label, defaultValue, type, labelFirst, isDate, containerCssClasses )

    був один випадок, коли мені потрібно додати класи CSS

  7. createFieldHtml( id, label, defaultValue, type, labelFirst, isDate, containerCssClasses, fieldCssClasses, disabled, clearAfter, helpText, uploadPath )

    ааааааааааааааааааа

На захист котла

Мені важко викласти це на словах, тому що це дійсно те, що я помічав зовсім недавно, тому я складу список:

  1. Мені здається, є певний страх мати повторювані лінії, які трохи розтягуються. Якщо це всього лише кілька рядків, це може бути зовсім не проблемою. деякі речі за своєю суттю "майже повторювані" (як приклад вище). Я бачу невеликий шанс оптимізуватись там у довгостроковій перспективі.
  2. Люди люблять кудись інкапсулювати функціональність; якщо ви дивитесь на це об’єктивно і здається, що це просто «приховує безлад» - будьте підозрілі! може бути час для старої хорошої котельні
  3. Коли у вас є функція, яка стає все більш потужною; що займає багато різних шляхів виконання залежно від вкладених даних і, в кінцевому рахунку, робить дуже мало - це може бути час роботи котла!
  4. Коли ви додасте шар абстракції поверх іншого шару абстракції, але лише для того, щоб ваш код був коротшим (базовий шар не передбачається змінювати) - час роботи котла!
  5. Коли у вас є функція, яка приймає стільки параметрів, що вам дійсно потрібно мати названі параметри - можливо, це час бойлерної панелі.

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

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


Оновлення : я щойно натрапив на статтю, яка дає мій приклад вище фактичної назви: "занадто DRY анти-шаблон".

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

Це коротке та цікаве прочитання, статтю ви можете знайти тут: Занадто сухий анти-візерунок


1
"Коли ви додаєте шар абстракції поверх іншого шару абстракції, але просто для того, щоб ваш код був коротшим" Правда, слід додати шари абстракції лише тоді, коли є можливість повторного використання.
Стівен Євріс

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

4

Я зневажаю код котла, але те, що можна видалити код котла, не завжди означає, що це найкращий шлях.

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

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

Рамка ВПФ добре зафіксована. Він належним чином документує, як написати код котла. Спроба видалити цей код котла - це приємна вправа, і те, що, безумовно, варто вивчити, але досягнення того ж рівня "польської", що й msdn, потребує тривалого часу, якого ми не завжди маємо.


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

3
кожен раз, коли я торкаюся WPF та цих властивостей залежності, я завжди хочу, щоб у C # було щось таке просте, як макроси C ++. Впевнені, що макроси зловживають в чужих руках, але вони можуть усунути так багато повторень тут. Мені доведеться поглянути на ваші рамки AOP наступного разу, коли я побажаю цих макросів :)
DXM

@DXM Якщо ви це зробите, і це трапляється аварійно, не забудьте звинувачувати мене і публікувати помилки. ; p
Стівен Євріс

Фрагмент коду працював для мене досить добре для властивостей залежності.
Кодизм

@Codism: Ну, вони є рішенням, але я зневажаю їх теж . :)
Стівен Євріс

1

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

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


2
Як це аргумент на користь котла ?
Кріс Вессілінг

0

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

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

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

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


-3

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

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