我拒绝接受的几个最佳编程实践方法

import类,而不是import整个包

在很多语言里,这通常是一种被推荐的做法,有些甚至是必须的。如果是在C++里,这还算是有点意义,因为更少 #include 意味着更快的编译速度,然而,这种意义仅体现在需要花很长时间去编译的大型项目中。

而对很多像Java这样的语言,这毫无意义。因为它不影响编译的时间,所有你得到的回报只是花更多的努力来维护你的import语句。虽然IDE可以帮助你做这些事情,但你仍然需要时不时的多点几次鼠标/键盘,在版本控制系统里多留几条变更记录,干扰你的代码审查。有什么实际用处?向官僚机构表明代码很规范,无它用途。

面向接口编程

这项编程法则要求程序员定义接口,并针对接口来编程,而不是针对实现编程。理由非常简单:容易开发第二种实现,易于测试(真的吗?),更有效的使用代码。

问题就出在你不能凡事都按照这个原则。我个人认为,如果一个方法需要有多个实现,那使用接口是不二选择。但除此之外,如果你仍遵守的话,除了增加代码量,增添麻烦外,不会有任何好处。而且,把一个类重构成接口和它的实现并不困难,事实上是非常简单,所以,为什么一开始就要写接口呢,当需要时把它改造成接口也不晚。

禁用某种语言功能

在很多企业、组织使用的编码规范中,你会发现各种各样的类似于“不要使用goto语句”,“不要使用三元操作符”等规则。

如果一种语言的某种语法并未标志为“deprecated”,为什么不让人使用?当然,要正确的使用!即使像 goto 这样的语法同样可以让代码更可读、更易理解——只要你能以正确的方式、用在正确的地方。

使用Setters/getters,禁止public属性

这是最著名的Java风格,Java里任何公有属性都是不提倡的,任何属性都应该通过 setters 和 getters 操作,不允许有任何质疑。有些共用框架更加强化了这些。每次当我看到一个5年前的老类里只有一些私有属性和公有的无聊的 setters 和 getters ,我都会奇怪这是要干嘛?是为了增加代码量?是为了预防将来有可能出现意外的属性值修改?但是如果真的有人修改了,这又能起到什么预防效果?

单个返回语句

有人说多个返回语句会让代码变复杂。我发现却正好完全相反。当方法/函数在退出之前需要做一些收尾工作时,单一return语句会让函数更简单,但在其它很多情况下,这反而会让事情变得复杂,你需要添加额外的if-else来处理各种非正常退出情况。

尽量责任分离

我这里主要是针对“尽量”。有些人把这做到了极限,甚至有些变态。没错,把大的复杂的问题拆分成小的简单问题,这很好。但拆的太小就会引起新的问题。如果你把一棵树砍成牙签那么大小的块,你得到的就是一堆垃圾。

有些问题本身就是很复杂,你无法通过拆解来让它变简单。

为了让这篇文章有个比较积极的结尾,下面是我认为的放之四海皆准的最佳实践方法:

  • 做任何事情都要有个理由
  • 如果你做的未能符合预期,重做,替换方法或给予修正
  • 扔掉垃圾通常是你最应该做的事情——不论这垃圾造价多高
[英文原文:Programming best practices I disaprove ]
分享这篇文章:

