Якщо я спробую створити новий метод для обробки B по-різному, він буде викликаний для дублювання коду.
Не всі дублювання коду створюються рівними.
Скажімо, у вас є метод, який бере два параметри і додає їх разом під назвою total()
. Скажіть, у вас є інша названа add()
. Їх реалізація виглядає абсолютно однаково. Чи повинні вони бути об'єднані в один метод? НІ!!!
Принцип " Не повторюй сам" або " БУЙ" не полягає у повторенні коду. Йдеться про поширення рішення, ідеї навколо, щоб, якщо ви коли-небудь змінили свою думку, вам доведеться переписувати всюди, де ви поширюєте цю ідею навколо. Blegh. Це жахливо. Не робіть цього. Замість цього використовуйте DRY, щоб допомогти вам приймати рішення в одному місці .
Принцип НУМИ (не повторюйте себе) говорить:
Кожна частина знань повинна мати єдине, однозначне, авторитетне представлення в системі.
wiki.c2.com - Не повторюйтеся
Але DRY може бути пошкоджена звичкою сканувати код, шукаючи подібну реалізацію, схоже, що це копія та вставлення десь в іншому місці. Це мозкова мертва форма СУХОГО. Чорт, ти можеш це зробити за допомогою інструменту статичного аналізу. Це не допомагає, оскільки він ігнорує суть DRY, яка полягає в тому, щоб тримати код гнучким.
Якщо мої загальні вимоги зміниться, можливо, доведеться змінити свою total
реалізацію. Це не означає, що мені потрібно змінити свою add
реалізацію. Якщо якийсь губер згладив їх в один метод, я зараз відчуваю трохи зайвих болів.
Скільки болю? Звичайно, я міг просто скопіювати код і зробити новий метод, коли мені це потрібно. Так що нічого не так? Маларкі! Якщо нічого іншого ти не коштував мені доброго імені! Хороші імена важко придумати і не реагувати добре, коли ви поспішаєте з їх значенням. Хороші імена, які роблять зрозумілий намір, важливіші, ніж ризик, що ви скопіювали помилку, яку, чесно кажучи, легше виправити, коли ваш метод має правильну назву.
Тому моя порада - перестати дозволяти реакціям на поштовхи колін на подібний код зав'язувати вашу кодову базу у вузлах. Я не кажу, що ви вільні ігнорувати факт існування методів, а замість цього мимоволі копіюйте та вставляйте. Ні, кожен метод повинен мати прокляте гарне ім'я, яке підтримує одну ідею, про яку йдеться. Якщо його реалізація збігається з реалізацією якоїсь іншої гарної ідеї, то кого, до чорта, хвилює?
З іншого боку, якщо у вас є sum()
метод, який має ідентичну або навіть іншу реалізацію, ніж total()
все-таки колись ваші загальні вимоги змінюються, ви повинні змінити, sum()
то є хороший шанс, що це одна і та ж ідея під двома різними назвами. Код був би не більш гнучким, якби вони були об'єднані, його було б менш заплутано у використанні.
Що стосується булевих параметрів, так це неприємний запах коду. Мало того, що контрольний потік створює проблему, ще гірше - це видно, що ви скоротили абстракцію в поганій точці. Абстракції повинні зробити речі більш простими у використанні, а не складнішими. Передача bools методу управління його поведінкою - це як створення секретної мови, яка визначає, який метод ви дійсно викликаєте. Ов! Не робіть цього мені. Дайте кожному методу своє ім'я, якщо у вас немає сумлінного поліморфізму .
Тепер ви, здається, вигоріли від абстракції. Це занадто погано, оскільки абстракція - це чудова річ, коли робиться добре. Ви багато використовуєте, не замислюючись над цим. Кожен раз, коли ви керуєте автомобілем, не розуміючи системи стійки і шестірні, кожен раз, коли ви використовуєте команду друку, не замислюючись про переривання ОС, і кожен раз, коли ви чистите зуби, не замислюючись про кожну окрему щетину.
Ні, проблема, з якою вам здається, - це погана абстракція. Абстракція створена для того, щоб служити іншим цілям, ніж ваші потреби. Вам потрібні прості інтерфейси до складних об'єктів, які дозволяють вам вимагати виконання ваших потреб, не розуміючи цих об'єктів.
Коли ви пишете код клієнта, який використовує інший об'єкт, ви знаєте, що ваші потреби та що вам потрібно від цього об’єкта. Це не так. Ось чому клієнтському коду належить інтерфейс. Коли ти клієнт, нічого не може сказати тобі, які твої потреби, крім тебе. Ви виставляєте інтерфейс, який показує, які ваші потреби, і вимагаєте, щоб все, що вам було передано, відповідало цим потребам.
Це абстракція. Як клієнт, я навіть не знаю, про що я говорю. Я просто знаю, що мені потрібно від цього. Якщо це означає, що вам доведеться щось обернути, щоб змінити його інтерфейс, перш ніж вручити мені це штрафом. Мені все одно. Просто роби те, що мені потрібно зробити. Перестаньте це ускладнювати.
Якщо мені доведеться заглянути всередину абстракції, щоб зрозуміти, як її використовувати, абстракція не вдалася. Мені не потрібно було знати, як це працює. Просто, що це працює. Назвіть це добре ім'я, і якщо я загляну всередину, я не повинен дивуватися тому, що знаходжу. Не змушуйте мене дивитися всередину, щоб пам'ятати, як ним користуватися.
Коли ви наполягаєте на тому, що абстракція працює таким чином, кількість рівнів позаду не має значення. Поки ти не дивишся за абстракцію. Ви наполягаєте на тому, що абстракція відповідає вашим потребам, не адаптуючись до її потреб. Для цього він повинен бути простим у використанні, мати гарне ім’я та не протікати .
Це ставлення, яке породило ін'єкцію залежностей (або просто посилання, якщо ви стара школа, як я). Це добре працює з перевагою складу та делегування над спадщиною . Ставлення випливає з багатьох імен. Моя улюблена річ - не кажи .
Я міг би вас заглушити в принципах цілий день. І це здається, що вже є ваші колеги. Але ось у чому річ: на відміну від інших інженерних галузей, це програмне забезпечення має менше 100 років. Ми все ще розгадуємо це. Тож не дозволяйте, щоб хтось із залякуючим звучанням книги вчився знущатися над написанням коду, який важко читати. Слухайте їх, але наполягайте, що вони мають сенс. Не віри нічого на віру. Люди, які кодують якимось чином лише тому, що їм сказали цей шлях, не знаючи, навіщо робити найбільші помилки з усіх.