在你读到这篇牢骚的时候,无数个项目正在慢慢变烂。

图片来源于网络 - 2008汶川大地震

既然标题都用到了”烂”这个词,那什么才是烂呢?

在你的项目里,”烂”和”好”一样无法准确的衡量和定义,在大多数人的职业生涯里,你听到”烂”项目肯定比听到”好”项目的情况要多很多。

当你在一个维护型项目面前,一边嘴里跑出一万只草尼马,一边还在上面Coding,最后居然还如期交付了维护任务,你能说那是”烂”项目吗?

我自己也没有遇到过真正”烂”到无法维护的项目,因为我就是那个让项目慢慢变烂的人。

也许,”烂”项目的罪证无法像《如何编写无法维护的代码》那样容易罗列,所以你根本就不认为那是烂。

意识到项目的”烂”与闻到《代码的坏味道》一样是优秀开发人员的基本素养。

不过本文说的”烂”,只是从程序员的角度去看项目,与项目本身的创意,项目在公司层面的战略意义没有关系。

工具

在我刚出道时(06年左右),那时候的Java生态圈其实已经很强大了,但是我刚毕业工作过的几家公司,几乎在项目部署上都没有使用太多的自动化工具。

有的是直接用开发工具Eclipse打包war文件,其中一家公司,甚至是在本地编译Java文件,然后上传class文件到线上服务器,就算那时已经有 Ant 这样的先进工具,可惜我们还是类人猿,没有进化过来, 要知道制作和使用工具是人类起源的重要标志.

如今我们在一个最好的时代, 你有太多的选择, AntMavenGradle ……, 无论如何请把打造高可用自动化工具链与开发高可用系统提升到同样一个高度。

如果你的项目中使用到了工具,但是它却很脆弱:过多依赖环境,依赖复杂的配置,有时候还会有BUG。

如果你的项目还不能做到一键命令构建,打包。

如果你的测试环境和线上环境程序部署时间不在可控范围。

……

那么你的项目,肯定会慢慢变烂, 因为效率太低。

框架

是的,从你找工作开始,就肯定听说了这个词,如果你在学校的时候就是一个勤奋好学的同志,那么你早就听说过了,在Java的世界里,你不会几种框架,还好意思出去混吗,于是很多招聘里面都提到,精通Spring,Hibernate,Struts,Mybatis … 我入职的一家公司,甚至还有公司框架Demo代码学习这个环节。

So,当你到公司第一次接触到项目的时候,我想上面提到的这几个框架,至少有一个出现在你的项目中,先来看看我遇到的项目中使用框架的情况:

  • 使用了框架,但是版本已经是上个世纪的了,却依然在线上跑着
  • 依赖同一个第三方开源工具包,却有多个版本
  • 有的地方用了框架的注解配置方式,有的地方却用的XML配置文件
  • 一个本来只需要几十K代码搞定的项目,最后把框架依赖一起打包,至少几十M
  • 没看出来为什么这个项目需要用到这个框架
  • ……

框架一词原本来自建筑学,在软件行业里面,本人理解框架,就是解决特殊场景问题的 抽象 实现。本着娱乐的精神,这里就不引入太书面的文字,容易引起反感。

如果你的项目和我遇到的情况一样,满足了上面两点以上,我相信,只要这个项目还要继续,就会继续变烂,原因大概有以下几点:

  • 你是一个有理想的男青年,你想把机械键盘砸在那个已经不知离职多久的前前前同事的脸上,然后大声喊出来“老子要重构”,然而老板说:可以,你先把这一堆需求实现了再说。
  • 最后老板还是同意了,没事儿你就重构吧,但是,你敢把一个正在好好running的线上项目框架换成最新版本吗?(你的项目用到还不只一个框架,有些框架之间在版本上还有依赖的,你不可能只升级其中一个)
  • 想到这里,再抬头看看周围Coding的同事,有的是已经工作了数年的老腊肉,还有一波刚入职的小鲜肉,他们是否和你一样有理想,有追求呢
  • ……