26 Responses to 我拒绝接受的几个最佳编程实践方法

  1. zpxol says:

    物极必反,把握好度,任何东西都有两面性,不要用过头,做过头。

  2. 忧郁 says:

    求Setters/getters这样写的好处?

    • Galen says:

      就是在设置值的时候可以做一些限制,比如年龄不能为负数。不过我们开发时都是自动生成的方法,我也感觉不到有啥用处。

    • mywjch says:

      Why use getters and setters?(来自Stack Overflow)
      Here are the some of the reasons I am aware of:
      Encapsulation of behavior associated with getting or setting the property .
      Hiding the internal representation of the property while exposing a property using an alternative representation.
      Insulating your public interface from change .
      Controlling the lifetime and memory management (disposal) semantics of the property.
      Providing a debugging interception point for when a property changes at runtime.
      Improved interoperability with libraries that are designed to operate against property getter/setters.
      Allowing inheritors to change the semantics of how the property behaves and is exposed by overriding the getter/setter methods.
      Allowing the getter/setter to be passed around as lambda expressions rather than values.
      Getters and setters can allow different access levels.

    • TigerWang says:

      这是一种对属性设置和读取的规范,前提是有必要的话,当要读取一个对象的属性的时候,很自然而然的想到get,当设置一个对象的属性的时候,很自然的想到用set。
      而且正是因为有这个规范,才是的很多开源框架得以实施,比如spring
      当然如果非框架,而且类本身只是一种结构体,无任何其他逻辑时,完全可以使用public或者default,视实际情况而定

    • fanslate says:

      方法能被代理,而属性不能

  3. 熊叉 says:

    恩,可以理解。就跟看书一样不能读死书。

  4. lewis says:

    1000个人有1000种看法,这个还是随主流的好,毕竟我们的绝大部分项目都是在团队中完成的

  5. 敏敏Alexia says:

    不管什么样的编码规范都不是死的,要学会灵活运用,作者的意思是在有些情况下可以面向简洁编程,哈哈

  6. mycodewind says:

    做什么都要把握适度原则

  7. hi says:

    “即使像 goto 这样的语法同样可以让代码更可读、更易理解——只要你能以正确的方式、用在正确的地方。”
    谁来确保正确使用了?即使×××,只要正确×××,也无所谓,是最倒胃口的句式,这种把正确作为条件的推理,不是思考模式的硬伤?
    我感觉最近几期翻译的都不是些有价值的文章。

  8. 曼曼_慢慢来 says:

    说真的,真的不太懂为什么非得用getters和setters方法。。

  9. Ben says:

    老实讲,这篇文章在放屁。

  10. Thomas says:

    很少看到有一篇文章有这么多另类观点的,一个个来说:
    1. import类,而不是import整个包。
    在JAVA里如果不这样做,代码可能不能兼容后续的JDK版本,在《软件框架设计的艺术》里有个例子:
    import java.awt.*;
    import java.util.*;
    /** Could compiled on jdk1.2 before java.util.List was created*/
    public class VList extends List{
    }
    2. 面向接口编程
    如果程序员非常确信一个类不可能有多个实现,当然不必再抽取一个接口出来,但是如果你真的做过项目,你就会知道实际上没有人能确定这个,等到发现有需求的时候再改,并没有作者说的那么简单。再有,接口也比较容易测试和模拟,除非你完全不写测试,否则多点接口总是有好处的。
    3. 禁用某种语言功能
    无语了,人家都说“deprecated”了你非要用?自残啊,找虐啊。你停止线程每次都用“stop()”啊?
    4. 使用Setters/getters,禁止public属性
    这个其实我有点赞同作者,Java的Setters/getters确实太臃肿了,不好看。但是除非你用其他的语言比如Objective-C,可以声明@property这样的变量,编译器帮你实现了Setters/getters,而且当你觉得有需要的时候可以重写自己的Setters/getters方法,否则,大量的公有变量会是灾难性的,很难跟踪状态的改变,出了错你断点都没处打。
    5. 单个返回语句
    唯一一个我认同的观点,单个返回语句这个编程方式太老了,不应该继续遵循。其实我们经常打破这个限制,比如简单工厂模式。
    public class FruitGardener{
    public static Fruit factory(String which)throws Exception{
    if(which.equalsIgnoreCase(“apple”)){
    return new Apple();
    }else if(which.equalsIgnoreCase(“strawberry”)){
    return new Strawberry();
    }else if (which.equalsIgnoreCase(“grape”)){
    return new Grape();
    }else{
    throw new Exception(“Bad fruit request”);
    }
    }
    }
    6. 尽量责任分离
    这个没有绝对的对错,任何好的事情你做的太过了都会物极必反,比如有人用了23个设计模式实现了一个Hello World,那是抽风。但是责任分离大多数时候都是好的,比如WEB系统的3层或4层架构,MVC模式,这都是责任分离的正面例子。

  11. 张井良 says:

    扔掉垃圾通常是最应该做的事情, 不管这些垃圾价值几何!!这句话讲的不错

  12. Techni says:

    在合作之下,规范是必不可少的。

  13. 海绵没了宝宝 对这篇文章的反应是赞一个
  14. 海绵没了宝宝 says:

    面向接口编程,感觉、感觉、感觉,我发现了好多web项目,就一个一个service接口,一个service接口实现,一个DAO,一个DAO实现,然后,木有然后,真心感觉没什么用啊,小系统,也没感觉有扩展的可能,就是一堆重复的方法而已

  15. awoke  这篇文章, 并对这篇文章的反应是垃圾

发表评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据