我继承了一个怪物。
它伪装成一个.NET 1.1应用程序处理符合医疗赔付文本文件(ANSI 835)的标准,但它是一个怪物。 正在处理的信息涉及医疗赔付,平等机会条例草案,和偿还。 这些文件包括有在根据规范该类型的记录格式的前几个位置和数据字段的标识符的记录。 一些记录ID控制段ID,其划定的与特定类型的交易记录组。
要处理一个文件,我的小怪物读取第一个记录,确定的那种交易是将要发生的,然后开始处理基于什么样的交易也正在处理其他记录。 要做到这一点,它采用了嵌套如果。 由于有许多记录类型,有需要作出一些决定。 每个决定都涉及一些处理,并需要根据以前的决定进行2-3其他决定。 这意味着嵌套,如果有很多的巢。 这就是我的问题所在。
这一个嵌套如果是715线长。 恩,那就对了。 七百而-FIF-青少年线路。 我没有代码分析专家,所以我下载了几个免费的分析工具,并用49一麦凯布圈复杂度的评价,他们告诉我,这是一个相当高的数字了上来。 高在亚特兰大地区,其中100是高标准和新闻说,“今天的花粉量为1,523”花粉计数。 这是箭反模式我曾经被priveleged看到的最好的例子之一。 在它的最高,缩进去15个标签深。
我的问题是,你会建议什么方法重构或重组这样的事情?
我花了一些时间来寻找的想法,但没有给我一个很好的立足点。 例如,代替一个水平的保护条件的一种方法。 我只有其中的一个。 一个窝,往下,十四中去。
也许有一个设计模式可帮助。 将指挥链是解决这个办法吗? 请记住,它必须留在.NET 1.1。
感谢您的任何和所有的想法。
我只是在工作中,本周是相似的(虽然不是可怕的)一些遗留代码为你所描述的。
有没有一两件事,将让你出这一点。 该状态机可能是最终形式的代码需要,但那不是会帮助你到达那里,也不应该你解开你已经拥有的烂摊子之前,这样的解决方案作出决定。
我将采取的第一步是写的现有代码进行测试。 这个测试是不显示的代码是正确的,但要确保当你开始重构你没有破坏什么。 获取数据的一个大的一叠过程中,饲料的怪物,并获得输出。 这是你的试金石。 如果你能做到这与代码覆盖工具,你会看到你测试不包括什么。 如果可以的话,建造一些人为的记录,也将行使这一代码,并重复。 一旦你觉得你做了什么,你可以用这个任务,输出数据将成为您的测试您预期的结果。
重构不应该改变代码的行为。 记住这一点。 这就是为什么你已经知道输入和已知的输出数据集来验证你是不是要打破的东西。 这是你的安全网。
现在重构!
一对夫妇的事情,我这样做,我发现有用:
倒置if
语句
一个巨大的问题,我只是读的时候我找不到相应的代码else
说法,我注意到很多块看起来像这样
if (someCondition)
{
100+ lines of code
{
...
}
}
else
{
simple statement here
}
通过倒置if
我能看到的简单情况,然后移动到更复杂的块知道什么是另外一个已经做了。 不是一个巨大的变化,但是帮助我理解。
提取方法
我用这一个lot.Take一些复杂的多路块,神交它,在它自己的方法,一边推它。 这让我更容易地看到那里有代码重复。
现在,希望你没有破坏你的代码(测试还通过对吧?),你有更好的可读性和更好地理解程序代码。 你看它已经提高了! 但是,测试你之前写的是不是真的不够好......它只是告诉你,原代码你复制功能(错误和所有),并且那只有你有报道作为行我相信你将发现的代码块,你可以不知道如何打,或只是永远不能打(我已经看到了这两个在我的工作)。
现在,所有的大牌模式开始发挥作用了大的变化是,当你开始寻找如何在一个适当的面向对象的方式重构这个。 还有就是皮肤这只猫不止一种方法,它会涉及到多种模式。 不知道你要分析我只能折腾周围的一些有益的建议可能会或可能不会是最好的解决方案,这些文件的格式的详细信息。
重构到模式是一个伟大的书,以协助explainging是在这些情况下有用的模式。
你想吃掉一头大象,而且也没有其他办法做到这一点,但在一次一口。 祝好运。
一个状态机似乎是逻辑的地方开始,并使用WF如果你能摆动它(听起来像你不能)。
您仍然可以实现一个无WF,你就必须自己做。 然而,从一开始就像一个状态机,它的思维可能会给你一个更好的实现然后创建一个程序的怪物上的每一个动作检查内部状态。
图你的状态,是什么原因导致的过渡。 实际的代码来处理记录应该被分解出来,并呼吁在国家执行(如果某个国家需要它)。
所以状态1的执行调用你的“读取记录”,然后根据该记录转换到另一种状态。
接下来的状态可能读取多个记录和通话记录处理指令,然后转换回状态1。
有一件事我在这些情况下,做的是使用“组合方法”的格局。 见杰里米·米勒的博客文章在这个问题上。 其基本思想是利用重构工具在IDE中提取有意义的小方法。 一旦你做到了这一点,你可以进一步重构并提取有意义的课。
我将与不羁使用提取方法的开始。 如果没有它在当前的Visual Studio IDE中,你可以得到一个第三方插件,或者在较新的相对于负载的项目 (它会尝试升级您的项目,但你会仔细地忽略这些更改,而不是在检查它们。)
你说,你已经缩进代码15个级别。 开始约1/2的出路,以及提取方法。 如果你能想出一个好名字,使用它,但如果你不能,反正提取。 在半再次分裂。 你不会在这里了理想的结构; 你试图打破代码中,将适合在你的大脑碎片。 我的脑子是不是很大,所以我会不断打破和突破,直到它不痛了。
当你去,寻找那些似乎比其他人不同的任何新的长期方法。 在新的班使这些。 只需要使用只有一个方法,现在一个简单的类。 哎呀,使得该方法是静态的罚款。 不是因为你认为他们是很好的课,但因为你是对一些组织如此绝望。
检查你经常去,这样你就可以检查点工作,后来了解历史,准备做一些“真正的工作”,而无需进行合并,并保存你的队友很难合并的麻烦。
最终,你将需要回去确保方法名是好的,您已经创建有意义的一套方法,清理新类等。
如果你有一个高度可靠的提取方法的工具,你可以逃脱没有良好的自动化测试。 (我相信VS在此,例如)。否则,请确保你不打破东西,或者你最终会比你差开始:一个程序,它不工作。
配对搭档将是有益的在这里。
通过描述来看,状态机可能是对付它的最好办法。 有一个枚举变量来存储当前的状态,并执行该处理作为循环过的记录,用开关或if语句来选择该操作利用基于对当前状态和输入数据。 你也可以很容易地派遣工作分开使用函数指针的基础上,国家职能,也一样,如果它变得太笨重。
有一个相当不错的博客帖子大约是在编码恐怖 。 我只碰到过这种反模式一次,我几乎只是跟着他的脚步。
有时我用栈相结合的状态模式。
它非常适用层次结构; 父元素知道什么状态推到栈处理一个子元素,但一个孩子不必知道它的父任何事情。 换句话说,孩子不知道下一个状态是什么,它会发出信号,这是“完全”和被弹出堆栈。 这有助于通过保持依赖性单向解耦彼此的状态。
它的伟大工程与SAX解析器处理XML(内容处理器只是push和pop状态的元素进入和退出,以改变其行为)。 EDI应该借给自己这种做法太。