Показаны сообщения с ярлыком Typical Copy-Paste. Показать все сообщения
Показаны сообщения с ярлыком Typical Copy-Paste. Показать все сообщения

четверг, 9 июля 2026 г.

Typical Copy-Paste, Cargo Cult Programming

Английское наименование: 

Typical Copy-Paste (или Cargo Cult Programming в более широком смысле).

Русская трактовка: Это антипаттерн разработки, при котором разработчик копирует и вставляет существующий фрагмент кода для решения новой задачи без полного понимания того, как этот код работает. При этом он либо оставляет большую часть логики нетронутой, либо вносит лишь минимальные, поверхностные изменения.

Термин «типовой» здесь подчеркивает, что такой подход часто становится стандартной практикой («так все делают») внутри команды или проекта, превращаясь в норму плохого тона.

Почему это происходит?

  • Дедлайны. Самый быстрый способ заставить что-то работать — скопировать похожий рабочий пример.
  • Сложность исходного кода. Разработчик не понимает абстракцию или шаблон проектирования, заложенный в оригинале, поэтому предпочитает просто дублировать его.
  • Отсутствие подходящей абстракции. В системе нет готовой функции или класса, который можно было бы переиспользовать, а создавать новый ради нескольких строк кажется избыточным.

Чем опасен «типовой копипаст»

  1. Раздувание кодовой базы. Вместо одной точки правки у вас появляются десятки одинаковых фрагментов. Если в алгоритме найдется ошибка, ее придется исправлять во всех местах, где был сделан копипаст.
  2. Эффект разрозненных изменений. Со временем копии начинают незаметно отличаться друг от друга. В одну копию внесли фикс производительности, в другую — изменили условие проверки, в третью забыли добавить обработку ошибки. Код теряет консистентность.
  3. Скрытые баги. Часто вместе с полезным кодом копируются переменные, константы или побочные эффекты, которые относятся к старой задаче, но совершенно не нужны в новой. Это приводит к трудноуловимым ошибкам состояния.
  4. Трудности рефакторинга. Инструменты автоматизированного рефакторинга работают плохо на сильно дублированном коде, так как не могут гарантировать корректность изменений во всех копиях.

Как отличить копипаст от осознанного шаблона

Важно различать вредный копипаст и намеренное использование паттернов:

  • Копипаст: вы скопировали метод CalculateOrderTotal(), потому что вам нужно рассчитать сумму корзины, но вы даже не посмотрели, какие поля объекта Order он использует. Вы просто надеетесь, что сработает.
  • Шаблон/Идиома: вы берете за основу структуру уже написанного BackgroundService, потому что понимаете принципы работы IHostedService в .NET. Вы удаляете специфичную бизнес-логику старого сервиса и вписываете свою, сохраняя архитектурный каркас. Это называется программированием по аналогии на основе общих принципов.

Связь с вашей архитектурой

В контексте ваших поведений (Behaviors) риск копипаста очень высок. Например, если разработчику нужно создать новое поведение для обработки события UserUpdated, он может взять файл PaymentBehavior.cs, скопировать его целиком, переименовать класс и поменять тело метода HandleAsync.

Результат: в проекте появляется два огромных класса, у которых 90% кода (конструктор, зависимости, логика подписки через BehaviorRouter) абсолютно идентичны.

Как бороться с этим в вашем случае? Именно для борьбы с таким «типовым копипастом» и предназначены ваши базовые классы-шаблоны (BehaviorTemplate<T>, EventBehaviorTemplate<T>). Они инкапсулируют всю скучную обвязку (работу с шиной, жизненный цикл), заставляя разработчика писать только чистую реализацию в методе HandleEventAsync.

Если же поведения всё равно получаются слишком похожими, это сигнал о том, что пора поднять общую абстракцию выше — например, создать промежуточный базовый класс вроде RetryableEventBehavior<T>, который будет содержать логику повторных попыток с экспоненциальным бэкоффом, чтобы её не приходилось копировать вручную из поведения в поведение.