`
ningboxiao
  • 浏览: 30682 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

阅读更多
import类,而不是import整个包

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

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

面向接口编程

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

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

禁用某种语言功能

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

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

使用Setters/getters,禁止public属性

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

单个返回语句

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

尽量责任分离

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

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

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

 

  • 做任何事情都要有个理由
  • 如果你做的未能符合预期,重做,替换方法或给予修正
  • 扔掉垃圾通常是你最应该做的事情——不论这垃圾造价多高

本文转载自http://www.aqee.net/programming-best-practices-i-disaprove/

12
21
分享到:
评论
26 楼 kidneyball 2013-12-31  
1) import类,而不是import整个包
文章作者(估计不是博主)可能没遇过因为种种历史原因同一个包名被分散在多个jar包中的情况。明确import类有助于在阅读代码时理清依赖关系。

2)面向接口编程
程序不仅仅是要一次运行,还要给别人看和用(二次开发)的。接口除了功能上可以轻易改变实现外,还可以告诉后续开发的程序员:这里是设计来给你改实现的。而不实现接口的类,则暗示这是一个内部实现,如果你改实现的话原作者在更新时不保证能向前兼容。

3)禁用某种语言功能
通用语言是设计来解决"所有“问题的,必然对各种边界场景有完善的应对措施,但某些边界条件不是企业业务的常态而且有明显副作用,一个企业针对自身情况从政策上禁用某些有明显副作用的语言特性,很正常。

4)使用Setters/getters,禁止public属性
这个作者可能不知道有动态代理这回事。

5)单个返回语句
这一点本来没有问题,在一个职责单一的方法里,先对一些简单边界情况进行处理返回,然后再处理正常主线逻辑,是很常见的做法(Java类库里这样的做法就有不少)。但这个作者同时又反对”尽量责任分离”则有很大问题,一个长方法里有多处返回点,会让阅读者不知道这个方法在干什么。而且如果你在排错时如果想跟踪这个方法每次被调用的返回值,则需要打多处断点。

6)尽量责任分离
比喻错误,如果你把一颗树砍成牙签那么大小的块,但这些牙签大小的块仍然有序地结合为树木的形状并且保持稳定(编程里你把方法按职责拆分后,仍然会有高层的方法把这些小方法有序组织起来),那就不是垃圾,而是卖得很贵的乐高积木

7) 放之四海皆准的最佳实践方法
做任何事情都要有个理由 ———— 反对任何事也应有个理由
如果你做的未能符合预期,重做,替换方法或给予修正  ———— 作者所反对的那些事情,恰恰是在保证程序能方便地“重做,替换或给予修正”
扔掉垃圾通常是你最应该做的事情——不论这垃圾造价多高  ————— 首先你得搞清楚为何这堆造价这么高的东西会被认为是垃圾。
25 楼 alvin198761 2013-12-31  
sswh 写道
引用
面向接口编程


接口体现的是业务模型中的“概念”,接口给了软件结构一个清晰的描述。

多人协作时,依赖其他(人/其他模块)提供的接口,是非常重要的。

如果连接口都无法清晰的划定,说明软件结构的职责、概念没有理清楚,

依赖于实现的代码,一般软件结构上都是混乱的。




楼主一个人能开发出一个魔兽,或者微软的一个操作系统,所以面向接口对他来说不是什么高级货,还会影响进度。。
24 楼 sswh 2013-12-31  
引用
面向接口编程


接口体现的是业务模型中的“概念”,接口给了软件结构一个清晰的描述。

多人协作时,依赖其他(人/其他模块)提供的接口,是非常重要的。

如果连接口都无法清晰的划定,说明软件结构的职责、概念没有理清楚,

依赖于实现的代码,一般软件结构上都是混乱的。



23 楼 sswh 2013-12-31  
引用
import类,而不是import整个包


这个好处体现在代码阅读时。

可以给阅读者一个总体的概览,粗粗浏览一下当前类依赖的外部类,结合当前类名、包结构,可以快速猜测当前类的实现目标、实现方式。

增强了代码的可读性。
22 楼 freezingsky 2013-12-30  
有些东西叫守则也叫规范,但如果不分情景的死守,就变成了墨守成规。
21 楼 Alex丿 2013-12-30  
同感~。。。
20 楼 white_crucifix 2013-12-30  
这个博主一贯就是发点翻译文或者鸡汤的

另外最近首页突然出现好几篇鸡汤……
19 楼 nakupanda 2013-12-30  
大家别中计, 查看一下左栏<评论排行榜>那里的几篇文章, 注看以下几点:

1, 楼主除了发了个主贴就从来没出现过了

2, 文章涵盖太广泛, 观点也不尽相似.

结论: 这个楼主只是随随便便上网找了些文章发出来, 甚至<转载>这样的标签也懒得加上.

18 楼 无双Rama 2013-12-30  
就这满文槽点的文章也能上首页?
哎 , iteye论坛真是要完了!
17 楼 white_crucifix 2013-12-30  
windshome 写道
说到楼主回复我的第二个观点,其实我觉得有趣的是楼主90%这个数字怎么来的,呵呵。


哈哈,我不是楼主

你的信息隐藏我觉得说得对,当然这种由业务控制,由程序员控制的事情是不是一定得靠getset代码来限制就说不清了,所以还是我说的不可证实,不可证伪。合理也是合理,不写也可以不写,哈哈。

关于第二点看来对后面的实质内容提不出什么异议,就算是也认可了吧,哈哈。至于这90%不知道我说估算出来的算不算 ,或者作为一个开放性命题,看到的大伙都来说说自己实践中都有怎样的多实现?反正这种接口的优势我只在做java server开发的经历中体会到过,web的确没体会过。
16 楼 windshome 2013-12-30  
说到楼主回复我的第二个观点,其实我觉得有趣的是楼主90%这个数字怎么来的,呵呵。
15 楼 windshome 2013-12-30  
其实我倒是感觉楼主是个用心思考的人。

get/set的用处还真不好去体现,但是做的久了就会发现。这是软件工程学的“信息隐藏”,成员变量里的一个属性,未必就等于get接口的返回值。

例如

Person类,有个属性是出生年月日,可以set,但是可能没有get这个属性的接口,只有get年龄的接口。

至于你说不应当成为障碍,这个很赞成。什么时候需要用这个,什么时候不需要,得用心思考的。
14 楼 white_crucifix 2013-12-30  
引用

set/get并非只是规范,而是有益才被广泛使用,写代码和做设计久了就会明白得;
90%不需要第二实现?这个90%是从哪里来的?接口的用处到底是什么?还是请深入理解面向对象编程的内涵;
增删改查怎么会是世界的全部呢?只是数据的存取嘛!



第一点我想说,同意“存在即合理”,但这只有指导意义,但不应该成为大家思维的阻碍。
第二点,接口的用处我已经用例子说明了,请看完嘛,不要只看一半就气冲冲回我让我“深入理解面向对象编程”……
13 楼 alvin198761 2013-12-30  
alvin198761 写道
楼主应该是搞 12306网站开发的吧,我相信有你这样的人才,中国将来一定不会强大

就冲你第一点,我就不想往下看了,你先回去看看书,然后说话吧,楼主
12 楼 alvin198761 2013-12-30  
楼主应该是搞 12306网站开发的吧,我相信有你这样的人才,中国将来一定不会强大
11 楼 icefishc 2013-12-30  
white_crucifix 写道
多年的编程经历下来感觉是:如今get set更多的是变成一种编程规范,而非真正意义上的有益。get set的好处就像是一个中医,不可证明也不可证伪,说优点吧就是为了避免手误的改值,说缺点吧,真心觉得get set无法阻止一颗想改值的心。get set更多的作用我觉得就是让大家养成像开门转钥匙一样的习惯,使得不用思考就能知道这里代码的作用,意义,和用法。当然做到这一点也是很赞的。

另外关于接口,我依然觉得文中说的有道理。事实上在当今世界上web开发中,90%的场景都是不需要第二实现的。
为什么这么说,原因就在于在web开发中,增删改查对于每一个实体几乎都是独立的,而对于每一个实体我们更愿意做的是分模块,对于相似的实体即便不分模块,也能通过代码和sql的改装做到复用,而不需要第二实现。
那么为什么j2ee会发展出这样的形式,那是因为在需求更多的系统中,除了sql相关的功能,会涉及到很多“server”相关的功能,涉及到file,io,socket,甚至操作系统操作。这部分其实是java server端软件开发的核心,比如我做一个nosql,涉及到存储模块,既需要文件存储,又需要内存存储,又需要可配置的其他存储,这时候接口实现继承等相关概念自然就出来了。而且做到外部可配置的存储,必然需要给用户提供一个interface。另外数据在网络中传输需要的序列化方式,数据的加密方式,这些都是可以做成接口,让用户自行扩展的。
但是这一切,在web中的使用场景非常的少。毕竟web系统是真实世界模型在网络上的投影,而增删改查几乎就是世界的全部。

90%都会有第二种实现的。 其中一个是mock
10 楼 windshome 2013-12-30  
white_crucifix 写道
多年的编程经历下来感觉是:如今get set更多的是变成一种编程规范,而非真正意义上的有益。get set的好处就像是一个中医,不可证明也不可证伪,说优点吧就是为了避免手误的改值,说缺点吧,真心觉得get set无法阻止一颗想改值的心。get set更多的作用我觉得就是让大家养成像开门转钥匙一样的习惯,使得不用思考就能知道这里代码的作用,意义,和用法。当然做到这一点也是很赞的。

另外关于接口,我依然觉得文中说的有道理。事实上在当今世界上web开发中,90%的场景都是不需要第二实现的。
为什么这么说,原因就在于在web开发中,增删改查对于每一个实体几乎都是独立的,而对于每一个实体我们更愿意做的是分模块,对于相似的实体即便不分模块,也能通过代码和sql的改装做到复用,而不需要第二实现。
那么为什么j2ee会发展出这样的形式,那是因为在需求更多的系统中,除了sql相关的功能,会涉及到很多“server”相关的功能,涉及到file,io,socket,甚至操作系统操作。这部分其实是java server端软件开发的核心,比如我做一个nosql,涉及到存储模块,既需要文件存储,又需要内存存储,又需要可配置的其他存储,这时候接口实现继承等相关概念自然就出来了。而且做到外部可配置的存储,必然需要给用户提供一个interface。另外数据在网络中传输需要的序列化方式,数据的加密方式,这些都是可以做成接口,让用户自行扩展的。
但是这一切,在web中的使用场景非常的少。毕竟web系统是真实世界模型在网络上的投影,而增删改查几乎就是世界的全部。

white_crucifix 写道
多年的编程经历下来感觉是:如今get set更多的是变成一种编程规范,而非真正意义上的有益。get set的好处就像是一个中医,不可证明也不可证伪,说优点吧就是为了避免手误的改值,说缺点吧,真心觉得get set无法阻止一颗想改值的心。get set更多的作用我觉得就是让大家养成像开门转钥匙一样的习惯,使得不用思考就能知道这里代码的作用,意义,和用法。当然做到这一点也是很赞的。

另外关于接口,我依然觉得文中说的有道理。事实上在当今世界上web开发中,90%的场景都是不需要第二实现的。
为什么这么说,原因就在于在web开发中,增删改查对于每一个实体几乎都是独立的,而对于每一个实体我们更愿意做的是分模块,对于相似的实体即便不分模块,也能通过代码和sql的改装做到复用,而不需要第二实现。
那么为什么j2ee会发展出这样的形式,那是因为在需求更多的系统中,除了sql相关的功能,会涉及到很多“server”相关的功能,涉及到file,io,socket,甚至操作系统操作。这部分其实是java server端软件开发的核心,比如我做一个nosql,涉及到存储模块,既需要文件存储,又需要内存存储,又需要可配置的其他存储,这时候接口实现继承等相关概念自然就出来了。而且做到外部可配置的存储,必然需要给用户提供一个interface。另外数据在网络中传输需要的序列化方式,数据的加密方式,这些都是可以做成接口,让用户自行扩展的。
但是这一切,在web中的使用场景非常的少。毕竟web系统是真实世界模型在网络上的投影,而增删改查几乎就是世界的全部。




set/get并非只是规范,而是有益才被广泛使用,写代码和做设计久了就会明白得;
90%不需要第二实现?这个90%是从哪里来的?接口的用处到底是什么?还是请深入理解面向对象编程的内涵;
增删改查怎么会是世界的全部呢?只是数据的存取嘛!


9 楼 一个java程序员 2013-12-30  
首先,必须尊重楼主,有自己的见解,不被老旧的规则套住。这种精神值得学习。

但是,毕竟是前辈们总结出来的经验, 如果要反驳掉,必须拿出自己的最佳方式出来。这样才有效力,让别人闭嘴。

如果一味的反驳别人的劳动成果,估计就是招来一群人喷的。

大多数都是规定。 就跟暗号一样。不遵守这个规定,就不行的。

8 楼 wangjian5748 2013-12-30  
关于setters与getters是LZ还没理解java,反射机制有些需要方法的,而不是字段。
7 楼 white_crucifix 2013-12-30  
多年的编程经历下来感觉是:如今get set更多的是变成一种编程规范,而非真正意义上的有益。get set的好处就像是一个中医,不可证明也不可证伪,说优点吧就是为了避免手误的改值,说缺点吧,真心觉得get set无法阻止一颗想改值的心。get set更多的作用我觉得就是让大家养成像开门转钥匙一样的习惯,使得不用思考就能知道这里代码的作用,意义,和用法。当然做到这一点也是很赞的。

另外关于接口,我依然觉得文中说的有道理。事实上在当今世界上web开发中,90%的场景都是不需要第二实现的。
为什么这么说,原因就在于在web开发中,增删改查对于每一个实体几乎都是独立的,而对于每一个实体我们更愿意做的是分模块,对于相似的实体即便不分模块,也能通过代码和sql的改装做到复用,而不需要第二实现。
那么为什么j2ee会发展出这样的形式,那是因为在需求更多的系统中,除了sql相关的功能,会涉及到很多“server”相关的功能,涉及到file,io,socket,甚至操作系统操作。这部分其实是java server端软件开发的核心,比如我做一个nosql,涉及到存储模块,既需要文件存储,又需要内存存储,又需要可配置的其他存储,这时候接口实现继承等相关概念自然就出来了。而且做到外部可配置的存储,必然需要给用户提供一个interface。另外数据在网络中传输需要的序列化方式,数据的加密方式,这些都是可以做成接口,让用户自行扩展的。
但是这一切,在web中的使用场景非常的少。毕竟web系统是真实世界模型在网络上的投影,而增删改查几乎就是世界的全部。

相关推荐

    多维随机数的生成方法

    ### 多维随机数的生成方法 #### 一、一维随机数生成方法 ##### 1.1 常见随机数的生成 在实际应用中,常常...不同的应用场景可能需要选择不同的方法来达到最佳效果。在实践中,应根据具体需求灵活选择合适的方法。

    模拟退火方法解决路径寻优问题及代码的注解_模拟退火代码_算法;路径_路径寻优_

    模拟退火算法的核心步骤包括以下几个部分: 1. 初始化:设置初始温度(通常较高)和初始状态(如随机路径)。 2. 计算当前状态的能量(代价),例如路径的总距离。 3. 生成一个新的状态(邻居解),例如通过交换...

    Windows Sockets 规范及应用 Windows网络编程接口

    9. **网络安全和最佳实践**:讨论网络编程中应考虑的安全问题,如数据加密、身份验证、防止拒绝服务攻击等,并给出相应的安全编码建议。 通过学习这本书,读者将能够掌握Windows环境下使用Winsock进行网络编程的...

    javascript-promise-book.pdf

    在JavaScript中使用Promise,有以下几个关键点: 1. Promise构造函数接受一个函数作为参数,这个函数也接受两个参数:resolve和reject,分别用于将Promise状态改变为fulfilled或rejected。 2. Promise.all方法可以...

    mfc编程 注册表安全设计

    在MFC中处理注册表,我们通常会用到几个关键类,如`CRegKey`。`CRegKey`类提供了对注册表进行读写、创建、删除键值等操作的方法。下面将详细介绍如何使用MFC进行注册表安全设计: 1. **打开注册表键**:首先,我们...

    软件工程中的网络编程与通信.pptx

    **软件生命周期**通常包括以下几个阶段: 1. **需求分析**:此阶段主要任务是收集和理解用户的需求,并明确软件的功能和性能要求。 2. **设计**: - **架构设计**:定义软件的整体结构和组成部分。 - **详细设计*...

    【并发编程】如何优雅使用线程池.pdf

    - **官方文档**:各种编程语言的官方文档通常包含有关并发编程的指南和最佳实践。 - **社区和论坛**:Stack Overflow、Reddit等,可以提供实际问题的帮助和讨论。 ### 线程池的优雅使用 #### 线程池引入 线程池是...

    模拟退火法 matlab程序

    在MATLAB源程序`anneal.txt`中,我们可以预期看到以下几个关键部分: 1. **初始化**:首先,程序会定义初始解,这通常是一个随机的解决方案。此外,还会设置初始温度(T)、最终温度(T_min)和冷却因子(α),...

    基于matlab的模拟退火算法及禁忌搜索算法源程序

    **MATLAB编程实践** 在MATLAB中实现这两种算法,主要涉及以下几个方面: - **矩阵运算**:MATLAB是矩阵运算的利器,适合处理大量数据的计算。 - **函数定义**:定义适应度函数、接受概率函数、禁忌判断函数等。 - ...

    DOTNET安全编程

    在.NET安全编程中,我们主要关注以下几个关键知识点: 1. **代码访问安全(CAS)** 代码访问安全是.NET框架的核心安全机制之一,它允许系统根据代码的来源、数字签名和其它属性来确定代码的权限。CAS可以防止恶意...

    刷题多久能面程序员-emacs-lisp-style-guide:社区驱动的EmacsLisp风格指南

    该指南分为相关规则的几个部分。 我试图添加规则背后的基本原理(如果省略,我认为这很明显)。 我不是凭空想出所有规则的; 它们主要基于我作为专业软件工程师的广泛职业生涯、来自 Emacs Lisp 社区成员的反馈和...

    AngularJS中的promise用法分析

    在编程实践中,我们可以创建一个deferred对象,然后通过.then()方法来处理异步操作的不同结果。在给定的代码片段中,$scope.send()函数内部首先创建了一个deferred对象,然后通过promise对象的链式调用来处理promise...

    BaseActivity+动态权限

    动态权限申请的基本流程包括以下几个步骤: 1. **检查当前权限状态**:首先,你需要在需要使用权限的地方检查用户是否已经授予了该权限。这可以通过`ContextCompat.checkSelfPermission()`方法完成,传入上下文和...

    信息安全技术:CSRF的防御编程.pptx

    【信息安全技术:防御CSRF攻击】\n\nCSRF(Cross-Site Request Forgery,跨站...同时,开发人员也应遵循最佳实践,如限制GET请求的敏感操作,使用HTTPS加密通信,以及保持软件和框架的更新,以应对不断演化的攻击手段。

    struts文件上传下载

    在Struts中实现文件上传,主要涉及以下几个步骤: 1. **配置Action类**:首先,你需要创建一个处理文件上传的Action类。这个类通常会继承自`org.apache.struts2.dispatcher.multipart.MultiPartRequest`或使用...

    OPC_Program.rar

    OPC分为OPC DA(Data Access)、OPC HDA(Historical Data Access)、OPC AE(Alarms and Events)等几个主要部分,分别用于实时数据访问、历史数据访问和报警事件处理。C#中的OPC编程通常涉及与OPC服务器的交互,...

    C#医院挂号系统源码.zip

    用户端的实现可能包括以下几个模块: 1. 用户登录注册:使用C#的ASP.NET框架,结合数据库进行用户身份验证和信息存储。 2. 预约挂号:涉及到数据库查询、事务处理和时间冲突检查,确保预约的公平性和准确性。 3. ...

    C++程序设计之“四书五经”

    除此之外,C++的“四书五经”还包括更多其他经典著作,如《Effective C++》、《More Effective C++》、《Exceptional C++》等,它们从不同的角度提供实用的编程技巧和最佳实践,帮助程序员写出高效、可靠的代码。...

    JAVA线程池原理以及几种线程池类型介绍

    - **拒绝策略**:当线程池已满且无法接受新任务时的处理策略。 #### 八、结论 综上所述,线程池是Java并发编程中的一个重要概念,它可以帮助开发者更高效地管理线程资源,提高应用程序的性能。理解线程池的工作...

Global site tag (gtag.js) - Google Analytics