阅读 759

公司的技术债务是如何形成的?又如何破解?—— 编程原则

人的理解总有一个边界,然而软件的需求和功能不会,规模会随着熵自发性变大,其复杂性源自于大量的不确定性,无法避免。

同时,随着软件变得越来越复杂,代码库越来越臃肿,最终团队里没有一个人能够搞清楚系统具体是怎样工作的。即使,某时某个程序员想要尝试重构部分重复的逻辑,但由于牵涉的代码太多,且很难理解相关业务,最终还是放弃了。这也体现出复杂性的危害,就是会不断递增。

复杂性

出来混,迟早要还。当技术债务已经严重影响了公司的运作、工作的效率时,才会着手去处理这些方面的问题,可要付出的代价就太大了。

这样的悲剧,在不同的公司里不断重复,是由于因果关系的时空上的不连续,使得人们并不能从其中获得经验。所以,在编程这件事情上,如何处理好复杂性,就显得非常重要。

所谓编程,其实大部分时间都是花在读代码上,而写代码的耗时极少。

所以,对代码结构化的需求,并非是因为结构化的程序看上去有多美好,而是我们的大脑无法有效的处理非结构化的信息。

与此同时,我们的大脑只能保存7 \pm 2个信息块,优雅的代码会创造出尺度合理的代码块,正好与我们的 心智消化系统 能够吸收的数量相匹配。

海马体

海马体( Hippocampus ):记忆的速写板,随着时间的推进,会将大部分内容清除,腾出空间留给记忆新的东西。好比:CPU的缓存,速度很快,但空间极有限。

代码的复杂性主要有两个来源:

  • 代码的含义模糊,看不出来里面的重要信息。
  • 代码的相互依赖,某个模块的代码,不结合其他模块,就无法理解。

虽然,我们无法彻底规避代码的复杂性,但可以通过利用编程原则,来有效降低。

抽象

抽象,是指从具体问题中,提取出具有共性的模式,再使用通用的解决方法加以处理。因为代码量越少,程序的复杂性越低。

我们在编写程序时,需要始终记得,我们是在抽象这个世界,而不是去描述这个世界,这也是信息技术的精髓。

很多优秀的开源库,就是对某类问题很好的抽象,提供了一堆简单的函数,可以自由组合,来解决问题。

一个很好的例子就是Linux的文件读写函数,只暴露了5个方法,就抽象出了所有的读写行为:

  • open
  • close
  • read
  • write
  • lseek

那么,具体如何去做呢?推荐两个比较常见的准则:DRYRule Of Three

DRY

DRY 是 Don't repeat yourself 的缩写,中文意思是:不要重复自己。

它的含义是,系统的每一个功能都应该有唯一的实现,也就是说,如果多次遇到同样的问题,就应该抽象出一个共同的解决方法,不要重复开发同样的功能

Rule Of Three

Rule Of Three 的中文意思是:三次原则,指的是当某个功能第三次出现时,才进行“抽象”,代码越少,Bug也越少,没有重复逻辑的代码更易于维护。

隔离

如果能把复杂性隔离在一个模块里,不与其他模块互动,就能达到降低复杂性的目的。如果多个模块耦合,那就把这些模块合并成一个。

通过有效的隔离,我们就可以将程序进行分层,每一层都只专注于自己这一层的问题,封装内部的复杂逻辑,只暴露出最简单的接口给使用方。

开源框架(比如: Django )就是这方面很好的例子,你只需实现回调函数就可以了,不需要控制函数调用的顺序,就可以完成复杂的功能。

依据同样的原则,我们还可以对业务进行隔离,形成一个业务层,进一步降低复杂性。

YAGNI

YAGNI 是 You aren't gonna need it 的缩写,中文意思是:你不会需要它。

它指的是你自认为有用的功能,实际上都是用不到的,不要过度设计。因此,除了最核心的功能,其他功能一概不实现,这样可以大大降低复杂性,加快开发速度。

后记

编写程序和写小说有些地方是非常相似的,像《指环王》这样的经典传世之作,其人物关系构成了一个非常复杂的系统,但最初也是从第一个单词、第一段落、第一章开始写起,一开始构思的情节往往与最后的结果不同,免不了迭代、重构。

每当项目进展不顺利的时候,或者整个团队对项目很不爽的时候,拿出一两天时间清理一些看似无关紧要的小事,比如:重构代码,让开发环境更整洁,大家的斗志可能就会回来了。

最后,安利大家一本掘金小册《深入理解NLP的中文分词:从原理到实践》,让你从零开始,彻底掌握中文分词技术,踏入NLP大门。

如果,因为以上内容对你有所帮助,希望你能够点赞、评论、转发,多谢多谢!