如果你学过PMP,那么上面这些问题可以概括为风险和成本。

引入了框架, 那么项目成员是否在框架上做足了技术储备? 如果仅仅是达到使用的地步,那么由于框架引发的问题,你是否能够在最短的时间内解决?

不然框架就成了项目的枷锁,即使不会让项目慢慢变烂,也不会让项目慢慢变好。

领域模型

对啊,没问题,我们项目里面的使用Spring,爽得不要不要的,Spring不是提倡面向接口编程吗,我们有完善的Service接口层。

是的,就像上面提到的,我曾经学习过公司的框架Demo代码,里面把Module都分好了,Domain, Dao,Manager(用于管理DAO层的事务),Service,Web。 真实的情况却是,Service里面,一个Service接口对应了一个Dao(大部分情况是这样的),你有几个数据表,大概就有多少个Service接口,如果有个新业务来了,添加了一张表,就再搞一个Service接口,Service,Dao基本都是在为数据库CRUD服务。

一个接口类从项目产生就没有出现过多个实现, 当时定义接口仅仅是为了遵循面向接口编程。

在充满疑惑的岁月里,我找到了真相,原来我把名词理解错了,“DDD”的含义有两种,一个是Data-Driven Design,一个是Domain-Driven Design

一个没有领域模型抽象的项目,迟早要慢慢变烂。

代码

框架和模型是让你站得更高的角度来看项目,最后还是得回到代码上,好的项目(应该说团队)一定能够找到一套规范(当前流行叫”军规”), 每个团队制定的规范可能有些不同,但还是能找到很多共性.

  • 代码规范(Checkstyle, 方法名,类名规范,注释规范,代码格式规范……)
  • 工程规范(构建流程,版本发布……)
  • 设计规范(设计复杂度控制,模块依赖……)
  • 数据库表设计规范, SQL规范
  • ……

经过我多年的经验,制定规范这事儿,其实重点在如何让项目成员理解和认同,最后才是执行,很多项目成员对规范的抵触源自浮浅地认为规范只能让他们将时间消耗在非功能性需求上.

规范是一种认同感, 但要想让项目成员建立更好的认同感, 有时候你必须利用人格魅力(如果你有的话),或者惨痛的经验(老司机肯定有的).

抬头看看你的项目, 能不能找到一条硬性要求的规范, 如果找不到, 可以直接跳出该文.

如果你有所觉悟,然后只是到网上到处借鉴各种军规堆砌在项目里, 那么依然没什么卵用.

规范并不能让你的代码变得多优秀.规范只是防止代码里到处弥漫着单身屌丝程序员(猿)的个人感情色彩,规避一些显而易见的错误.

有了规范, 你有没有代码审查?

你在网络上到处都能搜索到” XX团队如何看重代码审查,XX团队为了代码质量开发了一个代码审查工具”, 可是你很难找到XX团队是如何做代码审查的,所以搞清楚如何让代码审查起到作用 比代码审查本身更重要.

总之,在代码审查之外,你还需要权衡,要不要把代码审查搞成政治任务,要不要搞成批斗大会, 如果你在代码审查的气氛里面闻到了坏味道, 那就应该停下来.

一个做好了代码规范和代码审查的项目,想变烂都没那么容易.

测试

我在大学里面学编程的时候,似乎老师都没教过什么是测试,当时写TC的时候,老师只是说上机执行,现在回想起来,好像当时的教材也没有专门讲测试。(也许我就没有好好学过)

从项目代码来看,最基本的就是单元测试。

你的项目虽然有单元测试,但是他们要么过时(没有和被测试代码一起演化),要么根本就没有达到覆盖率要求。

当你想给一个功能补写单元测试的时候,发现编写单元测试的难度比重新实现这个功能的难度还要大,结果你就真那样做了。

测试的目的就是为了发现尽可能多的缺陷, 尽量 保证质量。

