if-statement - 需要重构 Arrow 反模式的想法

标签 if-statement nested refactoring anti-patterns

我继承了一个怪物。

它伪装成 .NET 1.1 应用程序处理符合医疗保健 claim 支付 (ANSI 835) 标准的文本文件,但它是一个怪物。正在处理的信息涉及医疗保健 claim 、EOB 和报销。这些文件由在前几个位置具有标识符的记录和根据该类型记录的规范格式化的数据字段组成。一些记录 ID 是控制段 ID,用于分隔与特定类型事务相关的记录组。

为了处理一个文件,我的小怪物读取第一条记录,确定即将发生的事务类型,然后根据当前正在处理的事务类型开始处理其他记录。为此,它使用嵌套的 if。由于有许多记录类型,因此需要做出许多决定。每个决策都涉及一些处理和 2-3 个其他决策,需要根据之前的决策做出。这意味着嵌套的 if 有很多嵌套。这就是我的问题所在。

这个嵌套的 if 有 715 行长。是的,这是正确的。七百五十条线。我不是代码分析专家,所以我下载了几个免费软件分析工具,得出的 McCabe 循环复杂度等级为 49。他们告诉我这是一个相当高的数字。与亚特兰大地区的花粉计数一样高,其中 100 是高标准,新闻称“今天的花粉计数为 1,523”。这是我有幸看到的箭头反模式最好的例子之一。在其最高处,缩进深度为 15 个制表符。

我的问题是,你会建议用什么方法来重构或重组这样的东西?

我花了一些时间寻找想法,但没有什么能让我站稳脚跟。例如,用保护条件代替级别是一种方法。我只有其中一个。一窝下来,十四走。

也许有一种设计模式可能会有所帮助。指挥链会是解决这个问题的一种方式吗?请记住,它必须保留在 .NET 1.1 中。

感谢您的任何想法。

最佳答案

本周我刚刚有一些遗留代码在工作,与您所描述的相似(尽管没有那么可怕)。

没有一件事能让你摆脱困境。 state machine可能是您的代码采用的最终形式,但这不会帮助您到达那里,您也不应该在解开已有的困惑之前决定这样的解决方案。

我要采取的第一步是为现有代码编写一个测试。这个测试不是为了证明代码是正确的,而是为了确保你在开始重构时没有破坏一些东西。获取大量数据进行处理,将其提供给怪物,然后获得输出。那是你的试金石。如果您可以使用代码覆盖率工具执行此操作,您将看到您的测试未涵盖的内容。如果可以,构建一些人工记录,这些记录也将执行此代码,然后重复。一旦你觉得你已经完成了这项任务,输出数据将成为你测试的预期结果。

重构不应改变代码的行为。记住这一点。这就是为什么您知道输入和输出数据集来验证您不会破坏事情的原因。这是你的安全网。

现在重构!

我做了几件我觉得有用的事情:

反转if声明

当我找不到相应的 else 时,我遇到的一个大问题是刚刚阅读代码声明,我注意到很多 block 看起来像这样

if (someCondition)
{
  100+ lines of code
  {
    ...
  }
}
else
{
  simple statement here
}

通过反转 if我可以看到一个简单的案例,然后知道另一个已经做了什么,然后进入更复杂的模块。变化不大,但帮助我理解。

提取方法

我经常使用这个。拿一些复杂的多线 block ,摸索它,然后用它自己的方法把它推到一边。这让我更容易看到代码重复的地方。

现在,希望您没有破坏您的代码(测试仍然通过,对吧?),并且您拥有更具可读性和更好理解的过程代码。看它已经改进了!但是你之前写的那个测试还不够好......它只告诉你你复制了原始代码的功能(错误和所有),而这只是你所覆盖的那一行,因为我确定你会发现你无法弄清楚如何命中或永远无法命中的代码块(我在我的工作中都见过)。

现在,所有大牌模式都发挥作用的重大变化是,当您开始考虑如何以适当的 OO 方式对其进行重构时。给这只猫剥皮的方法不止一种,而且会涉及多种模式。不知道您正在解析的这些文件的格式的详细信息,我只能提出一些有用的建议,这些建议可能是也可能不是最佳解决方案。

Refactoring to Patterns是一本很棒的书,可以帮助解释在这些情况下有用的模式。

你想吃一头大象,除了一次咬一口,别无他法。祝你好运。

关于if-statement - 需要重构 Arrow 反模式的想法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/105602/

相关文章:

Mysql 在表中使用 if 条件更新

c# - 条件(三元)运算符中的条件

python - 如何拆分嵌套列表的定义元素

mysql - 多个服务器上的常量

c# - 将公共(public)方法重构到另一个类

C# if else 语句

javascript - 插入 if 语句时函数不执行

vue.js - 在嵌套的 v-for 中使用 v-model

python - 嵌套 for 循环和 if 条件 pandas 替换

java - 像这样使用计时器的目的是什么?