Конвейер обработки устроен так, что каждый этап зависит от внутреннего состояния соседнего. Какой архитектурный сигнал показывает, что стиль pipe-and-filter выбран неудачно?
Это сигнал о нарушении главного условия стиля pipe-and-filter: фильтры должны взаимодействовать через явные данные, а не через внутреннее состояние друг друга. Если этапы знают внутреннее устройство соседей, конвейер становится тесно связанным и теряет заменяемость, повторное использование и возможность безопасно менять порядок обработки.
Стиль pipe-and-filter применяют для разбиения обработки данных на последовательность независимых преобразований. Каждый фильтр получает вход, выполняет локальную работу и передаёт результат следующему этапу через явно определённый канал.
Такой подход решает проблему больших процедур, в которых смешаны разные стадии обработки. Он упрощает тестирование отдельных этапов, позволяет переиспользовать фильтры и в некоторых случаях выполнять независимые стадии параллельно.
Зависимость от внутреннего состояния соседнего этапа означает, что контракт между фильтрами стал неявным. Изменение структуры состояния одного фильтра может потребовать изменений в других фильтрах, даже если формат их бизнес-результата не менялся.
Последствиями становятся невозможность свободно заменить или переставить этап, сложность повторного запуска отдельного шага и распространение ошибок по всему конвейеру. Параллельное выполнение также становится рискованным: этапы начинают конкурировать за общее состояние или требуют строгой координации.
В корректном pipe-and-filter взаимодействии границей является явный поток данных. Фильтр не должен обращаться к памяти, объектам или внутренним структурам другого фильтра; необходимые сведения должны входить в его входной контракт, а результаты — выходить через его выходной контракт.
Признак ошибочного выбора стиля — не просто наличие последовательных этапов, а необходимость для них вести себя как единый изменяемый компонент. Особенно сильные сигналы — двустороннее обращение между этапами, общий изменяемый контекст, зависимость от порядка внутренних операций и необходимость согласованно менять несколько фильтров при изменении одного состояния.
Исправление обычно начинают с выделения явной модели сообщения. В неё включают только данные, необходимые следующему этапу, а не внутренние объекты предыдущего. Если состояние действительно нужно нескольким этапам, его следует представить как отдельную управляемую границу, а не передавать скрытой ссылкой.
У этого решения есть компромиссы. Явные сообщения могут дублировать данные, требовать версионирования и увеличивать стоимость сериализации. Однако эта цена часто оправдана снижением связности и возможностью независимо тестировать, заменять и повторять этапы.
Если этапам требуется частое двустороннее взаимодействие, общая транзакция или сложная координация, лучше рассмотреть другой стиль: оркестрацию рабочего процесса, централизованный компонент координации или единый модуль с внутренними вызовами. Pipe-and-filter не следует навязывать процессам, в которых этапы фактически образуют одну согласованную предметную операцию.
В системе обработки документов были этапы распознавания текста, нормализации и классификации. Изначально классификатор читал внутреннюю структуру, которую создавал распознаватель, а нормализатор изменял её непосредственно. Любое изменение алгоритма распознавания приводило к каскаду изменений в последующих этапах.
Рассматривались три варианта:
Был выбран третий вариант. Распознаватель публиковал результат в согласованной модели, нормализатор возвращал новую версию результата, а классификатор зависел только от нужных ему полей. В итоге внутренние изменения одного этапа перестали автоматически требовать изменений остальных; при этом для операций, которым нужна общая согласованность, оставили отдельную оркестрацию, не маскируя её под независимый конвейер.
Нет. Важна не форма передачи, а владение и стабильность контракта. Если следующий фильтр получает объект и начинает читать или изменять поля, предназначенные для внутренней работы предыдущего, зависимость от реализации сохраняется. Явная граница требует выделенного контракта данных и запрета на использование неоговорённых деталей.
Да. Параллелизм является возможным преимуществом, но не обязательным условием. Основной критерий — независимость фильтров и взаимодействие через поток явно определённых результатов. Однако если последовательность обусловлена скрытым доступом к общему состоянию, это уже признак сильной связанности, а не просто допустимого порядка этапов.
Он оправдан, если это осознанная часть архитектурного контракта и его жизненный цикл, владение, версия и правила изменения определены явно. Но тогда систему следует рассматривать не как полностью независимый pipe-and-filter-конвейер, а как гибрид с общей моделью состояния или оркестратором. Важно не запрещать общий контекст формально, а честно учитывать его как архитектурную зависимость при оценке заменяемости, тестирования и масштабирования.