然而很多项目根本就没有清晰定义出 质量 的边界,甚至只完成了功能测试。

罗列你项目中的测试项,将他们分类列举,如果测试项用一张纸都能写完, 那么这个项目本身就是烂的,根本不需要慢慢变烂。

再强调一下,如果没有充分测试(怎样才是充分测试?)的项目,其实已经烂了。

需求

所有的业务需求你都应该去满足

业务是项目的基本驱动力,可以说没有需求就没有项目存在。

然而对于一个发展中的项目,有可能正是需求在让它慢慢变烂.

因为我见过太多的需求来至项目控制人员(简称领导),而不是来至于真正用户,这些项目控制人员还会振振有词地说:”我也是用户中的一员”,大部分开发人员基本上又都处于食物链的最低端, 所以遇到上面这种情况,基本是无解的(排除那些真正执行工程师文化的公司).

大部分项目的需求,都会对应到一个系统功能,系统功能都会有生命周期,但是项目中的代码却往往随需求一起增长,对于过时的功能代码,没人敢随便删除,然后就变得臃肿。

另外一种情况就是需求超越了领域模型,例如:ATM取款机,让你植入视频播放功能(现实生活中却真有的),你有时候无法分辨出这类需求,然后却漂亮地实现了它。

恭喜你,你的项目正在面临慢慢变烂的风险。

负面情绪

负面情绪让项目慢慢变烂,听起来有点牵强,其实负面情绪与项目中的”烂”有点像鸡与蛋的关系,但这也只是其中一方面,放眼望去,项目中的负面情绪来自于方方面面。

部分开发人员如果遇到《如何编写无法维护的代码》 中提到的问题会让他们大怒,然后抱怨没有统一的代码格式化工具,没有规范的目录结构,甚至日志输出格式也是五花八门……

如果你在项目中经常听到这种骂街的声音,那么你所在的项目还不至于那么快变烂。

不满现实,并动手去改变它,这也是优秀程序员的基本素养,但你必须停下来思索一下,你周围的人是不满的多,还是动手去改变的人多。

我自己就非常愿意和不满现实并且情绪化的开发人员一起工作,非常惧怕那些只是抱怨,说到动手去改变的时候又保持沉默的人。

情绪会传染,有些情绪在团队中会产生负面的效果,有些却能成为动力,这取决于团队的自我认知能力。

如何识别项目中遇到的负面情绪呢?

  • 小A最近经常一边写代码,一边逛招聘网站
  • 小B经常给你说,[某某公司]的工资更高,全员MAC环境开发,23寸显示器…
  • 小C给你讲,小A和小B的代码写得真烂
  • 小D抱怨技术上得不到提高
  • ……

放心,如果你在项目中是个领导角色,上面这些抱怨列表你基本上是不会听到的,如果你只是一个普通的开发人员,那么就去购买一本《程序员自我修养》,将负面情绪转化为正能量。

保持现状

有一个老程序员自豪地告诉我,他写的一个程序已经在线上跑了快10年了,从来没动过。

我只是笑了笑,说了一句:牛逼

如果我写一个打印Hello world的程序,部署在一台太阳能Linux机器上,然后把它放到外太空,谁知道能运行多久呢。

我做的部分项目里面,用到的第三方工具距离最新版发布时间有的至少快5年了。

同事告诉我,用着这么稳定,干嘛要升级。

你要知道,JDK现在多久发布一次?每次都有哪些BUG修复?有哪些性能提升?你用的这个第三方包,可是在5年前那个版本的JDK下开发完成的,而且那个开发第三方工具包的人有可能还死了。

请注意,我们不是在讨论升级的问题,我们是在讨论 变化 的问题.

保持现状是一种惰性思维,它已经麻痹了开发人员对项目变化带来的风险评估。

如果将项目比做一辆汽车,它只是在不停地行驶,却没有定期保养。(重点是你不知道应该保养哪些部件)

不要让保持现状的思维腐蚀了项目,让项目慢慢变烂。