Files
ecm_sync_system/docs/archive/from_root_docs/代码重构提纲.md
T
strepsiades 4a9c444b10 first commit
2026-03-09 16:31:42 +08:00

28 KiB
Raw Blame History

代码重构提纲

目标:删繁就简,将状态机、日志、持久化部分写扎实,提升代码质量

当前状态:基本功能已打通,所有业务类型可以从零推送,但代码存在重复、错误、不严谨、赘余、与文档不符等问题


重构原则

  1. 严格遵循文档:以 docs/ 文件夹中的架构文档为准
  2. 类型安全优先:充分利用 Python 类型系统和 Pydantic
  3. 单一职责:每个模块、类、方法只做一件事
  4. 可测试性:重构后的代码应该更易测试
  5. 可观测性:完善的日志和错误处理

第一阶段:核心状态机强化(最高优先级)

1.1 状态转换规范化

问题诊断

  • 检查状态转换是否严格遵循 状态定义规范.md
  • 检查是否有非法的状态转换路径
  • 检查状态转换是否都有日志记录

重构任务

Task 1.1.1: 状态转换集中管理

# sync_system_new/common/state_machine.py (新建)
class StateMachine:
    """集中管理所有合法的状态转换"""
    
    @staticmethod
    def can_transition(
        from_status: SyncStatus, 
        to_status: SyncStatus
    ) -> bool:
        """检查状态转换是否合法"""
        pass
    
    @staticmethod
    def validate_binding_status_transition(
        from_status: BindingStatus,
        to_status: BindingStatus
    ) -> bool:
        """检查绑定状态转换是否合法"""
        pass

