Почему бы написать статью в виде одного только агентского скилла. И вам полезно и мне не трудно.
Писал паттерн для себя. И для агента.
type-driven-legacy-refactoring
Универсальная методология рефакторинга и проектирования долгоживущих корпоративных систем с богатой бизнес-логикой на основе предварительного выявления намерений, археологии домена, функционального DDD Скотта Влашина и стратегии тестирования Майкла Физерса.
Применимость:
При рефакторинге и развитии долгоживущих продуктов, которые уже живут годами и будут развиваться дальше, где цена архитектурной ошибки крайне высока.
В проектах с высокой доменной сложностью и богатой бизнес-логикой (многостадийные визарды, финансовые/миграционные заявки, скоринги, биллинг).
Когда необходима «археология домена» — извлечение утраченных или неявных бизнес-правил из процедурного легаси-кода для их явной фиксации в новой архитектуре.
При жестких требованиях к надежности, отказоустойчивости (защита от разрывов сессий и сети) и статическим гарантиям корректности данных (Valid by Construction).
Навык агента (Agent Skill): Type-Driven Architecture & Refactoring via Intent Discovery, Wlaschin DDD & Feathers Testing
Этот навык представляет собой универсальный инженерный протокол проектирования и безопасного рефакторинга систем. Его ключевое отличие — обязательная предварительная фаза выявления намерений, приоритетов и архитектурных противоречий, а также опора на синтез теорий Скотта Влашина и Майкла Физерса.
ГРАНИЦЫ ПРИМЕНИМОСТИ (Где методология дает максимальный ROI)
Данный инженерный протокол является мощным архитектурным инструментом и дает стократный возврат инвестиций именно в следующих условиях:
Богатая бизнес-логика и высокая доменная сложность: Система содержит десятки взаимосвязанных правил, квот, ограничений и пошаговых переходов состояний.
Долгоживущие продукты (Long-Lived Core Products): Продукт жил годами, накопил процедурный долг и будет развиваться и поддерживаться еще долгие годы.
Необходимость «археологии домена»: Исходные требования или авторы утрачены, а реальные бизнес-правила и крайние случаи скрыты внутри тысяч строк легаси-скриптов и баз данных. Характеризационные тесты здесь выступают инструментом раскопки истины.
Высокие требования к надежности и архитектурным свойствам: Любой сбой в продакшене (Fatal Error, потеря сессии при вводе) недопустим из-за финансовых, юридических или репутационных рисков.
(Примечание: Для простых одноразовых CRUD-прототипов или быстрых MVP этот подход будет избыточным оверинжинирингом).
0: Выявление намерений, приоритетов и разрешение противоречий (Intent & Contradiction Discovery)
Перед выбором архитектурных паттернов и написанием кода агент или архитектор обязан остановиться и провести диалог по выявлению намерений (intents), весов/приоритетов и скрытых противоречий.
Протокол Фазы 0:
-
Выявление намерений и приоритетов (Intents & Priorities):
Что важнее в данном контексте: абсолютная типобезопасность ядра, скорость клиентского UI-ввода, минимизация дублирования кода (DRY) или отказоустойчивость при сетевых сбоях?
Каковы ограничения среды (например: «у нас часто дохнет сессия», «обрывы сети при отправке виртуальных форм»)?
-
Картирование противоречий (Contradiction Mapping):
Конфликт 1: Требование UX (собрать и показать на веб-форме все ошибки ввода без падения) противоречит принципу доменной строгости Valid by Construction (мгновенно выбросить исключение при первой ошибке).
Конфликт 2: Требование фонового автосохранения каждые 15 секунд противоречит строгим реляционным ограничениям
NOT NULLи Foreign Key в боевых таблицах.
Методология Contradiction-Driven Synthesis (Поиск решений под противоречия): Поиск и анализ противоречий — это постоянный навык архитектора. Когда выявлен жесткий конфликт требований, сначала ищется решение в базовых каталогах (GoF, DDD). Если стандартные шаблоны не решают конфликт идеально, на основе матрицы приоритетов синтезируется специализированное архитектурное решение.
1. Канонические и специализированные паттерны архитектуры
1. Кейс-стади Contradiction-Driven Synthesis: Рождение паттерна Dual-Mode Specification
Чтобы методология поиска противоречий не оставалась абстрактной, разберем конкретный пример того, что именно анализировалось и почему синтезированное решение помогло:
-
Анализируемое жесткое противоречие трех сил:
Сила А (UX веб-формы): При пошаговом вводе сложной заявки система обязана собрать и вывести на экран абсолютно все ошибки одновременно (например, 10 проблемных полей из 20), не прерывая выполнение выбрасыванием исключения при первой ошибке.
Сила Б (Доменная строгость Valid by Construction): При конструировании финального доменного объекта конструктор обязан мгновенно отклонить невалидное состояние (выбросить
DomainExceptionпри первой ошибке), чтобы невалидный объект принципиально не мог существовать в памяти.Сила В (Единая точка правды / DRY): Бизнес-правила запрещено дублировать (писать отдельные проверки для UI и отдельные
if-guard проверки внутри конструкторов домена).
Почему стандартные шаблоны не подошли: Стандартный паттерн Спецификация (GoF) или классическая валидация контроллера решают только одну сторону (либо мягкий сбор ошибок для UI, либо жесткий Guard для домена).
-
Синтезированное решение (Dual-Mode Specification): Поскольку форма черновика и финальный агрегат имеют совпадающую структуру полей, был введен общий интерфейс чтения (
DomainReadContractInterface). Бизнес-правила реализуются один раз против этого интерфейса и запускаются через исполнитель (SpecificationEvaluator) в двух разных режимах:Collector Mode (для UI-контроллера): прогоняет объект через правила, накапливает все ошибки в
List<ValidationError>и возвращает их для отображения на форме без падения.Guard Mode (для фабрики доменной сущности): прогоняет объект через те же правила при конструировании. Если список ошибок не пуст, выбрасывает
DomainValidationException.
Почему это помогло: Противоречие было полностью разрешено: бизнес-правила написаны ровно 1 раз (DRY), UX формы показывает все ошибки разом, а доменные сущности на 100% защищены по принципу Valid by Construction.
2. Базовый каталог паттернов для смежных легаси-кейсов
В зависимости от вскрытых на Фазе 0 противоречий, применяются следующие канонические абстракции:
-
Изоляция и миграция легаси:
Strangler Fig / Branch by Abstraction: Плавное переключение вызовов со старого монолита на новый чистый модуль без переписывания системы за раз.
Shadow Read-Write (Dark Launch): Параллельная запись в старую и новую схему со сверкой результатов в фоне.
-
Укрощение процедурной сложности:
Strategy / Pipeline / Railway programming: Замена многоэтажных
if-elseи монолитных скриптов на цепочки взаимозаменяемых независимых классов-шагов.Facade: Единая чистая точка входа над клубком легаси-функций.
-
Целостность и надежность данных:
Immutable Type-State Builder: Моделирование пошаговых переходов через
readonly classс возвратом новых экземпляров (исключает побочные эффекты мутации in-place).Anti-Corruption Layer (ACL): Изоляция сервисов от сырых HTTP-массивов (
$_POST, JSON) через строгие DTO.Typed Collection (
List<T>): Обертывание списков дочерних сущностей для 100% навигации в IDE. И вообще, очень не хватает дженериков в PHP, при желании эрзац дженерики и типизированные коллекции можно сделать самому через аннотации PHPDocsUnit of Work / Transactional Outbox: Атомарная запись агрегата и гарантированная отправка внешних событий без потери данных при сбоях.
2. Теоретический фундамент: Функциональный DDD Скотта Влашина
Методология паттернов опирается на 5 столпов книги Скотта Влашина «Domain Modeling Made Functional»:
Язык предметной области через типы: Бизнес-состояния должны быть выражены типами (Enum, Readonly Struct), а не примитивными строками.
Make Illegal States Unrepresentable: Невалидный доменный объект не должен существовать в памяти.
Бизнес-процессы как чистые функции:
.
Защита границ: Очистка и валидация данных происходит на внешней границе системы (ACL).
Value Semantics: Отказ от мутации состояния в пользу функциональных трансформаций.
3. Методология безопасного тестирования и рефакторинга легаси по Майклу Физерсу (Michael Feathers)
Любая архитектурная трансформация легаси-кода обязана подчиняться правилам книги Майкла Физерса «Working Effectively with Legacy Code»:
1. Главный постулат Физерса
«Легаси-код — это просто код без тестов. Код без тестов плох тем, что его невозможно изменить с гарантией безопасности.»
2. Закон обратной пропорции качества легаси и затрат на начальное тестирование
Чем хуже качество легаси-кода (высокая запутанность, отсутствие типов, глобальные зависимости), тем больше времени и усилий придется потратить на начальное характеризационное тестирование и ручное создание эталонов (Golden Master).
Эта первоначальная инвестиция времени окупается вдвойне:
Защита от регрессий: Создает надежный каркас безопасности перед декомпозицией.
Археологическая раскопка домена (Выявление скрытых намерений): В процессе ручной фиксации эталонов изменений вскрываются скрытые бизнес-намерения, забытые политики и крайние случаи оркестрации, которые извлекаются из процедурного мусора и прописываются в новом чистом коде в явном виде.
3. Стратегия характеризационного тестирования (Golden Master)
Захват эталона (Golden Master Capture): Направьте на старый скрипт репрезентативные наборы входных данных (
$_POST/$_GET).Фиксация побочных эффектов: Запишите точные SQL-запросы, изменения в БД и сгенерированный HTML.
Сверка при рефакторинге: Запустите новый контроллер на тех же входных пейлоадах и убедитесь, что доменные результаты на 100% совпадают с эталоном.
4. Швы (Seams) и Ростки (Sprout Class / Sprout Method)
Внедрение швов (Object Seams): Замените прямые вызовы глобальных объектов на внедряемые интерфейсы (
DbConnection,LoggerInterface).Классы-ростки (Sprout Class): Выращивайте новую чистую функциональность в виде изолированных, 100% покрытых тестами классов-ростков и делегируйте им работу из легаси.
4. Пошаговый протокол выполнения
Шаг 0: Диалог намерений и противоречий (Intent & Contradiction Discovery)
Выясните ключевые бизнес-приоритеты заказчика и ограничения инфраструктуры продакшена.
Выявите и озвучьте архитектурные противоречия. Подберите или синтезируйте паттерны для их разрешения.
Шаг 1: Аудит источника правды, характеризационные тесты и выявление скрытых намерений
Изучите исходные легаси-файлы. Потратьте необходимое время на построение эталонов (Golden Master) по Майклу Физерсу.
Извлеките скрытые бизнес-намерения из поведения старого кода, чтобы зафиксировать их в новой архитектуре в явном виде.
Шаг 2: Создание Agile Spike на Rust
Напишите компактный концепт на Rust (
ARCHITECTURE_CONCEPT.rs). Опишите чистые структуры полей без гетеров, перечисления этапов UI и домена, стратегии восстановления (ErrorRecoveryStrategy) и трейты репозиториев. Rust молодой и выразительный, обучающие паттерны на нём и привычки программистов модерновые и ещё не поросли мхом. Спецификации в виде типов и сигнатур без реализации очень компактны и полезны в проектировании.
Шаг 3: Проектирование слоя ACL, типизированных коллекций (List) и швов
Перенесите структуры в целевой язык в виде строгих
readonlyDTO. Замените массивы на спискиList<T>.Внедрите объектные швы (Seams) и ACL для изоляции домена от HTTP и глобальных переменных.
Шаг 4: Реализация универсального доменного ядра по Влашину и классам-росткам
Создайте общие интерфейсы чтения (
DomainReadContractInterface), атомарные правила (SpecificationRule) в виде классов-ростков и иммутабельные агрегаты (ValidAggregate).
Шаг 5: Изоляция представления и настройка IDE-навигации
Вынесите вёрстку и подсветку ошибок в изолированный класс вёрстки (
Render). Настройте единую точку входа (public/index.php), автозагрузчик и фабрику DI для 100% навигации в IDE.
Шаг 6: Защита продакшена, транзитные исключения и сверка с Golden Master
Проставьте точные аннотации
@throwsво всей цепочке вызовов. Постройте эшелоны отказоустойчивости.Прогоните характеризационные тесты и убедитесь в 100% совпадении с эталоном.
5. Антипаттерны (Чего делать КАТЕГОРИЧЕСКИ НЕЛЬЗЯ)
❌ Blind Coding without investigating: Написание кода или выбор паттернов без предварительного выявления намерений, приоритетов и противоречий заказчика.
❌ Refactoring without Characterization Tests: Изменение легаси-кода без инвестиции времени в фиксацию эталонного поведения (Golden Master).
❌ Legacy/poisoned Mindset / Primitive Obsession: Отравление легаси мышлением и инструментами. Например, использование сырых ассоциативных массивов (array $items) вместо DTO и типизированных коллекций List<T>.
❌ Duplicated/fragmented logic: Написание отдельных проверок для UI-формы и отдельных проверок внутри конструкторов домена.
❌ Anemic Valid Entity: Создание готовой сущности, которая является простой оберткой над DTO без проверки инвариантов при конструировании.
❌ In-Place Mutation/shared mutable state: Прямое изменение полей ($draft->items[] = ...) вместо иммутабельных функциональных трансформаций.
❌ Boolean Blindness: Использование примитивных флажков bool $isError вместо перечислений (ErrorRecoveryStrategyEnum).
Комментарии (3)

Void-Cowboy
04.07.2026 17:57Воистину можно и при молитве расшибиться
Скилы были даны нам что бы получать сфокусированные навыки для тонких вещей, а не для "делай хорошо, а плохо не делай"
Архитектура прописывается уже в самом проекте точечно в CLAUDE.MD или AGENTS.MD, а не в скилах.
sergey_vasin
И удивительным образом модель будет каждый раз использовать правила в главе антиптеррны, так как она сама является антипттерном
Dhwtj Автор
Удивительным образом и кожаные и железные это всё знают, но не применяют. Такой вот сдвиг приоритетов.
Я специально написал пункт про типичные / привычные шаги и про то, что их недостаточно