需要重构Arrow Anti-Pattern的想法 [英] Need refactoring ideas for Arrow Anti-Pattern

查看:134
本文介绍了需要重构Arrow Anti-Pattern的想法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我继承了一个怪物。



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



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



这一个嵌套,如果长715行。恩,那就对了。七百五十条青少年线。我不是代码分析专家,所以我下载了一些免费软件分析工具,并得出了McCabe Cyclomatic Complexity等级为49.他们告诉我这是一个非常高的数字。在亚特兰大地区的花粉数量很高,其中100是高标准,新闻称今天的花粉数量是1,523。这是我见过的箭头反模式中最好的例子之一。在最高处,缩进深度为15个标签。



我的问题是,您建议采用哪种方法来重构或重构这样的东西?



我花了一些时间寻找想法,但没有什么能给我一个良好的立足点。例如,用保护条件代替等级是一种方法。我只有其中一个。一窝下来,十四下去。



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



感谢您提出的所有想法。

解决方案

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



那里是没有一件事可以让你摆脱这一点。 状态机可能是您的代码所采用的最终形式,但那不是帮助你到达那里,在解开已经存在的混乱之前,你也不应该决定这样的解决方案。



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



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



现在重构!



我发现了一些我发现有用的东西:



反转如果语句



<我遇到的一个很大的问题就是在我找不到相应的 else 语句时才读取代码,我注意到很多块看起来像这样

  if(someCondition)
{
100+行代码
{
.. 。
}
}
其他
{
简单声明
}

通过反转如果我可以看到简单的情况,然后转到更复杂的块,知道另一个已经做了什么。不是一个巨大的变化,但帮助我理解。



提取方法



我经常使用它。使用一些复杂的多行块,然后用它自己的方法将它移开。这让我更容易看到代码重复的位置。



现在,希望你没有破坏你的代码(测试仍然通过了吗?),你有更易读和更好理解程序代码。看它已经改进了!但是你之前写的那个测试还不够好......它只会告诉你复制原始代码的功能(错误和全部),那只是你所覆盖的那一行,因为我确定你会发现你无法弄清楚如何击中或者无法击中的代码块(我已经在工作中看到过)。



现在发生了很大的变化所有大牌模式发挥作用的地方在于你开始研究如何以适当的OO方式重构它。皮肤这种猫的方法不止一种,它涉及多种模式。不知道您正在解析的这些文件的格式的详细信息,我只能抛出一些有用或可能不是最佳解决方案的建议。



重构模式是一本很好的书,可以帮助解释在这些情况下有用的模式。



你正在尝试吃大象,除了一口咬一口之外别无他法。祝你好运。


I have inherited a monster.

It is masquerading as a .NET 1.1 application processes text files that conform to Healthcare Claim Payment (ANSI 835) standards, but it's a monster. The information being processed relates to healthcare claims, EOBs, and reimbursements. These files consist of records that have an identifier in the first few positions and data fields formatted according to the specs for that type of record. Some record ids are Control Segment ids, which delimit groups of records relating to a particular type of transaction.

To process a file, my little monster reads the first record, determines the kind of transaction that is about to take place, then begins to process other records based on what kind of transaction it is currently processing. To do this, it uses a nested if. Since there are a number of record types, there are a number decisions that need to be made. Each decision involves some processing and 2-3 other decisions that need to be made based on previous decisions. That means the nested if has a lot of nests. That's where my problem lies.

This one nested if is 715 lines long. Yes, that's right. Seven-Hundred-And-Fif-Teen Lines. I'm no code analysis expert, so I downloaded a couple of freeware analysis tools and came up with a McCabe Cyclomatic Complexity rating of 49. They tell me that's a pretty high number. High as in pollen count in the Atlanta area where 100 is the standard for high and the news says "Today's pollen count is 1,523". This is one of the finest examples of the Arrow Anti-Pattern I have ever been priveleged to see. At its highest, the indentation goes 15 tabs deep.

My question is, what methods would you suggest to refactor or restructure such a thing?

I have spent some time searching for ideas, but nothing has given me a good foothold. For example, substituting a guard condition for a level is one method. I have only one of those. One nest down, fourteen to go.

Perhaps there is a design pattern that could be helpful. Would Chain of Command be a way to approach this? Keep in mind that it must stay in .NET 1.1.

Thanks for any and all ideas.

解决方案

I just had some legacy code at work this week that was similar (although not as dire) as what you are describing.

There is no one thing that will get you out of this. The state machine might be the final form your code takes, but thats not going to help you get there, nor should you decide on such a solution before untangling the mess you already have.

First step I would take is to write a test for the existing code. This test isn't to show that the code is correct but to make sure you have not broken something when you start refactoring. Get a big wad of data to process, feed it to the monster, and get the output. That's your litmus test. if you can do this with a code coverage tool you will see what you test does not cover. If you can, construct some artificial records that will also exercise this code, and repeat. Once you feel you have done what you can with this task, the output data becomes your expected result for your test.

Refactoring should not change the behavior of the code. Remember that. This is why you have known input and known output data sets to validate you are not going to break things. This is your safety net.

Now Refactor!

A couple things I did that i found useful:

Invert if statements

A huge problem I had was just reading the code when I couldn't find the corresponding else statement, I noticed that a lot of the blocks looked like this

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

By inverting the if I could see the simple case and then move onto the more complex block knowing what the other one already did. not a huge change, but helped me in understanding.

Extract Method

I used this a lot.Take some complex multi line block, grok it and shove it aside in it's own method. this allowed me to more easily see where there was code duplication.

Now, hopefully, you haven't broken your code (test still passes right?), and you have more readable and better understood procedural code. Look it's already improved! But that test you wrote earlier isn't really good enough... it only tells you that you a duplicating the functionality (bugs and all) of the original code, and thats only the line you had coverage on as I'm sure you would find blocks of code that you can't figure out how to hit or just cannot ever hit (I've seen both in my work).

Now the big changes where all the big name patterns come into play is when you start looking at how you can refactor this in a proper OO fashion. There is more than one way to skin this cat, and it will involve multiple patterns. Not knowing details about the format of these files you're parsing I can only toss around some helpful suggestions that may or may not be the best solutions.

Refactoring to Patterns is a great book to assist in explainging patterns that are helpful in these situations.

You're trying to eat an elephant, and there's no other way to do it but one bite at a time. Good luck.

这篇关于需要重构Arrow Anti-Pattern的想法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