设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

深度解析:清理烂代码

2013-7-2 12:35| 发布者: 红黑魂| 查看: 1418| 评论: 0|来自: 伯乐在线

摘要: 猜猜看怎么了!你正”继承“(接收)了一堆混乱的旧代码。恭喜你!现在都是你的了。混乱的代码可能来自任何地方。中间件,网络,可能来自你自己的公司。你知道在一个角落里有一个家伙,没有人过去管他在做什么。猜猜 ...

4. 不要同时清理代码和修正代码

这是(3)的结果,但是仍然很重要。

这是一个常见的问题。你开始察看一个模块,是因为你想加入某个新功能。然后你发现这个代码相当的糟糕,所以你开始重新组织它并且加入新的功能。

问题在于清理代码和修正错误是完全不同的目标。当你清理的势后,你想让代码看起来更好,而没有改变它的功能。当你修正错误时, 你想改变功能。如果你同时清理代码和改正错误,很难保证清理不会改变什么。

先清理代码,然后再在一个干净的基础上,加入新的功能。

 

5. 删除你没有使用的功能

清理的时间正比于代码的数量,复杂性和糟糕的程度。

如果代码的功能你目前没有使用,而且在可预见的将来也不会使用,那么就删除它,这会减少你浏览的代码数,降低复杂度(删除不必要的概念和依赖)。你会清理的更快的,而且最后的结果会更简单。

不要留着代码仅仅因为“谁知道呢,你可能某一天需要它”。代码是有代价的 – 它需要被移植,修正错误,被阅读以及被理解。你有更少的代码,就更好。就算在最不可能的情况下,你需要这个旧代码,你也能从代码库中找到它。

 

6. 删除大部分的注释

烂代码很少会有好的注释。它们通常是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Pointless:
 
    // Set x to 3
 
    x = 3;
 
// Incomprehensible:
 
    // Fix for CB (aug)
 
    pos += vector3(0, -0.007, 0);
 
// Sowing fear and doubt:
 
    // Really we shouldn't be doing this
 
    t = get_latest_time();
 
// Downright lying:
 
    // p cannot be NULL here
 
    p->set_speed(0.7);

看看整个代码。如果一个注释对你来说不再有意义,也对你理解代码没什么帮助,那么就删除它。否则你只会浪费你的脑力去理解一堆对你理解代码没帮助的注释。

同样的删除那些已经被注释掉的代码。如果你还需要它的时候,它还在你的代码仓库中。

甚至如果注释是正确而且有用的,记住你还可以重构你的代码。可能当你完成重构后,这些注释不再正确了。这个世界上还没有一个单元测试能够告诉你注释是否已经损坏了。

好代码需要很少的注释因为代码自己已经自说明了而且很容易理解。拥有好名字的变量不需要注释去解释它们的用途。函数如果有好的输入输出,没有特殊情况时是不需要说明的。简单的写得很好的算法在没有注释的情况下也是容易理解的。而断言记录了条件和预测。

大部分情况下,最好的做法是删除所有旧的注释,专注于让代码变得干净和具有可读性,然后再在需要的地方添加代码 – 这些注释反应新的API的用途以及你对代码的理解。

 

7. 避免共享的可更改的状态

共享的可更改的状态是理解代码的最大阻碍,因为它允许隔一段距离的行动,一段代码可以改变另一段完全不同的代码的行为。人们常说多线程是困难的。事实上,是由于线程共享了可更改的状态,才导致了问题。如果你能避免它们的话,多线程并不复杂。

如果你的目标是写高性能的软件,你应该不能避免一切可更改的状态,但是你的代码仍然可以从减少它而获益。为了“大部分功能完善”而努力吧,确保你确切的知道什么状态在什么地方改变了,并且知道原因。

共享的可更改的状态来自不同的地方:

● 全局变量。最经典的例子。现在每个人都知道全局变量的坏处。但是要注意(有时人们会忘记),全局变量是唯一的会造成问题的共享的可更改状态。全局常量并不糟糕,Sprintf也不糟糕。

● 对象 – 装有乐趣的大袋子。对象能够集合很多方法,无疑可以共享很多可变的状态(成员)。如果一个懒惰的程序员需要将一些信息在方法之间传递的话,她可以建立一个新成员,所以可以依照需要来读它和写它。这非常像全局变量。多么有意思!当一个对象有越来越多的成员时,问题就越来越严重。

● 巨大的函数。你可能已经听说它们了。这种神秘的产物栖息在最黑暗的代码洞穴的最底层。心眼坏的程序员在阴暗的酒吧里谈论它们,他们的理智被他们遇见的代码摧毁了:“我不停地向下翻向下翻,我不能相信自己的眼睛。居然有12,000行。”当函数足够长的时候,它们本地变量将和全局变量一样糟糕。我们不可能知道改变2000行之后的一个局部变量会有什么效果。

● 引用和指针参数。引用和指针参数没有被声明为const被传进函数时,可以在被调用者,调用者以及任何能被传递相同的指针的对象之间充当共享的可变的状态。

这里有一些避免共享的可更改的状态的建议:

  • 将较大的函数切分成较小的函数。
  • 将较大的对象切分成较小的变量,将相关的成员放在一起。
  • 将成员变成private。
  • 将函数声明const,返回结果,而不是可更改的状态。
  • 将函数声明static,从参数获得值,而不是从共享状态那里取值。
  • 避免完全使用对象,实现纯净的功能,不要引入副作用。
  • 将本地变量声明const。
  • 将指针和引用声明const。

 

8. 避免不必要的复杂性

不必要的复杂性通常是过度工程化的结果 – 支持的结构(如序列化,引用计数器,虚拟接口,抽象工厂,访问者等等)会拖慢真正有实际功能的代码。

有时候过工程化是因为一些项目开始的时候有一些更大的野心,多于实际完成的。更多的情况,我想是因为程序员读了关于设计模式的书之后和瀑布模型之后的想法,他认为过工程化会形成更“坚固”和“高质量”的产品。

通常,这个笨重的,僵化的,过度复杂的模型不能适应功能需求,而这是设计师不期望的。那些功能可能之后用hack的方式来实现,成了在象牙塔最顶上的螺栓和后门,变成了神经错乱的混合结构。

治愈过度工程化的方法就是YAGNI(you are not gonna need it)-你不需要它!只有当需要一个东西的时候才建造它。当你需要它的时候才建立更复杂的东西,而不是在你需要之前。

避免不必要的复杂性的一些实际的方法:

  • 移除你没有用到的东西(就像上面建议的一样)。
  • 简化必要的概念,避免不必要的概念。
  • 移除不必要的抽象,用实际的实现来替代。
  • 移除不必要的虚拟化,并且简化对象的结构。
  • 如果一个设置曾经使用过,那么就避免在用另外的配置来运行这个模块。

 

9. 就这么多了

现在开始清理你的“房间”吧!

原文链接: Niklas Frykholm    翻译: 伯乐在线 唐小娟
译文链接: http://blog.jobbole.com/28672/

酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部