再读编程的智慧一文有感

2018-05-04  本文已影响32人  sugaryaruan

记得是2015年还是2016年读过王垠的这篇文章--编程的智慧,收益良多。一些当时让我影响深刻的点,自那以后就一直用于生产了。

今天重温此文,感触最深的有以下三个点:

  1. 循环时避免使用continue和break,并提供了如何去掉的方法
  2. 如何正确的处理Java里的异常和错误
  3. 如何正确的处理Java里的空指针

本文是编程的智慧一文的内容概要。当然最好的方式,是花上2到3小时认真阅读王垠的原文,相信你会有很多感触和收获。

正文内容

推敲代码

反复推敲代码,仔细领悟,积累灵感和智慧,为了在遇到新问题的时候直接朝正确,或者接近正确的方向前进。

优雅代码的形状特征

看起来像整整齐齐,套在一起的盒子。抽屉里分门别类,再放几个小盒子。

逻辑上是枝丫分明的树状结构。程序所做的几乎一切事情,都是信息的传递和分支。

模块化代码

模块化不是简单的把代码切割开来,分放在不同的位置。指的是逻辑上模块化。

需要做到以下几点:

  1. 一个函数不超过40行
  2. 制造小的工具函数。函数内联,内联扩展是用来消除函数调用时的时间开销。它通常用于频繁执行的函数,对于小内存空间的函数非常受益
  3. 每个函数只做一件简单的事
  4. 避免使用全局变量和类成员来传递信息

可读的代码

使用有意义的函数和变量

局部变量应该尽量接近使用它的地方,加强读者对于这里的“计算顺序”的理解,局部变量的本质——它们就是电路里的导线。

局部变量名字应该简短

不要重用局部变量,否则会把局部变量的作用域不必要的增大。

把复杂逻辑提取出来,做成帮助函数

把复杂的表达式提取出来,做成中间变量

合理的地方换行

简单的代码

程序语言都喜欢标新立异,提供这样那样的“特性”,然而有些特性其实并不是什么好东西。很多特性都经不起时间的考验,最后带来的麻烦,比解决的问题还多。很多人盲目的追求“短小”和“精悍”,或者为了显示自己头脑聪明,学得快,所以喜欢利用语言里的一些特殊构造,写出过于“聪明”,难以理解的代码。

并不是语言提供什么,你就一定要把它用上的。实际上你只需要其中很小的一部分功能,就能写出优秀的代码。

避免使用自增减表达式(i++,++i,i–,–i)用在复杂的表达式里面

永远不要省略花括号

合理使用括号,不要盲目依赖操作符优先级,能降低视觉疲劳。

避免使用continue和break。这点更新了我的认知。它们依靠“控制流”来描述“不做什么”,“跳过什么”,结果到最后你也没搞清楚它到底“要做什么”。

  1. 如果出现了continue,你往往只需要把continue的条件反向,就可以消除continue。
  2. 如果出现了break,你往往可以把break的条件,合并到循环头部的终止条件里,从而去掉break。
  3. 有时候你可以把break替换成return,从而去掉break。
  4. 如果以上都失败了,你也许可以把循环里面复杂的部分提取出来,做成函数调用,之后continue或者break就可以去掉了。

写直观的代码

如果有更加直接,更加清晰的写法,就选择它,即使它看起来更长,更笨,也一样选择它

写无懈可击的代码

处理所有可能出现的情况,避免漏掉corner case。if语句就要把else情况都写上。

正确处理异常

Java的函数如果出现问题,一般通过异常(exception)来表示。你可以把异常加上函数本来的返回值,看成是一个“union类型”。

  1. catch异常的时候,你不应该使用Exception这么宽泛的类型或者。你应该正好catch可能发生的那种异常A。使用宽泛的异常类型有很大的问题,因为它会不经意的catch住另外的异常(比如B)
  2. 在自己函数的类型加上throws Exception,那么你就不可避免的需要在调用它的地方处理这个异常,如果调用它的函数也写着throws Exception,这毛病就传得更远
  3. try { … } catch里面,应该包含尽量少的代码,一个try里包含做一件事的逻辑代码

正确处理null指针

尽量不要产生null指针。尽量不要用null来初始化变量,函数尽量不要返回null。如果你的函数要返回“没有”,“出错了”之类的结果,尽量使用Java的异常机制

不要catch NullPointerException,而应该是在角色函数里处理过滤空指针

不要把null放进“容器数据结构”里面

其实是强硬的态度。你要告诉函数的使用者,我的参数全都不能是null,如果你给我null,程序崩溃了该你自己负责,采用强硬态度一个很简单的做法是使用Objects.requireNonNull()

使用@NotNull和@Nullable标记,它们的作用是:IntelliJ本身会对含有这种标记的代码进行静态分析,指出运行时可能出现NullPointerException的地方。在运行时,会在null指针不该出现的地方产生IllegalArgumentException

使用Optional类型,设计原理,就是把“检查”和“访问”这两个操作合二为一,成为一个“原子操作”。

附带:Java里closure的自由变量是只读的。所以内部类里的函数可以读外部的局部变量,但是不能对其写操作。

过度工程的征兆

  1. 就是当你过度的思考“将来”
  2. 过度的关心“代码重用”
  3. 过度地关心“测试”

小结

如果对上面的概述若有所思,有更多详细的细节在原文里-编程的智慧

上一篇下一篇

猜你喜欢

热点阅读