[Paper] Code Smells 在 Efferent Neighbors 对 Class Stability 的影响

发布: (2026年2月13日 GMT+8 22:15)
9 分钟阅读
原文: arXiv

Source: arXiv - 2602.12950v1

Overview

本文研究了一种隐藏的软件不稳定来源:存在于给定类所依赖的类(其外向邻居)中的代码异味。大多数以往工作仅关注被修改类内部的异味,而作者展示了来自有异味依赖的“涟漪效应”——以及这些异味在依赖之间的相互作用——如何显著降低类的稳定性。通过对 100 个流行开源项目一年内的提交进行挖掘,量化了这些外部异味对未来更改频率和规模的预测能力。

关键贡献

  • 经验性证据表明邻近类的异味重要性: 证明依赖类中的代码异味会增加干净类变得不稳定的可能性。
  • “代码异味相互关系”和“代码异味交互”的定义与度量: 引入正式度量来捕捉异味在静态依赖边上的共现情况。
  • 大规模数据集: 分析了 100 个星标最高的 GitHub 仓库(≈ 1 M+ 类,> 10 M+ 提交),拥有一年以上的历史,提供了坚实的经验基础。
  • 类稳定性的预测模型: 构建了回归和生存分析模型,纳入邻居异味特征,相较仅考虑类内异味的基线模型实现了统计显著的改进。
  • 面向开发者和工具构建者的实用指南: 提供可操作的洞见,指明在何处集中重构工作以抑制未来的不稳定性。

方法论

  1. 项目选择与数据收集 – 作者挑选了 100 个星标最高的 GitHub Java 项目,克隆每个仓库,并提取了一整年的提交历史(作者、时间戳、修改的文件)。
  2. 静态分析 – 使用 SpotBugsPMD 规则集,检测一系列常见的代码异味(例如 God Class、Long Method、Feature Envy)。利用 JDepend 构建依赖图,以识别每个类的外向(efferent)边。
  3. 定义关联性与交互性
    • 关联性:在同一类内部或跨依赖边出现的不同异味类型的计数。
    • 交互性:二元标记,指示两个直接相连的类是否各自至少包含一个异味,从而形成“异味‑到‑异味”链接。
  4. 稳定性度量 – 对每个类,稳定性衡量为 每月修改该类(或其公共 API)的提交次数,并按其规模(代码行数 LOC)进行归一化。
  5. 建模 – 作者拟合了多元线性回归和 Cox 比例风险模型,使用的预测变量包括:
    (i) 类内部异味计数,
    (ii) 外向邻居的总异味计数,
    (iii) 关联性得分,和
    (iv) 交互性标记。
    模型性能通过 R²、AIC 和交叉验证进行评估。
  6. 统计验证 – 通过假设检验(Wilcoxon、Mann‑Whitney)和效应量计算,确认邻居异味变量对稳定性具有非平凡的影响。

结果与发现

发现数据显示的内容
邻居气味增加不稳定性类的外向邻居包含 ≥ 2 个气味的类,其提交频率比邻居干净的类高 23 %(p < 0.01)。
相互关联放大效果当一个类和至少一个邻居共享相同的气味类型(例如,两者都有 God Class)时,不稳定性提升至 35 %
交互是强预测因子单独的二元“气味‑对‑气味”交互标志解释了 12 % 的稳定性方差,优于类内气味计数(8 %)。
预测模型改进添加邻居气味特征将基线模型的调整后 R² 从 0.31 提升至 0.44,表明 约 45 % 的未解释方差被消除。
时间维度生存分析显示,暴露于有气味邻居的类在六个月内成为“非稳定”(定义为每月 > 3 次提交)的风险比为 1.68

简而言之,类外部的气味——尤其是跨依赖关联的气味——对类需要更改的频率产生可衡量的负面影响。

Source:

实际影响

  • 优先重构有异味的依赖 – 能够显示 “热点” 类的工具也应同时显示它们的 外向 异味邻居。修复一个被许多其他类依赖的 God Class 可以降低整个模块的变更频率。
  • 依赖感知的代码审查清单 – 审查者可以标记修改了已知存在异味依赖的类的 PR,进而触发额外的测试或快速的合理性检查。
  • 自动化稳定性仪表盘 – 将论文中的度量(邻居异味计数、相互关联得分)集成到 CI 仪表盘,用于预测未来的维护工作量并主动分配资源。
  • 架构层面的决策 – 在设计微服务或模块化库时,目标是保持 低异味 的公共 API;即使内部组件充斥异味,干净的 API 仍会拖累客户端的稳定性。
  • 工具扩展 – 现有的静态分析插件(如 SonarQube、IntelliJ 检查)可以扩展为计算 “异味交互热图”,可视化依赖图中相互关联的异味簇。

限制与未来工作

  • 语言与生态系统聚焦: 本研究仅限于 Java 项目;其他语言使用不同的依赖机制(例如 JavaScript 中的动态导入)可能会表现出不同的模式。
  • 仅静态依赖: 运行时或反射式依赖未被捕获,这可能低估了在高度依赖反射或 DI 容器的框架中的涟漪效应。
  • 提交频率作为不稳定性的代理: 虽然被广泛使用,但提交次数并未区分琐碎更改与重大更改;未来工作可以加入变更规模度量或 issue‑tracker 数据。
  • 因果推断: 本分析是相关性的;需要受控实验或纵向干预(例如有针对性的重构)才能确认因果关系。
  • 更广泛的异味分类法: 作者使用了一套固定的流行异味;探索更新的或领域特定的异味(例如安全相关的反模式)可以扩展研究发现。

底线: 通过超越类的“内部”,并考虑其邻居的健康状况,开发者可以更准确地预测并缓解未来的维护难题。此研究为更智能、依赖感知的质量工具打开了大门,使代码库保持稳定,开发者更为满意。

作者

  • Zushuai Zhang
  • Elliott Wen
  • Ewan Tempero

论文信息

  • arXiv ID: 2602.12950v1
  • 分类: cs.SE
  • 出版日期: 2026年2月13日
  • PDF: 下载 PDF
0 浏览
Back to Blog

相关文章

阅读更多 »