来,说点大逆不道的。
代码是程序员的基础能力,毫无疑问。Linus 说,“Talk is cheap, show me the code.”。软件工程师,归根到底是要做工程的,代码写不好,就谈不上把工程做出来。
可是我觉得,越来越多勤奋的程序员,是写代码写得太多了,而不是太少了。
胡扯!读书百遍,其义自见。书山有路勤为径!代码也是如此,没有足够的积累,怎么能写得好代码?
可是,写代码真的需要那么勤奋地练习,那么大量的积累吗?
我想说一个现象,那就是很多公司每年都会举行调研,一个很常见的问题是,作为程序员,一年工作时间里面,写代码的比重有多少?
有一个很朴素的想法,就是如果编码时间的比例不足够高,那基本上就意味着程序员的时间都用去扯皮、流程,或者 ops……总之就是做一些内耗严重而缺乏实际产出效率的事情。进一步地,很多程序员就会抱怨,我想写代码,我不喜欢开会,不喜欢搞流程,不喜欢项目管理和人员管理。
可是,这真的 “正确” 吗?
来看看所谓的软件工程师的基础素质里面,写代码占了多大的比重?沟通、合作、学习,问题分析、解决,系统设计、算法,代码实现、测试、ops……到底有多少部分是 “写代码” 的?
如果我们把写代码看做软件的具体实现,那么,为了能写代码,有很多工作要做;而在写代码之后,也有很多工作要做。真正的、纯粹的写代码的时间,其实很少。
具体来说,当一个问题分析透彻,当一个系统设计清楚,当一个算法厘清逻辑,写代码的过程,本质上是一个使用特定的编程语言,将思路 “翻译” 到纸上(电脑上)的一个过程,这个过程难道不该很快完成吗?
如果你觉得写代码的时间很多,占得比例很大,我觉得多半可以怀疑,是不是这里面有些问题?
如果卡壳了很久,删删改改、来来回回折腾了很久,那多半是其它环节没有做到位。比如说,问题没分析透彻就开始写了,系统没有涉及清楚就开始码代码了,或者算法逻辑还没有厘清就开始先 “边写边看”……说到底,还是思考得太少,而代码写得太多。
哦,那看来这种觉得编码时间不够高的朴素的想法其实是 “错误” 的。
不知,你怎么想?
好吧,这有点像一个圈套,我认为正确和错误的回答都是不妥的。如果你是程序员,又在这一点上带着强烈的黑白是非的态度,无论觉得它明显地 “正确” 或者 “错误”,尖锐地说,这样的思维,似乎要把复杂的问题都简单地黑白论?如果回答是肯定的,那么我想这也是一个程序员思维模式很容易遇到的问题,因为我们在代码的世界里已经习惯了,使用 0 和 1 去描述一切。可就像生活中大多数的问题一样,很多问题往往不是非黑即白的——哪有可以用这样一句简单的判断,就给出绝对的是非结果来?
抱歉,扯远了……
话说回来,我从未否认的是,代码能力是程序员的最基本的素质之一,不会写代码的程序员无法称得上是 “合格” 的程序员。我只是觉得,程序员应当多分析、多思考、多讨论,实际我们能看得到的编码行动派很多,而 “想清楚了再动手” 的却很少。
也许有人会说,代码就是很难一蹴而就的,需要不断地迭代、重构,这是很花时间的。这话当然没错,但是我觉得现在某些流行的新的技术和编程技巧,让程序员的思考能力不断退化。
比如曾经大火过的 TDD(测试驱动开发)的例子,任何实践都是工具,是工具,就有适用场景。即便是最佳实践,也有不合适的时候,更何况 TDD 在我看来在多数场景下根本不是。不客气地说,在大多情况下,TDD 是弊大于利的。
原因就是它在一定程度上规避了好的自顶向下的思维习惯,而是自底向上,很容易丢掉系统和代码设计上的大局观,小细节抠得特别完美,结果做出来的东西大的设计是残缺的。
它带来的好处毫无疑问,对于一个即便设计能力不过关的程序员,也能够 “下手”,能够看到明确的代码产出成果,让情况看起来明显好过那些,不知道从何下手而干瞪眼的尴尬场景,因为自上而下的设计不但对于思考能力要求非常高,容易 “手足无措”,而且还容易让人感觉到 “没有进展”。
因此,自底向上的设计方法本来也没有什么问题,但是它的缺陷也太过明显。举个相关的例子,我们通常在面试的时候,一个新手程序员能掌握自底向上的思维方式其实很不错,但是如果一个老江湖了,设计编码还没有大局观,都是从一个个小的类和方法开始,写到哪算到哪,这样的程序员是不合格的(如果你对面试感兴趣,也认可我的观点,可以去看看我写的面试专栏)。
再有一个我工作中的例子,团队中的一位程序员在 oncall 的时候遇到一个上游系统 field 名称冲突的问题。简言之就是,我们系统交互中的 field 的名称通常都是唯一的,如果有冲突,我们的代码逻辑还没有足够聪明到可以应付这样情况的程度。他就在代码中增加了一个 “聪明” 的逻辑,通过引入更多辅助条件的判断,来识别当名称冲突的时候,哪一个 field 才是我们的系统需要的那一个。代码也不复杂,问题就解决了。
可是很快其他的一位同事看到这个问题以后,通过进一步调查和分析,发现在几个相关系统的设计中早就明确了,这个 field 就不应该冲突,于是和上游系统沟通后,这个 field 的问题从上游系统中修改掉了。而作为下游系统的我们,最多只需要增加一个验证的判断就可以了,根本不需要去带着任何正确与错误的假设,来处理这样的冲突问题,因为这样的的冲突本是不该出现的问题,而不是合理的特性。这就是一个问题不研究清楚,不沟通清楚,就拿写代码来凑的例子。
再呼应到标题和开头,所谓的 “写代码”,我们可以简单地将它理解为,问题都分析透彻了,系统都设计清楚了,算法逻辑也都厘清了,写代码的过程,就是一个将思维翻译成代码逻辑的过程。这个过程,不只可以说应当只占用程序员很少的一部分时间,而且还可以说,将来如果程序员的工作可以被越来越自动化的机器所替代,那么首先能被替代的几件事情中,有一件就是 “写代码”。
看看开头我们随便列出的程序员基础素质里面——沟通、合作、学习,问题分析、解决,系统设计、算法,代码实现、测试、ops,哪些才是作为程序员最值钱、最不可被替代的部分?
因此,往后再有还在情况模模糊糊的时候,就有想写代码的冲动的时候,不妨问问自己,真的是时候了吗?如果确实思考不清楚,那最好的办法,我觉得就是 “吹牛”,就把问题拿出来,和程序员朋友、程序员同事一起讨论,不要过于设置讨论的边界,内容完全可以宽泛一点(这也正符合吹牛的精神!),最好能讨论到不止你自己,连对方也觉得挺清楚,那就是动手写代码的时候了。
文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《四火的唠叨》
我认为 TDD 是一个有用的工具,但它有使用的场景。一个老程序员依赖 TDD,拿着需求或者简单的设计方案直接通过 TDD 开干是有问题的。
应该先完成系统设计和模块划分,到模块足够细的时候,才让 TDD 入场。
这吹牛不就是讲的编码前大胆设想方案,梳理逻辑的过程吗。
有想法却没实现,说是吹牛也没大毛病
代码活动 非代码活动
编码,调试,改 bug <—— 沟通、合作、学习,问题分析、解决,系统设计、算法,
代码实现、测试、ops,文档,FAQ
| |
| |
| |
\/ \/
交付软件 交付产品,维护
上述是我的一些直观理解,欢迎讨论。
留言中的空格给消除了,导致没有办法表现出真正的含义了…
can’t agree more