不要轻易重头再来,可能的话,尽量优化而非重构——读《 Things You Should Never Do, Part I》后感...

原文地址:http://joelonsoftware.com/articles/fog0000000069.html
[感想]
工程师总是喜欢另起一套东西,一套自己熟悉的东西。对于过往的代码,往往会因为可读性差而决定放弃使用他们,更宁愿重头再来重写一份代码。
其实很能理解。代码在长久的维护过程中,慢慢腐坏变得越来越丑陋是司空见惯的事,对于这样的代码,团队的老成员都会头皮发麻,团队新手进来就更难以溶入了。非常多的工程师在代码维护成本高达至不堪忍受时,都会想要放弃原代码从头再来。
还真是。我在接手站长天下代码,要将其改成淘宝外店时,也是觉得“非重构不可,我宁可从头再来”。接手web聊天室时,我、纯华、葛岩都非常想要重构,想要一份自己能够“掌控”的代码,而不是基于别人的代码进行维护。
代码为什么会变得越来越丑陋呢?前期构思不充分固然是可能的原因之一,但更大的可能性是因为有太多意料外的需求和bug。这不是前期构思不充分的错,前期不可能预测至所有的问题,只要主体架构搭得合理,前期的构思就算是成功的,小的细节问题是一定会存在的。这些细节问题只能在开发过程中发现,别无他法。每发现一个这种问题,就必须打一次补丁,补丁多了,代码就变得可读性越来越差。一直到那个无法再忍受的临界值达到为止,代码会越来越腐坏。然后终于要开始重构了,重头再来。
就像Joel Spolsky说的,重构的成本是非常大的。如果重构的团队还是之前那支团队,那还相对较好,如果团队是支新的团队,那效果未必好。你无法保证你的代码不会犯过去团队相同的错误,你在选择重构时,
丢弃了过往的累赘,但也丢弃了过往的经验。尽管过去的代码十分丑陋,但他们确确实实可以正常地在运转。如果要重构,你能保证你的代码不会像过去团队的代码一样,慢慢变丑陋吗?你面临同样的风险,而且,过去团队已经付出的时间成本,你还要再次付出一遍。
没有人愿意写出难看的代码,你们团队的实力也不一定会比过去团队更高明。在项目初期,大家的愿望一定都是好的,代码的组织结构也一定是满意的。在长期的维护过程中,意料外的事件是不可避免的。重要的不是重构,重要的是如何防止代码腐坏!这是最治本的,永远别说“稍后再来修改它”,因为“稍后”等于“永远”,代码就是在一次次这样的“稍后”中腐坏的。马丁说得对,永远要保证“签出”的代码比“签入”时更干净、更整洁。永远保证你的代码是高品质的输入,不要留任何坏的东西在代码库里,它会像破窗户原理一样,让你的代码越来越破,永远别打破那第一扇窗户。
如果代码已经很乱了,怎么办?重写吗?如果你的团队还是之前那支团队,你们已经有第一版的“经验”在了,我觉得是可以去重构的,这个风险在可控范围。但如果之前版本并非由你们来做,那么不要去重构,而是去读他们的代码,再难读也要去读,然后再去优化他们,而非重构。
也就是说,如果项目要交接给其他团队,不要寄希望于日后的新团队的重构,那成本实在太大。应该在交接的时候,交接清楚,我知道如果开发周期长,这个交接的过程并不容易,但即使如此,这个成本也是最小的,交接的过程不妨给长一些,保证质量。

posted on 2011-02-25 02:27  SunBo 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/sunyubo/archive/2011/02/25/2282071.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Java 中,可以使用 java.io.BufferedReader 类来取文件。该类提供了一个方法叫做 reset(),该方法可以将 BufferedReader 对象的指针重新指向文件的开头,从而实现重头取文件的目的。 以下是一个示例代码: ``` try { BufferedReader br = new BufferedReader(new FileReader("file.txt")); String line; while ((line = br.readLine()) != null) { // 处理文件内容 } br.reset(); // 将指针重新指向文件开头 while ((line = br.readLine()) != null) { // 重头处理文件内容 } br.close(); } catch (IOException e) { e.printStackTrace(); } ``` 在上述代码中,首先使用 BufferedReader 类取文件的内容,然后使用 reset() 方法将指针重新指向文件开头,最后再次取文件的内容。请注意,reset() 方法只能在 mark() 方法之后才能调用,因此在使用 reset() 方法之前需要先调用 mark() 方法来设置标记位置。 以下是一个使用 mark() 方法和 reset() 方法的示例代码: ``` try { BufferedReader br = new BufferedReader(new FileReader("file.txt")); String line; br.mark(0); // 设置标记位置为文件开头 while ((line = br.readLine()) != null) { // 处理文件内容 } br.reset(); // 将指针重新指向标记位置(即文件开头) while ((line = br.readLine()) != null) { // 重头处理文件内容 } br.close(); } catch (IOException e) { e.printStackTrace(); } ``` 在上述代码中,首先使用 mark() 方法设置标记位置为文件开头,然后使用 reset() 方法将指针重新指向标记位置,最后再次取文件的内容。请注意,在 mark() 方法中传入的参数表示标记位置的最大字符数,如果文件的大小超过了该值,则标记位置将失效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值