isolating-product-facade-contracts
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseIsolating a product with facade and contracts
使用外观(Facade)与契约实现产品隔离
Use this skill to migrate an existing product to the isolated architecture used by Visual review.
Keep migrations incremental, with narrow PRs that avoid broad breakage.
Prerequisite: the product must already live under . This skill does not cover moving code out of , , or other shared directories — do that first.
products/<name>/posthog/ee/使用此方法将现有产品迁移至Visual review所采用的隔离架构。
保持迁移的增量性,通过范围狭窄的PR避免大范围的代码损坏。
前置条件:产品必须已位于目录下。此方法不包含将代码从、或其他共享目录中移出的操作——请先完成该步骤。
products/<name>/posthog/ee/Core docs to load first
首先需要阅读的核心文档
Read these before changing code:
- products/architecture.md
- products/README.md
- docs/internal/monorepo-layout.md
- posthog/models/team/README.md (team extension model rule)
- docs/published/handbook/engineering/type-system.md (serializer/OpenAPI type flow)
- docs/published/handbook/engineering/ai/implementing-mcp-tools.md (schema quality and team isolation expectations)
Use Visual review as the concrete reference implementation:
- products/visual_review/backend/facade/contracts.py
- products/visual_review/backend/facade/api.py
- products/visual_review/backend/presentation/views.py
- products/visual_review/backend/presentation/serializers.py
- products/visual_review/backend/logic.py
- products/visual_review/backend/tests/test_api.py
- products/visual_review/backend/tests/test_presentation.py
For detailed sequencing, load references/phased-migration-plan.md.
在修改代码前,请阅读以下文档:
- products/architecture.md
- products/README.md
- docs/internal/monorepo-layout.md
- posthog/models/team/README.md(团队扩展模型规则)
- docs/published/handbook/engineering/type-system.md(序列化器/OpenAPI类型流程)
- docs/published/handbook/engineering/ai/implementing-mcp-tools.md(Schema质量与团队隔离要求)
请以Visual review作为具体的参考实现:
- products/visual_review/backend/facade/contracts.py
- products/visual_review/backend/facade/api.py
- products/visual_review/backend/presentation/views.py
- products/visual_review/backend/presentation/serializers.py
- products/visual_review/backend/logic.py
- products/visual_review/backend/tests/test_api.py
- products/visual_review/backend/tests/test_presentation.py
如需了解详细的迁移顺序,请查看references/phased-migration-plan.md。
Guardrails
约束规则
- Keep facades thin; put business rules in .
logic.py - Never return ORM models across product boundaries.
- Keep contracts pure (no Django/DRF imports).
- Filter by in querysets.
team_id - Do not add product-specific fields to ; use a Team Extension model.
Team - Add request/response schema annotations on viewset endpoints (or
@validated_request).@extend_schema - Regenerate OpenAPI/types () when serializer/view changes affect API schema.
hogli build:openapi
- 保持外观层简洁;将业务规则放在中。
logic.py - 切勿跨产品边界返回ORM模型。
- 保持契约层纯净(不导入Django/DRF相关内容)。
- 在查询集中按进行过滤。
team_id - 不要向中添加产品特定字段;请使用团队扩展模型。
Team - 在视图集端点上添加请求/响应Schema注解(或
@validated_request)。@extend_schema - 当序列化器/视图的更改影响API Schema时,重新生成OpenAPI/类型定义()。
hogli build:openapi
Required migration workflow
必填迁移流程
- Build an import map for the target product.
- Find cross-product imports into target internals (,
models,logic, non-facade modules).presentation - Classify each usage by capability (read/list, detail/read, create/update/delete, async/task, webhook/event).
- Find cross-product imports into target internals (
- Define the minimal contract surface.
- Start from currently consumed fields only.
- Create frozen dataclasses in .
backend/facade/contracts.py
- Introduce a thin facade in .
backend/facade/api.py- Map ORM instances to contracts with explicit mapper functions.
- Keep method names capability-oriented and stable.
- Migrate callers in small batches.
- Replace one caller cluster at a time (single endpoint, single task, or single service area).
- Keep compatibility shims only when needed; remove promptly.
- Move presentation to consume the facade.
- Serializers convert JSON <-> contracts.
- Views call facade methods only.
- Enforce boundaries and verify.
- Update interfaces/dependencies when applicable.
tach.toml - Run focused tests for changed files, then product-level backend tests.
- Update
- 为目标产品构建导入映射。
- 找出跨产品导入目标产品内部模块的情况(、
models、logic、非外观层模块)。presentation - 按功能类型对每种使用场景进行分类(读取/列表、详情/读取、创建/更新/删除、异步/任务、Webhook/事件)。
- 找出跨产品导入目标产品内部模块的情况(
- 定义最小化的契约接口。
- 仅从当前被使用的字段开始。
- 在中创建冻结的数据类。
backend/facade/contracts.py
- 在中引入简洁的外观层。
backend/facade/api.py- 使用显式的映射函数将ORM实例转换为契约对象。
- 保持方法名以功能为导向且稳定。
- 分批迁移调用方。
- 一次替换一个调用方集群(单个端点、单个任务或单个服务区域)。
- 仅在必要时保留兼容性垫片,并及时移除。
- 修改表示层以调用外观层。
- 序列化器负责JSON与契约对象之间的转换。
- 视图仅调用外观层方法。
- 强制执行边界并验证。
- 适当时更新中的接口/依赖配置。
tach.toml - 先对修改的文件运行针对性测试,再运行产品级后端测试。
- 适当时更新
PR slicing strategy
PR拆分策略
Default to several PRs instead of one big migration:
- PR 1: Add contracts + facade methods without changing external callers.
- PR 2-N: Migrate caller clusters one-by-one to the facade.
- Final PR: Remove deprecated internal import paths, tighten tach boundaries, and clean dead adapters.
If a product has many endpoints, migrate in this order:
- Read-only list/detail APIs (lowest risk)
- Internal service-to-service call sites
- Write paths (create/update/delete)
- Background tasks / async entrypoints
- Remaining edge endpoints and cleanup
默认拆分为多个PR,而非单次大迁移:
- PR 1:添加契约与外观层方法,不修改外部调用方。
- PR 2至N:逐个迁移调用方集群至外观层。
- 最终PR:移除已废弃的内部导入路径,收紧tach边界,清理无用的适配器。
如果产品包含多个端点,请按以下顺序迁移:
- 只读列表/详情API(风险最低)
- 内部服务间调用站点
- 写入路径(创建/更新/删除)
- 后台任务/异步入口点
- 剩余边缘端点与清理工作
Done criteria
完成标准
Treat migration as complete only when:
- Cross-product imports use only.
backend/facade - Facade returns/accepts contracts, not ORM.
- Presentation layer no longer encodes business logic.
- Tests cover facade and presentation boundaries.
- Turbo/tach config reflects intended product isolation.
仅当满足以下所有条件时,才视为迁移完成:
- 跨产品导入仅使用。
backend/facade - 外观层返回/接收契约对象,而非ORM模型。
- 表示层不再包含业务逻辑。
- 测试覆盖外观层与表示层的边界。
- Turbo/tach配置反映了预期的产品隔离状态。