操作步骤

  1. 创建 state_machine.py,定义状态转换矩阵
  2. SyncNode 的状态设置方法中调用验证
  3. 添加状态转换日志(包含 from/to/reason
  4. 更新所有修改状态的代码,使用统一的转换方法

验收标准

  • 所有状态转换都经过 StateMachine 验证
  • 非法转换会抛出明确的异常
  • 每次转换都有日志记录

1.2 BindingStatus 判定逻辑强化

问题诊断

  • 检查 BaseSyncStrategy.bind() 是否严格遵循核心状态判定表(状态定义规范 § 1)
  • 检查依赖解析逻辑是否符合规范(状态定义规范 § 2)
  • 检查自动绑定逻辑是否符合 1:1 原则(状态定义规范 § 3)

重构任务

Task 1.2.1: 核心状态判定表实现

# sync_system_new/sync_system/binding_matrix.py (新建)
class BindingMatrix:
    """实现核心状态判定表(状态定义规范 § 1)"""
    
    @staticmethod
    def determine_binding_status(
        has_binding: bool,
        local_data_valid: bool,
        remote_data_valid: bool
    ) -> Tuple[Optional[BindingStatus], Optional[BindingStatus]]:
        """
        返回 (local_status, remote_status)
        
        实现状态定义规范 § 1 的判定表
        """
        pass

Task 1.2.2: 依赖解析逻辑分离

# sync_system_new/sync_system/dependency_checker.py (已存在,需强化)
class DependencyChecker:
    """依赖检查与业务键解析(状态定义规范 § 2)"""
    
    @staticmethod
    def check_dependencies(
        node: SyncNode,
        local_collection: DataCollection,
        remote_collection: DataCollection,
        binding_manager: BindingManager
    ) -> Tuple[bool, Optional[str]]:
        """
        返回 (can_proceed, error_message)
        
        检查:
        1. 依赖节点是否存在
        2. 依赖节点的绑定状态是否为 NORMAL
        3. 依赖节点的 data_id 是否非空
        """
        pass

Task 1.2.3: 自动绑定逻辑重写

# sync_system_new/sync_system/auto_binder.py (新建)
class AutoBinder:
    """自动绑定逻辑(状态定义规范 § 3"""
    
    @staticmethod
    def try_auto_bind(
        local_nodes: List[SyncNode],
        remote_nodes: List[SyncNode],
        biz_key: tuple,
        binding_manager: BindingManager
    ) -> AutoBindResult:
        """
        实现去噪后 1:1 自动绑定
        
        算法:
        1. 全集搜索:寻找共享相同业务键的记录
        2. 排除稳态对:移除成对且互绑的 NORMAL 记录
        3. 判定剩余:L_remain=1 且 R_remain=1 才执行绑定
        """
        pass

操作步骤

  1. 创建 binding_matrix.py,实现核心判定表
  2. 强化 dependency_checker.py,严格按规范检查依赖
  3. 创建 auto_binder.py,将自动绑定逻辑从 strategy.py 中分离
  4. 重构 BaseSyncStrategy.bind() 方法,调用上述三个模块
  5. 添加详细的日志和错误信息(特别是 DEPENDENCY_ERROR 的格式)

验收标准

  • bind() 方法逻辑清晰,不超过 50 行
  • 每个判定步骤都有日志记录
  • DEPENDENCY_ERROR 的 error 字段格式符合文档规范
  • 自动绑定只在 1:1 场景下触发

1.3 CREATE/UPDATE 逻辑规范化

问题诊断

  • 检查 CREATE 阶段的 ID 替换逻辑是否完整
  • 检查 UPDATE 阶段是否正确跳过 FAILED 节点
  • 检查是否正确处理空数据(业务键缺失)

重构任务

Task 1.3.1: ID 替换逻辑统一

# sync_system_new/sync_system/id_replacer.py (新建)
class IDReplacer:
    """ID 替换逻辑(架构分层设计 § 6"""
    
    @staticmethod
    def replace_ids_for_create(
        data: Dict[str, Any],
        id_fields: List[str],
        binding_manager: BindingManager,
        direction: str  # "local_to_remote" or "remote_to_local"
    ) -> Dict[str, Any]:
        """
        创建新节点时,将依赖字段的本地 ID 替换为远程 ID
        
        示例:
        data = {"project_id": "P1", "code": "C01"}
        -> {"project_id": "RP_99", "code": "C01"}
        """
        pass
    
    @staticmethod
    def replace_ids_for_update(
        data: Dict[str, Any],
        id_fields: List[str],
        binding_manager: BindingManager,
        direction: str
    ) -> Dict[str, Any]:
        """准备更新数据时,替换数据中的依赖 ID"""
        pass

Task 1.3.2: UPDATE 阶段保护逻辑

# sync_system_new/sync_system/strategy.py
class BaseSyncStrategy:
    def update(self):
        """UPDATE 操作必须跳过 FAILED 节点"""
        # 过滤掉 status == FAILED 的节点
        # 详见:持久化与人工介入规范 § 1.2 (UPDATE 阶段保护)
        pass

操作步骤

  1. 创建 id_replacer.py,集中管理 ID 替换逻辑
  2. strategy.py 中提取 ID 替换代码,迁移到 IDReplacer
  3. update() 方法开头添加 FAILED 节点过滤
  4. 添加空数据检查(业务键缺失标记为 WARNING)

验收标准

  • CREATE/UPDATE 使用统一的 ID 替换逻辑
  • UPDATE 不会覆盖 FAILED 节点的状态
  • 空数据不参与同步,状态为 WARNING

第二阶段:持久化与状态重置强化

2.1 持久化规则严格执行

问题诊断

  • depend_ids 是否已移除持久化 已修复
  • 检查阶段1重置是否正确实现
  • 检查阶段2清理是否正确实现

重构任务

Task 2.1.1: 阶段1重置逻辑审查

# sync_system_new/common/state_reset.py
def get_phase1_reset_defaults() -> Dict[str, Any]:
    """
    阶段1:加载时重置(持久化与人工介入规范 § 1.2)
    
    必须重置:
    - data/origin_data → None(等待重新加载)
    - depend_ids → []
    - binding_status → UNCHECKED
    - error → None
    
    必须保留:
    - node_id, data_id
    - action(用于识别 CREATE 失败节点)
    - status(只保留 FAILED,其他重置为 PENDING
    - context
    """
    pass

Task 2.1.2: 阶段2清理逻辑审查

# sync_system_new/pipeline/full_sync_pipeline.py
async def _cleanup_create_failed_zombies(self):
    """
    阶段2:数据加载后清理(持久化与人工介入规范 § 1.2)
    
    清理步骤:
    1. 检测:action == CREATE && status == FAILED
    2. 删除本地失败节点
    3. 解除绑定记录
    4. 删除远程僵尸节点
    5. 重置所有剩余节点的 action 为 NONE
    """
    pass

操作步骤

  1. 审查 state_reset.py,确保阶段1重置符合规范
  2. 审查 _cleanup_create_failed_zombies(),确保清理逻辑完整
  3. 添加详细的日志(清理了哪些节点,原因是什么)
  4. 编写单元测试,验证重置和清理逻辑

验收标准

  • 阶段1重置字段完全符合文档表格
  • 阶段2清理逻辑不遗漏任何步骤
  • 每次重置/清理都有明确的日志

2.2 绑定记录持久性保证

问题诊断

  • 检查绑定记录是否真的"永久保留"
  • 检查是否有意外修改绑定记录的代码

重构任务

Task 2.2.1: 绑定记录保护机制

# sync_system_new/common/binding.py
class BindingManager:
    """
    绑定记录持久性规则(持久化与人工介入规范 § 1.3):
    
    - 只能手工 bind/unbind
    - 或 CREATE 失败自动清理
    - 其他情况绝不修改
    """
    
    def bind(self, local_node_id: str, remote_node_id: str, manual: bool = False):
        """
        建立绑定记录
        
        Args:
            manual: 是否为手工绑定(用于审计日志)
        """
        pass
    
    def unbind(self, node_id: str, manual: bool = False):
        """解除绑定(只在手工或 CREATE 失败时调用)"""
        pass

操作步骤

  1. 审查所有调用 bind()/unbind() 的地方
  2. 添加 manual 参数,区分手工和自动操作
  3. 添加审计日志(谁在何时为何修改了绑定)
  4. 确保只有允许的场景才能修改绑定

验收标准

  • 绑定记录修改有完整的审计日志
  • 自动绑定只在 1:1 场景触发
  • CREATE 失败清理有明确的日志

第三阶段:日志与可观测性

3.1 结构化日志体系

问题诊断

  • 检查当前日志是否足够定位问题
  • 检查日志格式是否统一
  • 检查是否缺少关键操作的日志

重构任务

Task 3.1.1: 统一日志格式

# sync_system_new/common/logger.py (新建)
import logging
from typing import Optional, Dict, Any

class SyncLogger:
    """统一的结构化日志工具"""
    
    @staticmethod
    def log_state_transition(
        logger: logging.Logger,
        node_type: str,
        node_id: str,
        from_status: str,
        to_status: str,
        reason: str,
        extra: Optional[Dict[str, Any]] = None
    ):
        """状态转换日志"""
        logger.info(
            f"[{node_type}] State transition: {node_id} "
            f"{from_status} -> {to_status} | Reason: {reason}",
            extra=extra or {}
        )
    
    @staticmethod
    def log_binding_operation(
        logger: logging.Logger,
        operation: str,  # "bind", "unbind", "auto_bind"
        local_node_id: str,
        remote_node_id: Optional[str],
        reason: str,
        manual: bool = False
    ):
        """绑定操作日志"""
        op_type = "MANUAL" if manual else "AUTO"
        logger.info(
            f"[{op_type}] Binding {operation}: "
            f"local={local_node_id} <-> remote={remote_node_id} | {reason}"
        )
    
    @staticmethod
    def log_sync_action(
        logger: logging.Logger,
        action: str,  # "CREATE", "UPDATE", "DELETE"
        node_type: str,
        node_id: str,
        data_id: str,
        success: bool,
        error: Optional[str] = None
    ):
        """同步操作日志"""
        status = "SUCCESS" if success else "FAILED"
        msg = f"[{node_type}] {action} {status}: node_id={node_id}, data_id={data_id}"
        if error:
            msg += f" | Error: {error}"
        
        if success:
            logger.info(msg)
        else:
            logger.error(msg)
    
    @staticmethod
    def log_dependency_error(
        logger: logging.Logger,
        node_type: str,
        node_id: str,
        dependency_errors: List[str]
    ):
        """依赖错误日志"""
        logger.warning(
            f"[{node_type}] DEPENDENCY_ERROR: {node_id} | "
            f"Errors: {'; '.join(dependency_errors)}"
        )

操作步骤

  1. 创建 logger.py,定义结构化日志方法
  2. 在关键模块引入 SyncLogger
  3. 替换所有 logger.info/warning/error 为结构化方法
  4. 添加日志级别配置(DEBUG/INFO/WARNING/ERROR

验收标准

  • 所有状态转换都有日志
  • 所有绑定操作都有日志
  • 所有同步操作(CREATE/UPDATE/DELETE)都有成功/失败日志
  • 日志格式统一,易于搜索和过滤

3.2 关键路径日志补充

问题诊断

  • bind() 阶段是否记录了每个判定步骤
  • create()/update() 是否记录了 ID 替换细节
  • cleanup 阶段是否记录了清理的节点

重构任务

Task 3.2.1: bind() 阶段日志强化

# sync_system_new/sync_system/strategy.py
class BaseSyncStrategy:
    def bind(self):
        # 1. 核心状态判定
        logger.debug(f"[{self.node_type}] Checking binding records...")
        
        # 2. 依赖检查
        logger.debug(f"[{self.node_type}] Checking dependencies for {node_id}...")
        
        # 3. 自动绑定尝试
        logger.info(f"[{self.node_type}] Auto-bind attempt: L_remain={L}, R_remain={R}")
        
        # 4. 状态转换
        SyncLogger.log_state_transition(...)

Task 3.2.2: create()/update() 日志强化

class BaseSyncStrategy:
    def create(self):
        # 1. 孤儿节点识别
        logger.info(f"[{self.node_type}] Found {len(orphans)} orphan nodes")
        
        # 2. ID 替换
        logger.debug(f"[{self.node_type}] Replacing IDs: {old_ids} -> {new_ids}")
        
        # 3. action 设置
        SyncLogger.log_state_transition(...)

操作步骤

  1. bind() 的每个判定步骤添加日志
  2. create()/update() 的关键操作添加日志
  3. _cleanup_create_failed_zombies() 添加详细日志
  4. 设置合理的日志级别(DEBUG/INFO/WARNING

验收标准

  • 开启 DEBUG 日志时,可以完整追踪每个节点的处理过程
  • 生产环境只需 INFO 日志即可定位问题
  • 关键错误都有 ERROR 级别日志

3.3 sync_log 字段利用

问题诊断

  • 检查 SyncNode.sync_log 是否被使用
  • 检查是否记录了完整的处理历史

重构任务

Task 3.3.1: sync_log 结构定义

# sync_system_new/common/sync_node.py
class SyncNode:
    """
    sync_log 格式:
    [
        {
            "timestamp": "2025-01-15T10:30:00",
            "phase": "bind",
            "from_status": "UNCHECKED",
            "to_status": "NORMAL",
            "reason": "Found binding record",
            "details": {}
        },
        {
            "timestamp": "2025-01-15T10:30:05",
            "phase": "update",
            "action": "UPDATE",
            "reason": "Data diff detected",
            "details": {"changed_fields": ["name", "amount"]}
        }
    ]
    """
    
    def append_log(self, phase: str, action: str, reason: str, details: Optional[Dict] = None):
        """向 sync_log 添加记录"""
        pass

操作步骤

  1. 定义 sync_log 的 JSON 结构
  2. 在每个阶段(bind/create/update/sync)添加日志记录
  3. 持久化 sync_log,用于审计和调试
  4. 提供查询接口,筛选特定类型的日志

验收标准

  • 每个节点的 sync_log 记录了完整的处理历史
  • 可以通过 sync_log 回溯任何状态变化
  • 失败节点的 sync_log 包含详细的错误信息

第四阶段:代码质量与结构优化

4.1 代码重复消除

问题诊断

  • 搜索重复的业务键提取逻辑
  • 搜索重复的 ID 解析逻辑
  • 搜索重复的数据校验逻辑

重构任务

Task 4.1.1: 业务键处理统一

# sync_system_new/sync_system/biz_key.py (新建)
class BizKeyExtractor:
    """业务键提取与处理"""
    
    @staticmethod
    def extract_from_data(
        data: Dict[str, Any],
        fields: List[str]
    ) -> Optional[Dict[str, Any]]:
        """从数据中提取业务键"""
        pass
    
    @staticmethod
    def to_tuple(biz_key: Dict[str, Any]) -> tuple:
        """转换为可哈希的 tuple"""
        pass
    
    @staticmethod
    def is_complete(biz_key: Dict[str, Any]) -> bool:
        """检查业务键是否完整(无空值)"""
        pass

操作步骤

  1. 创建 biz_key.py,集中业务键处理逻辑
  2. 从各个 Strategy 中提取重复代码
  3. 统一业务键的提取、验证、比较逻辑
  4. 添加单元测试

验收标准

  • 业务键处理逻辑在一个文件中
  • 各 Strategy 调用统一的工具方法
  • 代码行数减少 20% 以上

4.2 错误处理统一

问题诊断

  • 检查是否有裸露的 try-except
  • 检查异常类型是否明确
  • 检查错误信息是否包含足够的上下文

重构任务

Task 4.2.1: 自定义异常体系

# sync_system_new/common/exceptions.py (新建)
class SyncSystemException(Exception):
    """同步系统基础异常"""
    pass

class StateTransitionError(SyncSystemException):
    """非法状态转换"""
    def __init__(self, from_status, to_status, reason):
        self.from_status = from_status
        self.to_status = to_status
        super().__init__(
            f"Illegal state transition: {from_status} -> {to_status} | {reason}"
        )

class DependencyError(SyncSystemException):
    """依赖错误"""
    def __init__(self, node_id, dependency_errors):
        self.node_id = node_id
        self.dependency_errors = dependency_errors
        super().__init__(
            f"Dependency error for {node_id}: {'; '.join(dependency_errors)}"
        )

class DataValidationError(SyncSystemException):
    """数据校验错误"""
    pass

class BindingConflictError(SyncSystemException):
    """绑定冲突(如 N:N"""
    pass

操作步骤

  1. 创建 exceptions.py,定义异常类型
  2. 替换通用异常为自定义异常
  3. 在异常中包含足够的上下文信息
  4. 在顶层捕获并记录异常

验收标准

  • 所有业务异常都是 SyncSystemException 的子类
  • 异常信息包含 node_id、node_type 等上下文
  • 顶层有统一的异常处理和日志记录

4.3 类型注解完善

问题诊断

  • 检查是否所有方法都有类型注解
  • 检查返回值是否都有明确类型
  • 运行 mypy 检查类型错误

重构任务

Task 4.3.1: 类型注解审查

# 运行 mypy 检查
mypy sync_system_new/ --strict

操作步骤

  1. 为所有公共方法添加类型注解
  2. 为复杂的返回值定义 TypedDict 或 Pydantic 模型
  3. 修复 mypy 报告的类型错误
  4. 添加 mypy 到 CI/CD 流程

验收标准

  • mypy 检查通过(允许少量 type: ignore
  • 所有公共 API 都有完整的类型注解
  • IDE 可以提供准确的类型提示

4.4 文档字符串完善

问题诊断

  • 检查关键类/方法是否有 docstring
  • 检查 docstring 是否符合 Google/Numpy 风格

重构任务

Task 4.4.1: Docstring 补充

class BaseSyncStrategy:
    """
    同步策略基类。
    
    职责:
    1. bind(): 判定 binding_status
    2. create(): 处理孤儿节点
    3. update(): 处理差异节点
    4. pre_sync_check() / post_sync_check(): 状态验证
    
    子类使用示例:
    ```python
    class ProjectStrategy(DefaultSyncStrategy):
        default_config = StrategyConfig(
            auto_bind_fields=["code"],
            local_orphan_action=OrphanAction.CREATE_REMOTE
        )
        schema = ProjectResponse
    ```
    
    参考文档:
    - 架构分层设计.md § 3
    - 状态定义规范.md § 1-4
    """
    
    def bind(self):
        """
        判定绑定状态。
        
        执行步骤:
        1. 核心状态判定(状态定义规范 § 1)
        2. 依赖检查(状态定义规范 § 2)
        3. 自动绑定尝试(状态定义规范 § 3)
        
        状态转换:
        - UNCHECKED -> NORMAL/MISSING/ABNORMAL/WARNING/DEPENDENCY_ERROR
        
        Raises:
            DependencyError: 依赖节点未就绪
            BindingConflictError: 出现 N:N 绑定冲突
        """
        pass

操作步骤

  1. 为所有公共类添加类级别 docstring
  2. 为所有公共方法添加方法级别 docstring
  3. 在 docstring 中引用相关文档章节
  4. 添加使用示例和注意事项

验收标准

  • 核心类(SyncNode, BaseSyncStrategy, FullSyncPipeline 等)都有完整的 docstring
  • 关键方法都有参数说明、返回值说明、异常说明
  • 文档引用链接正确

第五阶段:测试覆盖与 pytest 修复

5.1 单元测试强化

问题诊断

  • 运行 pytest,检查失败的测试
  • 检查测试覆盖率(目标 >80%

重构任务

Task 5.1.1: 修复现有测试

# 运行测试并查看失败原因
pytest sync_system_new/tests/ -v --tb=short

# 检查覆盖率
pytest sync_system_new/tests/ --cov=sync_system_new --cov-report=html

操作步骤

  1. 运行 pytest,逐个修复失败的测试
  2. 更新测试用例,匹配重构后的代码
  3. 添加缺失的测试(特别是状态转换、绑定逻辑)
  4. 确保测试覆盖所有关键路径

验收标准

  • 所有测试通过
  • 核心模块测试覆盖率 >80%
  • 关键逻辑(状态判定、依赖检查、自动绑定)有完整的单元测试

5.2 集成测试补充

问题诊断

  • 检查是否有端到端的集成测试
  • 检查集成测试是否覆盖主要场景

重构任务

Task 5.2.1: 端到端测试场景

# tests/integration/test_full_workflow.py
async def test_full_sync_workflow():
    """
    完整同步流程测试:
    1. 加载 JSONL 数据
    2. 执行策略(bind/create/update
    3. 推送到 API
    4. 验证结果
    """
    pass

async def test_create_failed_recovery():
    """
    CREATE 失败恢复测试:
    1. 模拟 CREATE 失败
    2. 下次同步自动清理僵尸节点
    3. 重新尝试 CREATE
    """
    pass

async def test_dependency_blocking():
    """
    依赖阻断测试:
    1. 父节点 CREATE 失败
    2. 子节点标记为 DEPENDENCY_ERROR
    3. 修复父节点后,子节点自动恢复
    """
    pass

操作步骤

  1. 创建 tests/integration/ 目录
  2. 编写端到端集成测试
  3. 使用真实的 JSONL 数据和 Mock API
  4. 验证关键场景(自动绑定、CREATE 失败恢复、依赖阻断)

验收标准

  • 有至少 5 个集成测试场景
  • 集成测试覆盖主要业务流程
  • 集成测试可以在 CI/CD 中自动运行

第六阶段:文档与代码对齐

6.1 文档与代码对齐检查

问题诊断

  • 逐个对照文档,检查代码实现是否一致
  • 检查文档中的示例代码是否可运行

重构任务

Task 6.1.1: 对齐检查清单

文档章节 代码位置 对齐状态 备注
架构分层设计 § 2 common/sync_node.py SyncNode 定义
架构分层设计 § 3 sync_system/strategy.py ⚠️ 需补充 ID 替换逻辑
状态定义规范 § 1 sync_system/binding_matrix.py 需新建
状态定义规范 § 2 sync_system/dependency_checker.py ⚠️ 需强化
状态定义规范 § 3 sync_system/auto_binder.py 需新建
编排流程规范 pipeline/full_sync_pipeline.py 流程正确
持久化与人工介入规范 § 1.2 common/state_reset.py 阶段1/2 重置

操作步骤

  1. 创建对齐检查表
  2. 逐个章节对照代码
  3. 标记不一致的地方
  4. 更新代码或文档,确保一致

验收标准

  • 所有文档章节都有对应的代码实现
  • 代码实现严格遵循文档规范
  • 文档示例代码可以直接运行

6.2 文档更新

问题诊断

  • 检查重构后的代码是否需要更新文档
  • 检查是否有新增的设计决策需要文档化

重构任务

Task 6.2.1: 文档更新清单

  • 更新 架构分层设计.md,补充新模块说明
  • 更新 状态定义规范.md,补充状态转换图
  • 创建 日志规范.md,说明日志格式和级别
  • 创建 异常处理规范.md,说明异常类型和处理
  • 更新 README.md,补充使用示例

操作步骤

  1. 根据重构内容,识别需要更新的文档
  2. 更新或创建文档
  3. 添加架构图和流程图(使用 Mermaid)
  4. 添加代码示例和最佳实践

验收标准

  • 文档完整覆盖重构后的架构
  • 文档包含清晰的架构图和流程图
  • 文档包含可运行的示例代码

执行计划与优先级

优先级定义

  • P0 (关键):影响正确性,必须立即修复
  • P1 (高):影响可维护性,应尽快完成
  • P2 (中):改善代码质量,可以分批完成
  • P3 (低):锦上添花,时间允许时完成

阶段划分

阶段 优先级 预计工时 依赖关系
第一阶段:核心状态机强化 P0 3-4 天
第二阶段:持久化与状态重置 P0 1-2 天 第一阶段
第三阶段:日志与可观测性 P1 2-3 天 第一、二阶段
第四阶段:代码质量优化 P2 2-3 天 第一阶段
第五阶段:测试覆盖 P1 2-3 天 第一、二阶段
第六阶段:文档对齐 P2 1-2 天 所有阶段

建议执行顺序(3天计划)

Day 1

  1. 完成第一阶段(状态机强化)- P0
  2. 完成第二阶段(持久化审查)- P0

Day 2: 3. 完成第三阶段(日志强化)- P1 4. 完成第五阶段(pytest 修复)- P1

Day 3: 5. 完成第四阶段(代码优化)- P2 6. 完成第六阶段(文档对齐)- P2 7. 全面回归测试


验收标准

代码质量指标

  • pytest 通过率: 100%
  • 测试覆盖率: 核心模块 >80%
  • mypy 类型检查: 通过(允许 <10 个 type: ignore
  • 代码重复率: <5% (使用 pylint 检查)
  • 文档覆盖率: 所有公共 API 都有 docstring

功能完整性

  • 所有业务类型可以从零推送
  • CREATE 失败自动恢复
  • 依赖阻断正确工作
  • 自动绑定只在 1:1 场景触发
  • 手工绑定永不自动修改

可观测性

  • 每个节点都有完整的 sync_log
  • 关键操作都有结构化日志
  • 错误信息包含足够的上下文
  • 可以通过日志快速定位问题

文档一致性

  • 代码实现与文档规范一致
  • 文档示例代码可运行
  • 架构图和流程图准确

附录:重构检查清单

状态机检查

  • 状态转换是否经过 StateMachine 验证
  • 每次转换是否都有日志
  • 是否有非法的状态路径

绑定逻辑检查

  • 核心判定表是否实现(状态定义规范 § 1)
  • 依赖检查是否完整(状态定义规范 § 2)
  • 自动绑定是否只在 1:1 场景触发(状态定义规范 § 3)
  • DEPENDENCY_ERROR 格式是否符合规范

持久化检查

  • depend_ids 是否不持久化
  • 阶段1重置是否正确
  • 阶段2清理是否完整
  • 绑定记录是否永久保留

日志检查

  • 是否使用结构化日志
  • 关键操作是否都有日志
  • 日志级别是否合理
  • sync_log 是否记录完整历史

错误处理检查

  • 是否使用自定义异常
  • 异常信息是否包含上下文
  • 是否有顶层异常处理
  • 错误是否正确传播

代码质量检查

  • 是否有重复代码
  • 是否有明确的类型注解
  • 是否有完整的 docstring
  • 是否通过 mypy 检查

总结

本重构提纲基于以下文档制定:

  1. 架构分层设计.md - 四层架构模型
  2. 状态定义规范.md - 状态机逻辑
  3. 编排流程规范.md - Pipeline 流程
  4. 持久化与人工介入规范.md - 持久化和重置规则
  5. 业务流程与依赖关系.md - 业务实体依赖

核心目标

  • 删繁就简:消除重复,提取公共逻辑
  • 状态机强化:严格遵循状态定义规范
  • 日志完善:结构化日志,完整的 sync_log
  • 持久化规范:阶段1/2 重置,绑定记录保护
  • 代码质量:类型安全,错误处理,文档完善

关键原则

  • 以文档为准,代码严格遵循规范
  • 类型安全优先,充分利用 Python 类型系统
  • 可观测性优先,完善的日志和错误信息
  • 单一职责,每个模块只做一件事
  • 可测试性,易于编写和维护测试

按照此提纲逐步执行,可以系统性地提升代码质量,同时保持与文档的一致性。