某些时候,重构是有危害的

某些时候,重构是有危害的

重构涵盖了一系列使代码更整洁、更可靠、更易维护的技术。但是,有时候这些特性q却不可兼得。而通常困扰我们的特性就是性能问题。例如,让我们来思考把循环不变因子boolean值从块内提取出来的问题:

for(....) { 

    ... 

    if(b) A; 

    else B; 

    .... 

}

当b是一个循环不变量时,这段代码可以改成:

if(b) 

    for(...) { 

        ... 

        A; 

        ... 

    } 

else 

    for(...) { 

        ... 

        B; 

        ... 

    }

如果代码中有大量的循环不变因子,那么它可能会变得更加快。然而,它也可能会变慢。特定的基准是需要的:-)

无疑,它变得更加地不可维护并且更加地不清晰。当你看到一段经过如此变换后的代码时,我们很难去发现这两个循环是有关系的。如果任何一个循环块内出现一个bug,那么两个循环都必须修正它。测试变得更加的复杂,因为重复的代码必须被独自单独地测试(有点冗余)。如果代码中有多个循环不变量,那么代码量将会以指数级增长,这使得问题变得更加严重。(代码量增长的速度)将会变得相当疯狂相当迅速。我已经看到过一些事例,这些事例里面大伙试着通过灵活运用C中的宏来清晰地认识这些变换。但实际上,这会让代码变得更加凌乱。并且代码的爆炸性增长是引人注目的:几年前我刚接触这类问题时,有人阻止了一个新的“划线法程序”加入到SunOS内核(在SVr4,System V Release 4,合并之前Solaris的称呼,即Solaris的前身),它比内核的所有其余部分加起来还要大。但是,它速度快。我获得了修改它的任务:-( 

对大多数人而言,这类变换应该像瘟疫一样来避免。但是对于像我这样常常需要去做大量调整代码工作的人来说,这类变换是有必要的。他们能够被写的更加简洁吗?遗憾的是,重构被视为纯粹是IDE干的事。有时候,如果重构以语言的方式表达出来,你可能在做cool的事情。但这是另一篇博客所要说的了。

原文参见高司令的个人网站http://nighthacks.com/roller/jag/entry/refactoring_considered_harmful_sometimes

Refactoring considered harmful, sometimes

    Refactoring covers a broad swath of techniques to make code cleaner, more reliable, more maintainable, ... But sometimes, these attributes fight against each other. The usual attribute that causes trouble is "more performance". For example, consider factoring out a loop-invarient boolean:
for(....) {
    ...
    if(b) A;
    else B;
    ....
}
when b is loop-invarient, this can become:
if(b)
    for(...) {
        ...
        A;
        ...
    }
else
    for(...) {
        ...
        B;
        ...
    }
    Depending on a wide variety of factors, this can be faster. Although it might be slower. Careful benchmarking is required :-)
    It is certainly less maintainable and less clear. When you see a pice of code that is the result of such a transformation, it's often difficult to tell that the two loops are related. If a bug is found in any of the replicated pieces of code, it has to be fixed in *both* places. Testing gets more complicated because the replicated code paths have to be independently (and somewhat redundantly) tested. To compound the problem, if you have (for example) multiple loop-invarient booleans, the code expansion is exponential (!!) in the number of factored-out booleans. This can get pretty insane pretty fast. I've seen instances where folks have tried to be clean about these transformations by clever use of C macros, but this can get really messy. And the code explosion can be dramatic: I got pulled into this problem years ago when someone checked a new line-drawing routine into the SunOS kernel (that's what Solaris was called before the SVr4 merge) that was bigger than the whole rest of the kernel. But it was fast. I got the job of fixing it :-(
    For most people, this class of transformations should be avoided like the plague they are. But for folks like me who all too often need to do intense tuning, they are necessary. Can they be made cleaner? It's a pity that refactoring is viewed purely as something done in an IDE. Sometimes, you can do cool things if the refactoring is expressed in the language. But that's another blog entry.

评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值