其他
需要排查代码库架构坏味道…
对项目、模块或最近变更进行架构坏味道、反模式与算法复杂度热点分析,输出带证据、严重性、修复路线图的报告。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 48/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 57/100 ×0.15
适用场景
需要排查代码库架构坏味道、反模式和算法复通用
解决思路
- 明确分析范围:询问用户选择 A. 整个项目;B. 指定模块/目录;C. 仅最近变更文件(git diff);D. 仅架构级问题(跳过低级代码坏味道)。
- 若用户未指定范围:小于 100 个文件的项目默认整个项目;大项目默认仅最近变更文件(git diff)。
- 使用 Explore 子代理(`Agent` 且 `subagent_type: "Explore"`)扫描代码库,并行运行多个探索任务以收集架构模式和反模式证据。
- 项目结构扫描:映射目录树,识别架构风格(分层、模块化单体、微服务等)。
- 依赖分析:查找 import/include 模式,检查循环依赖,识别耦合热点。
- 模块/组件扫描:识别 God Objects(文件 > 500 行),检查内聚,检查单一职责违规。
- 模式检测:查找已知反模式特征(static cling、service locator abuse、leaky abstractions)。
- 测试扫描:检查测试覆盖模式、测试文件位置、测试与代码比例。
- 命名与清晰度扫描:标记误导性名称、过度泛化名称(Manager、Helper、Util)、不一致命名约定。
- 复杂度扫描:检测算法复杂度热点——嵌套循环、N+1 查询、重复扫描、sort-in-loop、渲染路径昂贵重算。
- 把所有启发式视为候选信号而非发现;行数、嵌套、命名或 Big-O 匹配必须结合代码职责、调用者、变更历史、工作负载和有意约束验证;不要仅凭阈值分配严重性。
- 处理每个候选分三阶段:1)候选检测:静态模式、文件指标、依赖扫描只产生候选;2)上下文验证:阅读实现和相关调用者,检查变更频率、输入大小、运行频率、框架约束、生成/vendor 状态、现有缓解措施;3)发现确认:合并同一根因、影响路径、失败/变更场景、修复方向的候选为一个发现。
- 按独立根因计数发现,绝不按牵连的原则数量计数;使用一个 Primary principle 和可选 Related principles。
- SOLID 是伞标签;证据支持具体镜头时用 SRP、OCP 或 DIP 作为 primary,不要另外创建 SOLID 发现。
- 按 11 原则矩阵确认发现:SOLID 仅在设计问题跨多个 SOLID 镜头或无更窄镜头可靠时使用,不要重复具体 SRP/OCP/DIP 发现。
- DRY 确认证据:同一业务规则或知识必须在多个地方变更;常见误报:预期独立演进的相似语法。
- KISS 确认证据:额外层、间接或机械增加成本且无 observable leverage;常见误报:小抽象移除了真实复杂性。
- YAGNI 确认证据:未使用的扩展点、参数、适配器或投机需求;常见误报:现有边界或变更所需的已测试接缝。
- SRP 确认证据:多个独立变更原因,由职责或变更历史支持;常见误报:仅文件大小或方法数。
- Open/Closed (OCP) 确认证据:添加已知变体反复修改稳定分支逻辑;常见误报:一个简单、局部条件。
- Dependency Inversion (DIP) 确认证据:高层策略直接依赖具体基础设施,损害替换或测试;常见误报:为单一稳定实现加接口。
- Composition 确认证据:继承导致不想要的耦合、拒绝行为或不可分离变化轴;常见误报:机械替换每个有效继承关系。
- Separation of Concerns 确认证据:业务策略、I/O、展示或持久化关注点跨边界泄漏;常见误报:故意很薄的边界适配器。
- Fail Fast 确认证据:无效输入、状态或依赖传播到远处操作才失败;常见误报:有意聚合、重试或延迟验证语义。
- Measure First 确认证据:性能、规模或优化声明缺少基线或代表性工作负载;常见误报:把静态复杂度报告为已测量瓶颈。
- 为每个确认发现记录证据强度(Measured、Observed 或 Inferred)并与置信度(High、Medium 或 Low/Candidate)分开;证据强度不暗示严重性。
- 按严重性 rubric 分类:Critical 为正确性、可靠性、安全、数据一致性或已测量系统级影响且通常需高置信度;Warning 为明确影响范围且反复变更/运行成本有具体维护或运行后果;Suggestion 为局部、低频或有限影响且有证据的改进;Candidate requiring measurement 为静态信号但影响未知,排除出严重性总数并放入单独报告章节。
- 生成报告并包含结构:标题、Project、Scope、Date、Analyzer;Executive Summary;Architectural Style Detected;Style Expectations vs. Reality 表;Findings by Category;Detailed Findings;Dependency Graph Analysis;Module Health Scorecard;Smell Distribution;Refactoring Roadmap;Appendix: Anti-Pattern Reference。
- Executive Summary 只总结已确认发现:检测到的架构风格、整体健康评估、前 3-5 个关键问题;候选单独提及。
- Architectural Style Detected 中识别架构风格(Layered、Modular Monolith、Microservices、Hexagonal、Clean Architecture 或 Big Ball of Mud),并用 Style Expectations vs. Reality 表列出期望、现实、状态(✅/⚠️/🔴)。
- Findings by Category 分节:🔴 Critical Issues(Must Fix)、🟡 Warnings(Should Fix)、🔵 Suggestions(Nice to Fix)、Candidates Requiring Measurement(不计入严重性总数)。
- 每个 Detailed Finding 记录字段:Category、Severity、Anti-Pattern、Location(file:line 和相关调用者)、Confidence、Evidence strength、Failure or change scenario、Primary principle、Related principles(仅解释,不单独计数)、Description、Evidence、Measured/observed impact、Recommendation(最小合理重构)、Verification(如何证明行为和影响)。
- Dependency Graph Analysis 汇总模块依赖、发现的循环依赖、耦合热点。
- Module Health Scorecard 按模块列出:Module、Lines、God Object Risk、Coupling、Cohesion、Test Coverage、Health(🟢/🟡/🔴)。
- Smell Distribution 只按去重后的确认发现的主类别计数;Related principles 和候选不影响总数;表列 Category、Count、Critical、Warning、Suggestion。
- Refactoring Roadmap 按影响、置信度、依赖顺序和验证成本排序,而不是按原则数量或 smell 名称;Immediate Actions 只放高置信度可验证发现,候选则推荐下一步测量而非重写。
- Refactoring Roadmap 分 Immediate Actions(This Sprint)、Short-Term(1-3 Months)、Long-Term(3-12 Months),分别列可操作修复、结构改进、架构转型。
- Appendix: Anti-Pattern Reference 提供检查过的反模式浓缩参考和简短描述。
- 将报告保存到 `tasks/smell-report-[YYYY-MM-DD-HHmm].md`,若路径冲突则追加 `-2`、`-3` 等。
- 向用户呈现已确认发现摘要,并把候选发现单独列出。
- 检测架构坏味道 Big Ball of Mud:无清晰目录结构;所有内容在根目录或一个扁平文件夹;无关注点分离。
- 检测架构坏味道 Violated Layer Boundaries:内层导入外层;基础设施代码位于 domain/core 层。
- 检测架构坏味道 Missing Architecture:没有 `src/`、`lib/`、`core/` 分离;SQL 与 UI 代码内联;HTTP handler 与业务逻辑混合。
- 检测架构坏味道 Distributed Monolith:微服务共享数据库;服务不能独立部署。
- 检测架构坏味道 Anemic Domain Model:Model/entity 类只有 getter/setter 且无行为;所有逻辑在 services 中。
- 检测架构坏味道 CQRS Without Need:简单 CRUD 使用分离读写模型;不必要的复杂性。
- 检测架构坏味道 Over-Layered Architecture:过多层/层,只增加无真实价值的 pass-through 代码。
- 检测架构坏味道 Over-Abstraction:过多间接、接口、泛型,导致跟踪代码时迷失。
- 检测架构坏味道 Futuristic Architecture:为可能永远不会来的需求做投机灵活性(预测未来)。
- 检测架构坏味道 Technology-Enthusiast Architecture:因为技术新而不是因为适合,就把闪亮/未经验证的技术用到生产。
- 检测架构坏味道 Overkill Architecture:用重量级架构/技术解决简单问题。
- 检测架构坏味道 Cloud/Visio Architecture:图与实际代码和运行时现实脱节。
- 检测耦合坏味道 Circular Dependencies:模块 A 导入 B,B 导入 A;通过 import graph 分析检测。
- 检测耦合坏味道 Content Coupling:一个模块直接访问另一个模块的内部/私有成员。
- 检测耦合坏味道 Common Coupling:过多全局变量/共享可变状态;singleton 滥用。
- 检测耦合坏味道 Stamp Coupling:只需要少数字段却传递大数据结构。
- 检测内聚坏味道 God Object:单类/模块 > 500 行;> 20 个公共方法;处理不相关关注点。
- 检测内聚坏味道 Shotgun Surgery:单个变更需要跨不相关模块触及 5+ 个文件。
- 检测内聚坏味道 Feature Envy:方法调用外部类方法比调用自身类方法更多。
- 检测内聚坏味道 Data Clumps:同一组 3+ 参数在多个方法签名中一起出现。
- 检测内聚坏味道 Divergent Change:一个模块因许多不相关原因被修改(与 Shotgun Surgery 相反)。
- 检测内聚坏味道 Data Class:类只有字段加 getter/setter,无行为(贫血数据袋)。
- 检测内聚坏味道 Lazy Class:类/模块做得太少,不足以证明其存在。
- 检测设计坏味道 Leaky Abstractions:通过接口暴露实现细节(DB 查询、HTTP 调用)。
- 检测设计坏味道 Static Cling:过度使用静态方法;静态状态阻碍可测试性。
- 检测设计坏味道 Service Locator Abuse:传递 DI 容器而不是正确构造函数注入。
- 检测设计坏味道 Violated SOLID:SRP 违规、OCP 违规(对类型使用 switch/if-else 链)、ISP 违规(胖接口)。
- 检测设计坏味道 Switch Statements:对类型代码的相同 switch/if-else 链出现在多个地方;应改为多态。
- 检测设计坏味道 Refused Bequest:子类继承不使用的方法/字段,或覆盖为 throw/no-op。
- 检测设计坏味道 Alternative Classes w/ Different Interfaces:两个类做同一件事但方法命名不同。
- 检测设计坏味道 Parallel Inheritance Hierarchies:在一个层级中创建子类会强制在另一个层级创建匹配子类。
- 检测设计坏味道 Speculative Generality:未使用的抽象类、hook、参数或泛型“为未来需要”(YAGNI)。
- 检测设计坏味道 Incomplete Library Class:因第三方类缺少所需方法而包装/修补它。
- 检测耦合坏味道 Inappropriate Intimacy:两个类过多访问彼此私有/内部部分。
- 检测耦合坏味道 Message Chains:长调用链 `a.getB().getC().getD()`(违反 Law of Demeter)。
- 检测耦合坏味道 Middle Man:类只把每次调用委托给另一个类。
- 检测代码坏味道 Temporary Field:实例字段只在特定情况下设置/使用,否则为空。
- 检测代码坏味道 Duplicated Code:相同/相似逻辑出现在 3+ 处;复制粘贴模式。
- 检测代码坏味道 Long Method:方法 > 50 行;嵌套深度 > 3 层。
- 检测代码坏味道 Long Parameter List:方法参数 > 4 个。
- 检测代码坏味道 Primitive Obsession:用 string/int 代替领域类型(例如 `string email` 代替 `Email` 类型)。
- 检测代码坏味道 Magic Numbers/Strings:硬编码字面量没有命名常量。
- 检测代码坏味道 Comments as Deodorant:过度注释解释坏代码而不是重构。
- 检测代码坏味道 Dead Code:未使用 import、不可达代码、注释掉的代码块。
- 检测测试坏味道 No Tests:模块零测试覆盖。
- 检测测试坏味道 Test-Implementation Coupling:测试断言内部实现细节而非行为。
- 检测测试坏味道 Slow Tests:测试做真实 I/O、数据库调用、网络请求且未 mock。
- 检测命名坏味道 Vague Names:过度使用 `Manager`、`Handler`、`Processor`、`Helper`、`Util`、`Service`、`Data`、`Info` 且无上下文。
- 检测命名坏味道 Inconsistent Naming:snake_case 和 camelCase 混用;同一概念用不同模式。
- 检测可读性坏味道 Deep Nesting (Arrow Anti-Pattern):循环/条件嵌套 > 3 层;向右漂移的 arrow 形状难以追踪。
- 检测复杂度坏味道 Nested Loops (O(n^2)+):循环套循环;forEach 套 for;map 套 map;嵌套迭代暗示多项式复杂度。
- 检测复杂度坏味道 Repeated Linear Scan:循环内使用 `includes()`/`indexOf()`/`.find()`;列表上 O(n*m) 成员检查,应改为 Set/Map。
- 检测复杂度坏味道 Sort-in-Loop:迭代代码中调用 `.sort()` 或 `sorted()`;可只排序一次却反复 O(n log n)。
- 检测复杂度坏味道 N+1 Query Pattern:循环内数据库/API/HTTP 调用;每次迭代 fetch/query/execute/findMany 而不是批量。
- 检测复杂度坏味道 Render-Path Recompute:组件 render body 中 `.filter().map().sort()` 链;无 memoization 的昂贵转换。
- 检测复杂度坏味道 Pairwise Comparison:嵌套迭代把每个元素与每个其他元素比较;O(n^2),而 sort+two-pointer 可为 O(n log n)。
- 检测复杂度坏味道 Unnecessary Recompute:同一昂贵计算无缓存重复;缺少 `useMemo`/`memo`/lazy eval。
- 检测复杂度坏味道 Wrong Data Structure:用 Array 而 Set/Map 可 O(1) 查找;用 List 而 Queue/Heap/Stack 更自然。
- 对复杂度候选执行 Measure First:1)确定实际输入大小、调用频率、I/O 延迟、路径是否热;2)优先 profiler、代表性 benchmark、query log、trace 或明确操作计数;3)仅当工作负载和影响证明时才把候选提升为发现;4)修复后在同一工作负载上重新测量;没有基线不要声称性能提升。
- 对每个复杂度候选项说明:要测量什么、何时成为发现、何时不应标记;保留 Big-O 分析和正确性检查,但不要仅从语法推断严重性。
- 不要标记 What NOT to Flag:冷路径(仅启动、配置加载或极小 N < 100)的复杂度;有意权衡(清晰 O(n) 代码而 O(n log n) 只增加复杂性无测量收益);已经优化(已用 Map/Set、已批量加载、已有 memoization)。
- 对 Nested Loops 修复:为内层集合建 Map/Set 索引 → O(n+m);sort + two-pointer → O(n log n);分组/分桶后再迭代;区间/范围问题用 sweep-line;检查顺序、重复键、原逻辑取 first/last/all 匹配。
- 对 N+1 Query Pattern 修复:按 ID 批量取 `SELECT * FROM x WHERE id IN (...)` 后在内存 join;使用 ORM eager-loading/`include`/`preload`/DataLoader;批量 API 端点接受数组;保留 auth 过滤、租户隔离、排序、分页、错误语义;不要取原逐项逻辑未授权的记录;保留缺失记录行为。
- 对 Repeated Linear Scan 修复:循环前建一次 `Set`(成员检查)或 `Map`(键→值查找);检查相等语义变化、JavaScript 对象身份 vs 值相等、Python hashability。
- 对 Sort-in-Loop 修复:循环外排序一次;需要增量 top-K 用 heap(PriorityQueue);用二分搜索/插入到已排序集合;检查每个中间排序状态是否外部可观察、比较器是否依赖循环局部状态。
- 对 Render-Path Recompute 修复:用 `useMemo`/`computed`/`derived` 并正确依赖数组;把派生移到 selectors、loaders 或服务端;虚拟化长列表(windowing);仅在影响子渲染时稳定 callback 和对象 props;检查依赖数组包含每个语义输入、memoization 不隐藏可变输入突变。
- 对 Pairwise Comparison 修复:pair/range 匹配用 sort + two-pointer;区间重叠用 sweep-line;邻近用 spatial hashing 或 grid bucketing;连通性用 union-find;检查顺序稳定性、相等情况 tie-breaking。
- 对 Unnecessary Recompute 修复:添加带正确失效的 memoization/caching;按场景用 `lru_cache`/`memoize`/`useMemo`。
- 对 Wrong Data Structure 修复:按访问模式替换为复杂度匹配的数据结构:Set → O(1) has/add/delete;Map → O(1) get/set;Heap → O(log n) push/pop;Queue/Deque → O(1) enqueue/dequeue。
- 设计原则违规报告契约:使用 Step 3 的 canonical 11-principle matrix;这些检查细化候选检测,不允许每个原则创建一个发现。
- SRP 报告:确认独立变更原因;仅大小不足。
- OCP 报告:确认真实变体被反复编辑;不要用投机多态替换简单局部条件。
- LSP 报告:子类型必须保持基类契约的前置条件、后置条件和不变量;报告为 `SOLID/LSP`。
- ISP 报告:确认客户端依赖不使用的方法;报告为 `SOLID/ISP`。
- DIP 报告:确认高层策略以损害测试或替换的方式耦合具体机制;单个实现不自动证明接口合理。
- DRY 报告:去重共享知识,而不是巧合相似的语法。
- KISS 和 YAGNI 报告:拒绝未来变化或杠杆未被证明的抽象。
- Composition 报告:当继承暴露不想要行为或绑定独立变化轴时优先组合,而不是机械规则。
- Separation of Concerns 报告:确认策略、展示、持久化或 I/O 跨预期边界泄漏。
- Fail Fast 报告:在源头附近检测无效状态,同时保留既有错误、重试、事务和清理语义。
- Measure First 报告:把未测量优化声明降为候选,而不是报告第二个原则违规。
- 检测 OO Abuser Switch Statements:重复 switch/if-else 链基于类型代码或 enum;添加新类型强迫编辑每个 switch(OCP 违规);修复:用多态替换条件(Strategy/State)或 Replace Type Code with Subclasses。
- 检测 OO Abuser Refused Bequest:子类继承不需要的方法/字段;覆盖为 throw、no-op 或做无关事;修复:下推未使用成员,或用委托替换继承。
- 检测 OO Abuser Alternative Classes with Different Interfaces:两个类角色相同但方法命名不同,如 `sort()` vs `arrange()`、`getUser()` vs `fetchUser()`;修复:统一接口(重命名方法、提取公共父类/接口)。
- 检测 OO Abuser Incomplete Library Class:第三方/库类缺少所需方法且不能修改;修复:引入 Foreign Method 或包装为 adapter/本地扩展类。
- 处理边界情况:用户未指定范围时,> 200 文件的 repo 默认 recent changes(`git diff`),否则完整分析。
- 处理边界情况:项目没有清晰架构时报告 Big Ball of Mud 并给证据,建议增量重构。
- 处理边界情况:空项目/monorepo 时报告架构分析需要代码,并要求用户指定模块。
- 处理边界情况:语言不支持时报告一般结构观察,并注明语言特定检查有限。
- 处理边界情况:用户要快速检查时只运行 Critical-level 扫描,跳过 Code 和 Naming 类别。
- 处理边界情况:用户只要一个类别时聚焦该类别分析,跳过其他。
适用边界 · 注意事项
- 项目为空、无代码或未指定模块时,无法进行架构分析,应先要求用户指定模块或提供代码。
- 语言不受支持时只能做一般结构观察,语言特定检查有限。
- 冷路径、极小 N(< 100)、有意权衡或已经优化的代码,不应仅因静态复杂度模式被标记为性能问题。