“程序员就是解决问题的人”
五年前刚进入育碧时,经理的这句话深深的映入脑海,至今记忆犹新。
不得不感叹,国内外公司在不同的企业文化下,有着截然不同的价值观。就我后来的经历来看,大部分公司的开发主管是不会专门抽时间,举办一个会议告诉你程序员到底是什么样的人。我也许是幸运的,我牢记了这句话,并在以后的工作中不断的以此为职业准绳面对工作中的各种问题,建立了自己对于职业的好坏标准。
如同大家所知的,程序员分两种,一种是提供解决方案的,另外一种是coder。我这么说并不是说前者就比后者重要,相反,在一个和谐的团队中,这两个角色都扮演了重要的作用,缺一不可。因为他们两者之间的工作是不能互换的,他们谁都不能或者不愿意去做彼此的工作。
最近,有件事情也让我挺为难的。就我的经历中,我发现国内公司的经营模式与我的价值观有一定的抵触。这里不谈所谓的技术或者能力,我所接手的工作,大部分都是,上一个程序员留下来的摊子。这其实是非常正常的,但是每次当我去收拾这些摊子的时候,我发现,代码相当的凌乱,一部分是随意的hack或者hardcode,另外一部分就是,作者本人的逻辑已经有问题了。读这样的代码是非常不愉悦的,而且公司不能提供给你任何关于这个模块的信息或者文档,所以你必须要主动的去搞懂模块功能,并建立一个清晰的架构。
这里就有一个问题,这么乱的代码,为什么会被允许提交?
我认为,在程序的部门架构组织上,是需要一个主管的。这个主管,并不是技术特牛或者能力特强,而是,他能做到将整个部门的信息反馈整合。我之前见过一个主管,能力是尚可的,但是,他的能力仅限于写代码或者修bug,对于部门的管理基本为0,每次发版本的时候,才发现各种问题没解决,然后将相关人员组织起来一顿加班。对于部门的沟通也是没有起到任何作用,相反还要求自己手下的人主动去找其他部门沟通。
从公司的角度,一切应该是按照稳定来保证生存。绝对不允许发生的情况是一个人的离开导致整个公司的无法运行。所以这里必须要建立一个树状的管理结构,就算是某个子节点出了问题,更换即可。而有些公司的管理架构是图状的,这样就会导致,联系中心的人一旦离开,整个公司的运行就会乱作一团。
管理方面的事情我不在行也不多说了,回到主题,这么乱的代码为什么会存在?谁应该为模块无法继续维护负责?
我认为这种走一个人,就来一个人重新读重新写或者在原来基础上越写越离谱的情况,是公司的一种变相开销,虽然没有明确的体现在公司的财务报表,但是这里也是一些完全可以避免浪费的地方。一个程序主管应该对所有的代码质量负责,他必须清楚整个项目的代码情况,问题汇总,如何分配等,这些问题才是一个主管应该去关心的,而不是因为自己懂一些别人不懂的东西,就认为自己可以做主管了,其实压根不是这样的。现在的公司很少有review机制,即,任何一个程序员是不可以随意提交代码的,每次提交都必须由主管审核以后才可以提交,这样就算这个程序员离职了,下一个程序员接手的时候,一来是代码质量有保证,另外,主管也掌握一部分信息。
如果主管走了怎么办?如果一家公司的主管流失量也同普通员工一样大,那就是穷途末路了,这也是为什么主管的工资比一般员工工资高的原因,他的可替代性远比普通员工小,他掌握的信息比普通员工要多,想挣大钱的程序员,停止一头钻进代码里吧。
另外一个问题就是沟通,程序员有相当一部分不太会沟通,我自己的沟通也不是特别的好,所以也有深受其害的感觉。
这里的沟通并不是日常沟通或者技术交流。而是一种让他人接受你观点的能力。
目前有以下几种观点我无法从沟通上打败,而这种观点在程序员或者主程里是相当普遍的:
1. 为什么这个问题现在还解决不好!代码就这么几千行!
每次被问及这个问题,我都很尴尬,因为在这种程序员眼里,工作量和代码量是成正比的。也可能是我自己有代码上的洁癖(我对代码质量要求比较高),我对任何一行代码的更改,都会非常的谨慎,必须搞清楚上下文,会带来的影响,以及最好的解决方案。在一段比较凌乱的结构上,彻底读懂代码其实非常非常的困难(甚至会超过重写的时间)。我曾经遇到过这样的团队:
pPointer->Foo(); //崩溃了,原因pPointer为空
这个bug交给了我,我第一个反应是,检查pPointer为什么会为空。检查的过程中,主程过来了,问我bug修的如何,我说正在看。他说这个看那么久啊,很好改嘛。我说愿闻其详,然后他俯下身来,瞬间修复了bug:
if(pPointer != NULL)
pPointer->Foo();
这样的事情,我在不同的场合,不同的人身上都经历过。不知道如何去说服他,这么做其实是头疼医头脚疼医脚,因为他们总会以项目进度不允许花太多时间为理由彻底将你击败。
2. 写工具是浪费时间,你直接打印log不就完了!
当时的情况是这样的,给了一个模块,这个模块算是整个项目的一个小核心,凌乱如风,以前的程序跑路以后,项目里其他人也轮番的hack过。当时我读代码的时候整个人都有精神分裂的感觉,我不知道大家能不能理解这种情况下我的心情,呵呵。因为那个模块的核心是一个回调函数,会被不同的上下文回调,并且!注意,项目环境不允许你查看上下文信息(没有采用OO设计,类似于C吧,将上下文的信息用库函数结构给屏蔽掉了,所以没办法在内存查看器里看)!
其实,没有上下文信息的代码基本是不可以调试的,除非你愿意花时间去猜,并且也猜中了,并且那段代码恰好如你所愿的没有潜规则。但是这种几率相当的小,我决定写一个工具,让这个工具HOOK住模块并将上下文用一定的手段保存下来以便debug时查看。结果得到了如上的评价。
我真的不能理解,一个项目如果不靠工具,而全靠人力来维护是多么的蹒跚。也正是由于他们这样的观点,导致了代码维护成本的增加。打印log固然是个好办法,但是前提是你也得有一个工具能好好的维护log,而不是刷一大堆黑客帝国的代码在屏幕上,这毫无意义。后来我知道他将这种刷屏log同时保存在一个记事本文件里,然后直接操作记事本文件,这也是个办法,但是有工具了就有扩展功能的可能性(过滤,搜索,回滚),否则只有成天不断的CTRL+F。
3. 你的东西可以通用吗?
我在工作的第三个年头以后就没有通用这个概念了。一个程序员不能够永远停留在造轮子这个阶段。打个比方,一个资深的UI程序员,不可能仅仅是因为他非常熟悉或者了解使用CEGUI;一个资深的美工,也并不仅仅是因为他非常熟悉使用3DMAX。在解决一个问题的时候,我们要提供的不仅仅是代码,而是一个方案。这样的好处是,下一次遇到同样的问题,你不用重头再来一次。就算你换项目甚至换公司,你所得所积累的东西也一并存在。这样才可以提高你个人的价值。我想这大概也就是和coder的区别吧。如果你的主管也是coder那是一件比较悲催的事情,他们见不到你为公司提供的价值所在,在他们眼里,代码和代码没有什么区别,两个程序员完成同样的功能,他们对优秀的评价标准仅仅是时间快慢。所以这里涉及到的东西就跟经验能力挂钩,如何抽象出问题的需求,如何提供合适的解决方案来解决你这个需求,能不能保证下一次遇到这个问题的时候,将移植开销减到最小,能不能保证在任何项目和环境都可以正常工作,等等。这些才是我们应该花时间思考的地方。
4. 我们的这种解决方案比C++/STL/微软提供的好。
就自己的水平来衡量,我觉得这种结论是片面的。这是个无底深渊的讨论,不做评价了。
5. 他的工作高效,所以他是一个优秀的程序员。
我见过高效的,譬如第一点中提到的。如果我做主管,我绝对不会把高效和优秀画上等号。我也不能理解公司在开发过程中,居然没有任何人为项目代码的整体质量负责,有时候真的自己都忍不住想站出来帮忙整理代码了。呵呵。
6. 他有X万行代码量\日产代码X千行,所以他是个优秀的程序员。
不做评价,但是我不苟同。
...
啰嗦了以上观点,都是我遇到过的观点,可是我无法立刻阐述自己的观点和理由,其实这是相当制约发展的问题。每次都是表面上被对方说服,但是内心又觉得好像哪儿没对,等过一会儿才反应过来,不是这么回事儿啊,呵呵呵。
不知道我的观点是否也太过激,人的成长就是一个不断批判自己的过程,特别是程序员。我希望能尽快用自己的工作成果来印证自己的观点正确性。也希望在沟通方面自己能得到更多的锻炼和拓展。