Дурний DRY

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

Неправильне розуміння DRY – Don’t Repeat Yourself

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

З цим важко не погодитися. Проте, декотрі розробники йдуть трохи далі і намагаються замінити декілька схожих функцій на одну універсальну, яка підходить для усіх попередніх випадків використання. Саме у цьому криється зло. Таке слідування принципу DRY я буду надалі називати “дурним DRY”.

AHA! Анти-патерн “Дивна деталь”

Колись я сформулював анти-патерн “Дивна деталь”, про який писав у телеграм-каналі ITRampage. Пізніше я, можливо, напишу окрему публікацію про нього, але вже зараз доречно його згадати, оскільки дурне слідування DRY також породжує дивні деталі.

Уявіть, що у Вашого авто зламалося бічне дзеркало. Ви відвезли авто до центру обслуговування і Вам сказали, що авто можна забрати вже наступного дня. Ви приходите наступного дня і вам кажуть, що аби замінити дзеркало, потрібно також замінити поршні у двигуні та задню фару з протилежного боку і це займе по часу два тижні. – Якого …?! – Кажете Ви!

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

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

Для запобігання виникненню дивних деталей був створений підхід AHA (Avoid Hasty Abstractions – уникайте поспішних абстракцій), згідно якому, дублювання краще за погану абстракцію і з цим також важко не погодитися.

Дурний DRY породжує складніший для розуміння код

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

Дурний DRY породжує менш ефективний код

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

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

Дурний DRY – це марнотратсво часу (тому і дурний)

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

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

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *