Seam — контрольована точка розділення

Seam — це місце, де можна змінити або підмінити частину поведінки без одночасного переписування всього legacy-модуля. Ним може бути interface, adapter, gateway, function boundary, event або routing decision. Хороший seam зменшує blast radius і робить replacement спостережуваним.

Seam не створює безпеку автоматично. Якщо межа лише перейменовує прямий виклик, але не ізолює side effects, configuration або failure path, ризик залишається.

Як знайти seam

СигналЩо дослідитиРизик
Stable input/outputчи є чіткий формат на межі?приховані поля або state coupling
Repeated dependencyчи повторюється client або utility?зміна одного caller зачепить багато flows
Side-effect boundaryде відбувається write, event або external call?часткова міграція і подвійний side effect
Routing decisionхто вирішує legacy vs new path?розбіжність flags, dates або rollout
Test boundaryчи можна перевірити seam окремо?неможливо відрізнити regression від integration failure

Dependency direction і adapters

Під час декомпозиції зафіксуйте, хто володіє контрактом і в якому напрямку течуть залежності. Adapter може сховати legacy API від нового коду, але не повинен непомітно змінювати semantics, формат помилок або retry behavior.

Інтерфейс має бути достатньо вузьким, щоб описувати потрібну поведінку, а не всю внутрішню поверхню legacy-класу. Якщо seam повторює кожну деталь реалізації, він не створює незалежної точки заміни.

  • позначте producer, consumer і owner контракту;
  • запишіть data transformation та можливу втрату інформації;
  • окремо опишіть errors, timeouts, retries і idempotency;
  • перевірте, чи seam можна вимкнути або обійти під час rollback.

Seam map як decision record

  1. Виберіть один flow і знайдіть його entry point та side effects.
  2. Намалюйте фактичний dependency path без бажаних компонентів.
  3. Позначте candidate seams і evidence для кожного.
  4. Вкажіть, яка частина може бути замінена незалежно.
  5. Зазначте unknowns, owner та спосіб focused verification.
  6. Оберіть один seam для першого slice і зафіксуйте, чому інші відкладені.

Антипатерни seam-декомпозиції

  • створити абстракцію лише заради кількості інтерфейсів;
  • заховати business rule в adapter без окремого owner;
  • змішати routing, persistence і форматування в одну нову boundary;
  • ігнорувати legacy callers, які обходять новий seam;
  • вважати seam безпечним до того, як перевірено його failure path.

Канонічне джерело уроку · JavaRush

Відкрити матеріал JavaRush