Чи повинен мій код бути сухим чи читаним, якщо він не може бути обом?


14

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

Мій останній приклад: Моя програма приймає дані, і через жорсткі вказівки щодо формату, вона може легко визначити, чи слід вводити чи розшифровувати вхід. Для спрощення, коли ключ шифрування та повідомлення конвертуються / генеруються на сумісність, справа в тому, щоб відняти ключ із зашифрованого повідомлення або додати ключ до незашифрованого повідомлення, щоб отримати бажаний вихід (думайте про ключ як шифрування, повідомлення + шифрування = код; код - шифрування = повідомлення). Положення DRY говорить мені, що я повинен перетворити своє зашифроване повідомлення інакше від мого незашифрованого повідомлення, щоб функція, яка приймає ключ шифрування і застосовувала його до повідомлення, ніколи не потребувала розрізнення. Я виявив, що це означає, що мені потрібні деякі вкладені, якщо заяви у функції, але логіка здається суцільною. Однак цей код не легко читається.

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

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

Поки я схильний наголошувати на стислій, DRY-коді над читабельним кодом.


2
Перше, що можна використовувати, сухе друге, третє читати. Високопридатний код призводить до легко читаного споживчого коду, який легше відповідає DRY та читається. Ось чому ви хочете взяти неприємні складності і покласти їх десь із приємним API, якщо вони не можуть бути покращені; принаймні, код, який взаємодіє з ними, буде позбавлений від поганого, а також при такому підході.
Джиммі Хоффа

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

2
Не дублікат. Краткий v. Читабельний і DRY v. Читабельний - це два дуже різних порівняння. Не бути сухим набагато небезпечніше, ніж бути лаконічним.
djechlin

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

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

Відповіді:


20

DRY - це настанова, а не релігія. Ті, хто переносить це до сухих, перш за все, завели занадто далеко.

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

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

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

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


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

1
@lutze Я перл, а іноді і рубіновий кодер, і, безумовно, можу зрозуміти спокусу написати розумний код там. Версія цієї відповіді перед публікацією містила цитату Ларрі Уолла про hubris - я вважаю, що це дуже важлива чеснота при роботі з кодом, який якийсь день буде підтримуватися. Через можливу лаконічність мов іноді важко отримати перевагу, щоб написати більше коду, а не намагатися за розумний щільний код ... поки вам не доведеться його підтримувати.

17

Я не впевнений, виходячи з того, що ви розумієте СУХО. DRY-код не є тим самим, як стислий. Досить часто відбувається навпаки.

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

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

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


Чудові моменти, я дійсно трохи поєднав принцип DRY з метою стислого коду.
люце

12

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

Метою як читабельності, так і DRY є ремонтопридатність .

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

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

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

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

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

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

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

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

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

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


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

+1. Зараз я маю справу із системою, яка зловживала копією та наклеювала до смішної міри. Створення одного методу з копіюваного / вставленого коду було видалено понад 400 рядків з одного з моїх занять сьогодні. На жаль, я знайшов це методом 900 рядків ...
KChaloux

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

7

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

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

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


2

Хоча я не впевнений у тому, що саме спричиняє проблему, мій досвід полягає в тому, що коли ви виявляєте, що СУХА та читабельність є конфліктними, це говорить про те, що настав час щось переробляти.


0

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


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

0

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

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

Повторний код слід або переробити на власний метод, або витягнути у власний клас.

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

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