本年度第10/100篇原创。每周六日20:00准时放送。
几十年以前,当人们还在用汇编语言的时候,对怎么写代码几乎是没有什么限制的,因为汇编只是机器码的翻译。我觉得汇编里最有趣的就是JMP 这个命令,你可以随意跳到任何地方,做任何事情,在编程世界里拥有无限的自由。
然后我们有了高级语言,倍增了我们的生产率。但是高级语言有带来了什么新功能吗?它能做的事情和汇编其实是一样的,它的效率高主要是写一行能顶汇编的好几行。但它的编程模型不同,叫做所谓的结构化编程(structured programming)。它提供了if/else/while/for,以及作用域的概念,它限定死了你的代码必须要有组织的按照一块一块的方式写到一个个用大括号括住的block里面,这是什么呢,这是一种对自由的限制,你的双手已经被套上了枷锁。
更不要说Dijkstra的那篇文章直接判了goto死刑,从此在结构化编程里你只能够从上到下,从左到右的表达你的逻辑,妄想从第131行跳回31行再蹦到68行去执行逻辑,这是不能被接受的。为什么这么做呢,因为跳来跳去的话debug和read就异常痛苦了。
所以,在我们欢欣鼓舞生产率提高的时候,不要忘记了我们是让渡了部分编程的自由,我们被告知:不要去做jump和goto,按structured programming的那一套来。这可以被总结如下:
Structured programming imposes discipline on direct transfer of control.
然后我们有了OO,OO给我们带来了什么新的能力吗?完全没有,汇编能做什么,OO也就能做那么多,剩下的也就是些编译器里面的魔法而已。OO的强大在于它的编程模型,它的概念比如encapsulation,inheritance,polymorphism。但是这些东西,更进一步的限制了我们的编程自由,我们的脚上也被箍上了枷锁。
Encapsulation?把我们要操作的数据结构包起来,限制了我们直接访问的自由。Inheritance & polymorphism? 用接口隔离了我们要操作的对象,在我们要操作的对象之上加了一层抽象,而我们只能操作这层抽象,因此这限制了我们直接访问的自由。
Object-oriented programming imposes discipline on indirect transfer of control.
最后再来看看函数式编程(functional programming)这个古老的模型,我记得当年学习SICP真是痛苦,以至于到现在都没有看完。functional programming 和我们现在的imperative programming模型完全不同,它给我们带来了天生完美支持并发的好处,但你要用它的话,就得放弃给变量任意赋值的自由。这一次,敌人把我们的嘴也堵上了。
Functional programming imposes discipline upon assignments.
有趣的是,一个被剥夺了很多编程自由的人,竟然藉由自由的剥夺而得到了更高的生产率。几十年来,编程本身并没有增加任何新的能力,各路编程模型的唯一作用是限制我们编程的能力。这就是标题所说的不做的艺术。人生又何尝不是这样呢,想做的,能做的太多了,因此最重要的是决定不去做什么。
What we have learned over the last half-century is what not to do.
不要忘了我们还有五大编程原则:S.O.L.I.D. 这些原则,更进一步限制了我们的自由。
对于S.O.L.I.D了,我想对S和O提一点自己的意见。
Single Responsibility:之前讨论的很多了,这里面牵扯到Single的定义,single的范围的大小的问题,这里官方的定义现在已经更新了:
旧定义:A module should have one, and only one, reason to change.
新定义:A module should be responsible to one, and only one, actor.
因为引起reason to change的只能是人,是stakeholder,也就是在新定义里的actor,这样就更加准确没有歧义了。下面这个图简明扼要的说明了违反这个定义是什么样子的。
Open Close: 我认为这是最重要的,凌驾于所有其他原则之上的一个原则,因为上篇已经说了架构的价值在于易于修改,那么最厉害的修改就是现有的code根本不需要改,而只添加新code,这样才能保证我原来的东西完全不会有任何机会被破坏。但是somehow,还有一个原则叫DRY,OCP实践起来,很可能会和DRY冲突,因为如果添加的新code都符合同一个pattern的话,即便business logic在每个新code里都是不一样的,但是为了新code符合OCP设定的pattern,它有一些脚手架的code比如继承或者template method的method签名本身,也会duplicate,特别是在template method有好几个的情况下。这里如果要消除pattern本身带来的duplication,那么势必破坏OCP,根据maintainace cost往往是最大的cost而不是写code当时爽一下,破坏OCP基本上是不值得的。
很多人误以为DRY应该是第一要follow的原则,然而DRY本身并没有那么重要。如果添加了2份code,2份code的business logic或者说解决的business requirement是不同的,那么它们的业务逻辑已经被很好的隔离了。过分追求DRY,将会破坏module间的de-coupling。
认清什么是true duplication很重要:
能看穿假的duplication而不去消除它,也是一种不做的艺术。
点击好看支持我哦
领取专属 10元无门槛券
私享最新 技术干货