Ни для кого не секрет, что дублирование кода — это зло. Понимание принципа DRY (Don’t repeat yourself) указывают как требование в вакансиях разработчиков. Даже можно встретить такое выражение, что если задаётся вопрос по программированию из серии «Зачем это нужно?», смело можно отвечать «Чтобы избежать дублирования»)) С высокой вероятностью ответ окажется верным.
И действительно, наследование, полиморфизм, паттерны проектирования и многие другие вещи были придуманы именно для того, чтобы бороться с дублированием кода. Но что же в нём такого плохого?
Традиционно называют 2 проблемы.
- Кода становится элементарно больше. А значит, ухудшается структура и его сложнее воспринимать. Да и вообще всем же известно, что чем меньше кода, тем лучше.
- Очень сложно вносить изменения, не наплодив при этом кучу багов. Ведь трудно через полгода вспомнить все места, куда копипастился код. Особенно, если эти изменения были не в одном коммите. Получается классическая ситуация — изменения внесли не везде, какой-то участок пропустили. Здравствуйте, баги!
С дублированием принято бороться переиспользованием участков кода и созданием абстракций. И в теории это работает прекрасно. Но между теорией и практикой лежит огромная пропасть. Так ли всё обстоит в реальном мире?
Прежде всего, создание абстракции требует некоторого опыта и навыков, чтобы код был читаемым и понятным для других разработчиков. Нужно знать определённые паттерны, понимать, какие участки лучше обобщать и т.д. Для обычного джуна это может быть сложновато.
Но есть куда более опасная проблема. Разработчик не может заранее предвидеть, как будет в дальнейшем развиваться продукт. И очень может быть, что через каких-нибудь полгода-год нужно будет переделывать созданную абстракцию. Или скорректировать для пары нестандартных случаев. Вполне возможно, придётся удалять созданные абстракции и заново придумывать под новые условия. И времени и сил в таком случае потребуется намного больше, чем если нужно было бы просто поменять что-то в дублирующихся участках.
Ещё один минус такого подхода — код становится менее явным. Другому разработчику потребуется больше времени, чтобы понять, как всё устроено.
Так что же тогда делать? Получается, что копипастить плохо. Строить абстракции — иногда тоже такой себе вариант. Как поступать?
Прежде всего, признать, что мы все живём и работаем не в волшебном мире пони и единорогов. То, что ни в коем случае нельзя делать в теории, на практике иногда просто необходимо. А также, что бездумное следование какому-либо подходу до добра не доводит.
Так в каких же случаях допустимо дублировать код?
- В тестах. Тесты должны быть максимально простыми и понятными для восприятия. Использование обобщений и абстракций может сделать их менее явными и усложнить. Также в тестах не так критична самая главная опасность дублирования. Если вдруг разработчик забудет изменить какой-то участок скопипасченного кода, к серьёзным багам это вряд ли приведёт.
- С тестами разобрались. Но в каких случаях можно дублировать код там, где идёт работа с бизнес-логикой приложения. Для начала нужно оценить примерный срок жизни проекта. Если небольшой краткосрочный проект, то можно спокойно дублировать. Никаких ужасных последствий от этого не будет. Или, например, необходимо в максимально короткие сроки сделать прототип, чтобы показать заказчику или протестировать отклик пользователей. Тут главное скорость, а не качество кода. Поэтому можно обойтись и копипастой, ведь дальше прототипа продукт может и не пойти. В таком случае всем будет вообще без разницы, какие паттерны проектирования использовались при разработке.
Другое дело крупный долгосрочный проект. Лишний раз говнокодить — себе дороже. Впрочем, как и бездумно делать обобщения за счёт паттернов или метапрограммирования там, где это не особо-то и нужно. Как ни крути, но абстракции делают код менее явным. Но тут мы приходим к простому правилу.
Создание и поддержание абстракций требует временных затрат. Дублированный код также требует затрат, и чем больше копипаст, тем больше эти затраты. В итоге разработчику необходимо выбрать, что обойдётся дешевле: работать с абстракциями или с дубликатами. И на основе этого принимать решение.
В целом, особенно для начинающих разработчиков подойдёт следующий подход. По началу просто писать код и не обращать внимания на копипасты. Когда их станет три и больше, стоит задуматься, можно ли как-то избавиться от дублирования? Переиспользовать общие участки, например, сделать абстракцию и т.п. Если нужно будет потом вносить изменения, не будет ли проблем с этой абстракцией? Останется ли код понятным для других? И в зависимости от ответов на эти вопросы, выбирать дальнейший путь.
Подводя итоги, можно сделать следующие выводы:
- Нет никаких жёстких правил, которым обязательно нужно следовать. В любой ситуации стоит выбирать то, что будет рациональнее
- Не нужно плодить дублирующийся говнокод, объясняя это тем, что «так будет понятнее». К дублированию стоит прибегать тогда, когда поддержка такого кода будет дешевле, чем работа с абстракциями.
- На практике дублирование не всегда плохо, а обобщения, паттерны и метапрограммирование не всегда хорошо.
Автор статьи — Артемий Баумгартен, Full Stack разработчик. Артём занимается разработкой приложений для бизнеса при помощи Ruby On Rails и React/Vue. Главная цель в работе — сделать продукт, который будет эфективно решать необходимые бизнес-задачи.
[customscript]techrocks_custom_after_post_html[/customscript]
[customscript]techrocks_custom_script[/customscript]