Фраза сидит в вашей кодовой базе как бомба замедленного действия с перегоревшим светодиодным таймером. Никто не помнит, кто её установил, зачем она там и когда стала «принятым порядком вещей». Но она есть — устаревшие шаблоны, архитектурные решения и процессы, которые с течением времени и из-за инерции учреждения превратились в абсолютную истину. Самая опасная фраза в инженерии — это не синтаксическая ошибка или исключение нулевого указателя. Она гораздо тише и коварнее: «Мы всегда делали это так».

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

Почему эта фраза — тихий убийца

Позвольте мне описать сценарий, через который вы, вероятно, проходили. Вторник, утро. Вы просматриваете чей-то запрос на включение, и замечаете, что используется шаблон, который кажется, ну, неэффективным. Вы спрашиваете, почему, и ответ приходит быстрее, чем вы успеваете сказать «технический долг»: «Так мы всегда строили это».

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

Опасность исходит не от самого шаблона — шаблоны являются нейтральными инструментами. Опасность исходит от нерассмотренных допущений. Когда мы перестаём подвергать сомнению унаследованные решения, мы перестаём заниматься проектированием и начинаем слепо копировать. Мы становимся программистами по поддержке собственной архитектуры, заменяя компоненты без понимания структурной целостности всей системы.

Скрытые издержки

Проблема проявляется тремя коварными способами:

Деградация производительности: тот шаблон запросов к базе данных, который имел смысл при 10 тысячах записей? Теперь он работает с 10 миллионами. Но мы продолжаем его использовать, потому что, ну, так мы делаем запросы. Я видел, как команды годами поддерживали неэффективные шаблоны доступа к базе данных просто потому, что первоначальное решение лежало в чьей-то голове и ушло вместе с ним.

Уязвимости безопасности: механизмы аутентификации, которые были разумными в 2015 году, становятся катастрофическими в 2026 году. Однако системы продолжают их использовать, потому что «мы всегда аутентифицировались таким образом». Я проводил аудит производственных систем, всё ещё использующих устаревшие криптографические библиотеки, поддерживаемые не из-за необходимости, а из-за институциональной амнезии.

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

Анатомия стагнации

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

┌─────────────────────────────────────────────────────────────┐
│ Решение принято (2016)                                      │
│ «Мы будем использовать Redis для хранения сессий»            │
│ (В то время имело смысл, идеальные требования)               │
└─────────────┬───────────────────────────────────────────────┘
              │
              ↓
┌─────────────────────────────────────────────────────────────┐
│ Институционализация (2017–2019)                             │
│ Шаблон скопирован в 15 различных сервисов                   │
│ Никто больше не задаёт вопросов                             │
└─────────────┬───────────────────────────────────────────────┘
              │
              ↓
┌─────────────────────────────────────────────────────────────┐
│ Потеря знаний (2020–2022)                                   │
│ Первоначальный автор решения покидает компанию               │
│ Логика уходит вместе с ним                                  │
└─────────────┬───────────────────────────────────────────────┘
              │
              ↓
┌─────────────────────────────────────────────────────────────┐
│ Накопление технического долга (2023–2026)                   │
│ Новые требования конфликтуют с шаблоном                     │
│ «Мы всегда делали это так»                                  │
│ Инженеры тратят 6 недель на борьбу с системой               │
└─────────────┬───────────────────────────────────────────────┘
              │
              ↓
┌─────────────────────────────────────────────────────────────┐
│ Хрупкость системы                                           │
│ Уловки строятся на уловках                                  │
│ Архитектура становится карточным домиком                   │
└─────────────────────────────────────────────────────────────┘

Вот диаграмма механизма, показывающая, как это происходит:

graph TD A["Начальное решение
Звуковое обоснование
Идеально для контекста"] --> B["Решение становится
Стандартом команды"] B --> C["Документация
Становится скудной"] C --> D["Первоначальное обоснование
Забывается"] D --> E["Предположения
Становятся невидимыми"] E --> F["Контекст меняется
Требования эволюционируют"] F --> G["Конфликт между
Шаблоном и потребностями"] G --> H{"Кто-нибудь
Задаёт вопросы?"} H -->|Нет| I["'Мы всегда
Делали это так'"] H -->|Да| J["Решение пересматривается
Современное решение"] I --> K["Технический долг
Нарастает"] J --> L["Система эволюционирует
Здорóво"] K --> M["Будущие проблемы"] L --> N["Устойчивый рост"]

Аргументы в пользу продуктивного скептицизма

Это не призыв к хаосу. Я не предлагаю вам выбрасывать каждый устоявшийся шаблон и перестраивать всё с нуля каждый квартал. Этот путь ведёт к худшему безумию — бесконечному циклу переписывания, который ничего не решает.

Вместо этого я выступаю за документированное принятие решений и плановый пересмотр. Революционные концепции, я знаю.

Вот практическая структура, которая, как я обнаружил, работает:

Шаг 1: Аудит существующих шаблонов

Прежде чем вы сможете что-либо подвергнуть сомнению, вам нужно знать, что вы на самом деле используете. Создайте инвентарь:

# patterns_audit.py
import ast
import os
from collections import defaultdict
class PatternDetector(ast.NodeVisitor):
    def __init__(self):
        self.patterns = defaultdict(list)
    def visit_Call(self, node):
        """Обнаруживает шаблоны вызовов функций/методов"""
        if isinstance(node.func, ast.Attribute):
            pattern_name = ast.unparse(node.func)
            self.patterns['function_calls'].append({
                'pattern': pattern_name,
                'line': node.lineno
            })
        self.generic_visit(node)
def audit_codebase(directory):
    """Сканирует кодовую базу на наличие установленных шаблонов"""
    all_patterns = defaultdict(list)
    for root, dirs, files in os.walk(directory):
        # Пропускать каталоги поставщиков
        dirs[:] = [d for d in dirs if d not in ['node_modules', 'venv', '.git']]
        for file in files:
            if not file.endswith('.py'):
                continue
            filepath = os.path.join(root, file)
            try:
                with open(filepath, 'r') as f:
                    tree = ast.parse(f.read())
                    detector = PatternDetector()
                    detector.visit(tree)
                    for pattern_type, instances in detector.patterns.items():
                        all_patterns[pattern_type].extend(instances)
            except SyntaxError:
                pass
    return all_patterns
# Использование
patterns = audit_codebase('./src')
for pattern_type, instances in patterns.items():
    print(f"\n{pattern_type}: {len(instances)} экземпляров")

Это даёт вам представление о том, какие шаблоны существуют. Знание — это необходимое условие для того, чтобы задавать вопросы.

Шаг 2: Документируйте «Почему»

Для каждого значительного шаблона создайте запись решения. Я не имею в виду написание романа — просто ответьте на три вопроса:

Почему: какую проблему это решило? Когда: каков был контекст (масштаб, ограничения, доступные опции)? До каких пор: при каких условиях это следует пересмотреть?

Вот шаблон:

# docs/architecture-decisions/session-storage.md
## Решение: использовать Redis для хранения сессий
**Дата принятия**: 2016-03-15
**Автор решения**: Сара Чен (руководитель отдела разработки, теперь в конкурирующей компании)
### Формулировка проблемы
Сессии хранились в процессе, что приводило к потере данных при развертывании