我正在对我维护的遗留系统进行一些探索, 依赖型 (很棒的工具,看看),前几天。我的发现差点让我把一口咖啡喷到屏幕上。该系统中按圈复杂度降序排列的前 3 个函数是:

  1. SomeAspNetGridControl.CreateChildControls(CC 171!!!)
  2. SomeFormControl.AddForm(CC of 94)
  3. SomeSearchControl.SplitCriteria(CC of 85)

我的意思是171,哇!!!难道不应该吗 20以下 或者其他的东西?所以这让我想知道。您维护或重构的最复杂的功能是什么?您将如何重构这样的方法?

笔记: 我测量的 CC 是针对代码,而不是 IL。

有帮助吗?

解决方案

与我几年前开发的一些 20 世纪 70 年代的老式 COBOL 相比,这简直就是小孩子的东西。我们用的是原来的 麦凯布 工具以图形方式显示某些代码的 CC。打印输出是纯黑色的,因为显示功能路径的线条非常密集并且像意大利面条一样。我没有具体数字,但肯定比 171 高很多。

该怎么办

代码完成 (第一版):

如果分数是:

  • 0-5 - 常规可能没问题
  • 6-10 - 开始思考如何简化日常工作
  • 10+ - 将例程的一部分分解为第二个例程并从第一个例程调用它

在打破原始例程时编写单元测试可能是个好主意。

其他提示

这是当前在产品中发布的 C/C++ 代码:

我可以可靠识别的最高 CC 值(即我不怀疑该工具错误地为 main(...) 的不相关实例添加了复杂性值:

  • 图像处理函数:184
  • 具有验证功能的数据库项加载器:159

还有一个 CC = 339 的测试子例程,但这并不是严格意义上的发货产品的一部分。让我想知道如何才能真正验证其中实施的测试用例......

是的,函数名称已被隐藏以保护有罪者:)

如何更改:

人们已经在努力解决这个问题。这些问题主要由两个根本原因引起:

  1. 意大利面条式代码(没有封装,大量复制粘贴)
  2. 一些没有经过真正的软件构建/工程/木工培训的科学家向产品组提供的代码。

主要方法是识别意大利面条的有凝聚力的部分(拉动一根线:))并将冗长的功能分解为较短的功能。通常,可以将映射或转换提取到函数或辅助类/对象中。改用 STL 而不是手工构建的容器和迭代器也可以减少大量代码。使用 std::string 代替 C 字符串有很大帮助。

我找到了对此的另一种意见 这个博客条目 当与各种代码库进行比较时,这似乎很有意义并且对我有用。我知道这是一个非常固执己见的话题,所以 YMMV。

  • 1-10 - 简单,风险不大
  • 11-20 - 复杂,低风险
  • 21-50 - 太复杂,中等风险,注意
  • 超过50个——太复杂,无法测试,风险高
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top