走出软件作坊(二十七)(转)
二十七、沙场秋点兵
前几个月,公司旁边的写字间又搬进一家公司,好似也是做软件的,而且好像是刚成立的公司,程序员们天天加班,神情很年轻,头发很油,穿着大背心大裤衩人字拖,男的女的都有,经常站在通道里成群的吸烟,或者干脆席地而坐围成一堆开会,都不下食堂吃饭,都订盒饭,中午晚上都是如此,我经常晚上下班,看见他们不时有人捧着一个盒饭从办公室走出来把吃完的饭盒扔进垃圾筒,不知道他们会工作多晚。
近来发现,他们开始有人正常下班了。他们也很少聚在一起抽烟开会了。通道里有的只是单个的人在打电话,声音很低,神情普通。偶尔看见他们在外面通道里开会,也是个个神情紧张或肃穆或很累或木然或沉默。
我想起了一句话:Boy,Slowly,Slowly。
新的产品,新的梦想,大家都很希望能够把多年积累的知识都用上去,做一个业界一飞冲天的产品。但是,这这个新的团队呀。
我想起了我刚出道的时候。我现在仍然很庆幸我能经历一个产品的从萌芽规划到实现到销售到规模销售的整个过程,让我看到了一个产品是如何成长起来的,在成长过程中会遇到哪些问题,是如何克服的。很多程序员没有这样的机会,往往一出道,就加入了一家运行N久的公司,团队是现成的,产品是现成的,自己就是做维护开发而已,没有完整经历一个产品生命周期。所以一旦遇到新开发一个产品的时候,就很茫然,不知道如何下手,而且心情很激动,过去一直维护别人的代码了,很多弊病想推翻重做都不行,现在终于自己可以一展身手了,这回要把自己的想法都加进去,不能留有遗憾,不能重蹈覆辙。于是扑入了自己全部的心血,就连睡觉也不踏实,每日心情澎湃。但时间不长,两个多月,各种问题就都来了。新技术、新团队、新产品,一切都是新的,很多交叉出现的问题让解决异常困难,团队也出现了烦躁,看淡,疲惫的情绪,大家想尽快结束,但开发才到中间,正是关键攻坚要命的时候。
我刚出道的时候,加入了一个新成立的研发中心,才成立四个月,我是第六人。产品还在规划当中,团队还在建设当中,技术还在学习摸索当中。
当时的技术总监做了两件我现在也认为很对的事情:一、他让所有人阅读上一代产品的源代码,整理上一代产品的功能,并且得出上一代产品的功能所映射的客户业务流程。并且要求指出上一代产品业务流程中的漏洞和矛盾。二、他让大家通过改造源代码来学习新技术。
他不仅仅让大家整理业务,还要画出来详细的流程图,整理出详细的数据结构。然后安排集中会议让大家讲,讲的时候,以流程图为主,走到哪一步,就进入软件界面讲解,并且讲明背后的数据存取到底是处理了哪些字段标志, 表之间是怎么关联的,到底从哪些表中取出来,表结构设计的有什么不合理的。
这次没讲明的,这次提问没有确切答案的,下次继续讲,而不仅仅是讲一回。我发现,很多团队缺乏这种不断追根到底的魄力。总是虎头蛇尾,第一次讲的很起劲,讲的期间出现了自己也没有理解透的东西,领导只是安排下去再去研究一下,但就没有了下文。自己下去了看了一下,认为找到了答案,但就没有再次校验的机会了,于是最应该细究的地方被这样放过了。我们知道,编写程序,往往是最细节差异的地方最容易出现问题,而且很少能被测试到,而且维护代码的程序员往往不清楚这块是干什么的,一旦出现问题很难阅读懂。
技术总监还让我们改造源代码。但这个也是有目标的,就是把控件都修改成一个统一的体验风格,没有DB的控件,就去寻找。寻找到了,就把这部分代码摘出来,然后形成我们自己的控件包,力求不要为了一个小小的控件,就安装整个的控件套件包。实在寻找不到,就自己开发控件。
学习新技术,我认为这种方法是最好的一种方法。我现在也是这样指导我的下属的。
学习新技术,为了怕误导,一是阅读官方的例子,如JAVA的宠物店或.NET的宠物店。但我后来我明白了,不能这么学。因为本来就对新技术陌生,一开始入主的就是这样的代码,那么以后的编写程序的风格就往往会像这些例子一样。其实,我们编写业务应用程序,并不需要这样的架构风格,也不需要秀那么多代码模式。照猫画虎把我们画的很累,还扭转不了已经固有的思维。我们不需要这种看上去很美的代码。
学习新技术,第二种方法就是找一个网上开源的什么系统,如某些新技术尝鲜者做了论坛系统或什么什么管理系统。但这种方法也有个弊病,就是他自己写的代码有他自己的风格,而且他还处于尝试期,写这个东西可能是他为了学习这个技术,而非目标是开发这个管理系统。本来咱们对于新技术就是一张白纸,这下被他带到沟里去了。
学习新技术,第三种方法就是阅读这个新技术本身的源代码。可惜本来就对新技术不熟悉,而新技术本身的源代码更是复杂,看的云里雾里,吃力看不到进展,欲想放弃。
所以,学习新技术,最好是学习基于新技术的第三方的外国开源源代码。他们对新技术理解快理解深入,他们应用新技术不是为了尝试新技术或者秀新技术,他们是为了完成他们的一个实用产品。我们当时为了摘出某个控件,几乎阅读了那个控件套件包的所有源代码,并且理出了源代码的结构思路,否则我们无法确定我们遗漏了什么,会不会有BUG。
但是,现在回过头来看,方法是对的,时机却是错的。
我们是新团队、新产品、新技术,很多我们尚未了解清楚的,我们却把我们学习新技术后得到的控件应用到了我们以后的正式产品中,并且作为基础应用。这给以后的发展带来了几乎是灾难性的打击,我最后费了好大的劲才算把基础重构并且稳定住,否则基础崩盘了,上面的应用就不可收拾了。
所以,我现在都是尽量限制使用新技术。也就是说,不会让新产品、新团队、新技术这三个新都同时出现,风险太大了。而且坚决不使用新技术作为基础技术。
我们还犯了一个错误,就是正式开发的时候,我们一上手就开发基础框架。大家都知道一个系统的基础框架的重要性。但是我们却用刚刚学会的新技术开发我们以后业务模块都要深度依赖的基础框架。我想起了某公司一套战略性的大型产品的开发:用的是新技术JAVA,大家都还是新团队,做的也是新产品,全体程序员都已经封闭开发了,居然有人提出了一套自己也未经过商业规模应用验证的基础框架,并且自己实现了一个小DEMO。大家一看这个小DEMO非常有思想,就决定让整套产品线都应用这套基础框架。
我想象他们的痛,和我很神似。所以,我现在如果面临新产品、新团队、老技术,我都不会让大家一上手就开发基础框架。
去年,我就面临了一个老团队、老技术,但是是全新一代产品的开发。
具体情况是这样的,经过几年发展,我们的现有产品渐渐老化,所以决定要开发新一代的产品。上一代的产品是C/S结构,而且是适合单客户使用的。这次,我们要开发B/S结构,而且是适合集团客户使用的。
让上一代产品的开发团队继续维护上一代产品。让新一代开发由新的开发团队去执行。所以,我们就招聘了新的团队(当时公司对开发新产品有不同的利益冲突团体,还没有达成一致,招聘新团队既有为新一代产品开发做准备的目的,也有其他的目的,造成这支新团队的打造过程中往往出现两种极端:要么好几个人都管,要么三不管)。刚开始并没有去动手设计与开发新一代系统,而是为客户定制开发了一两个其他IT项目。所以说还算接触了客户行业,大家彼此在一起工作也快八个月了,算是一个老团队。
但是这支团队对客户、对现有的产品并不深刻了解,虽然我给团队多次讲解过业务,也让大家分析学习现有产品,阅读现有产品的说明书,根据新的业务模式也组织大家一起分析业务设计功能、编写功能设计说明书,但理解上确实还不够令人满意,大部分人还是似懂非懂。遗憾的是,在老板的规划下,新一代的系统开发必须启动。
如果这时候开发基础框架,大家根本不理解以后这个基础框架之上要编写什么样的应用代码,那么这个基础框架就会变成形式,以后的应用代码怎么都觉得这个基础框架没什么用,用起来也是格格不入,不像是螺丝对螺母那样合缝。
所以,我先安排团队开发了系统管理工具。这是个没有具体业务的,而且通用的,而且也是基础框架的一部份的开发工作。但是,由于系统管理工具,涉及到了新的组织结构模式,新的权限控制模式,这是大家不太熟悉的。而且编码架构风格和他们以往的开发不太一样。所以开发起来也是疑问不断,需要实时复查代码,实时解答问题。
终于开发完毕,我们开了一个总结会。大家都总结了对这次开发的体会,并且讨论出来以后再遇到这样的问题要如何解决,每个人的分工和人员配合流程再次确定,功能和功能的用意再次给大家讲了一次,对于新的编码架构风格再次讲了一次好处和用意。大家都说:如果在开发前就把这些讲清楚了,那么开发就不会遇到这么多问题了。我说:开发前我就是这么讲的,但是大家都不理解。这次经历过来了,就明白了。
接下来该怎么办?
我说:重新开发一次系统管理工具。时间为期十个工作日。
大家都啊了一声。干吗要重新开发,好不容易开发出来就这么废了?
我对大家说了我的经历,我说:系统管理工具是基础框架的一部份,是以后用户很常用的工具,而这个工具却是我们在不清晰不熟练的阶段开发的,我们如何能把这么重要的基础功能交付给客户呢?尤其以后这个工具要和需要系统结合,这个工具的数据结构目前还无法支撑以后的众多连接,你们也看到了许多遗憾,我们不能一起步就是个瘸子。
大家又问:那过去的代码我们还能用么?
我说:你们自己看需要。我既不赞同你们尽量使用过去代码,也不赞同全部重新编码。如果你们想把一个有残疾的代码上改造成一个优秀的代码,我说不可能,过去的很多缺陷会牵绊着你。你为了保留过去的代码,你就会向过去妥协,而把丝丝缺陷带了进来。每个人每个功能都留了一点点小尾巴,那么所有开发的功能总和出来的缺陷就是一个大问题。所以大家自己看着办,先重新写,需要用的时候自己就COPY出来。
果然,理解了清晰的功能和功能用意的程序员,开发起来很快,毕竟都写过一次系统管理工具了,也是老技术、老团队了。半个月完成工作。
我问:上一次你们编写的系统管理工具代码用了多少?
他们回答说:不到20%。明白了思路,重写起来很快,反正没有什么高难度技术。本来想COPY旧代码,发现老有关联,摘不干净,还不如重新写一个来的快。
我说:好。咱们下一步就实现一个咱们系统中最简单的也是比较边缘的一个业务子系统。在开发中大家重点发现需要什么公共功能,咱们都提炼出来,就会形成咱们的基础框架的一部份。
这个简单的业务子系统开发了出来,我又开了总结会。
大家这次都发言热烈:我现在终于发现了系统管理工具和业务子系统之间的关联关系了,他们有很多代码能够共用。由于这次开发业务简单,而且经过上次系统管理工具的开发,开发方法和代码方法都已经熟悉,对于系统管理工具的认识也深刻了许多,所以这次我开发业务系统的时候,还顺便把过去的系统管理工具的代码进行了重构,发现了不少可以共用的部分。我发现,这些基础代码总结了出来之后,好像系统管理工具也是从这些公共代码基础之上开发出来的一个特殊的业务子系统了,所有子系统都依赖这个基础代码框架。过去本来系统管理工具的风格和业务子系统不一致,这次重构,一下子都统一了。
我笑的很开心,似乎我过去的心结终于可以解开了。