Tag Archives: 软件工程

国内软件行业2种低级行为

  一、违背软件工程基本原理,妄想“纸糊“航空母舰

  一个在微软给操作系统做过测试的老朋友,在朋友圈吐槽很多软件公司老板不专业:“核心原因是没干过硬事,自然更不明白该怎么设计体系去干硬事,听不进也听不懂专业人士的建议,只能在自己认知水平上拍脑袋……”

  二、剽窃开源社区的成果,搞所谓“自主可控”

  当年Ubuntu便是从Debian分叉出来的。其实在开源软件社区,只要有本事,fork分支另立山头没啥不好意思。但若三观不正,修改授权协议,替换文件名,然后说代码全是自己写的,这就会被整个行业戳脊梁骨。

软件研发和团队交流

  下面每一段话都源于近半年的亲身经历,很多话是拥有十几年软件经验的老兵的原话。

  当了pm,尤其是没有界面不需要Axure的底层Web Service的pm,依赖一支巨大的分布式团队,面对不止一家强势客户,交流就成了最关键的任务。半年前我还是中科院里一个不折不扣的技术宅男,与生人聊非技术话题有障碍,害怕给陌生人打电话,外出聚餐拿菜单看半天也不知道点什么。幸运的是,跳槽后碰到几位好上级,每次掉进坑里都能获得诚恳的建议,甚至专门帮我复盘。

  我有每天记录想法的习惯,很多内容整理之后就发BLOG。但这个“团队交流”的主题等了很久。涉及公司内部信息,无法带上具体场景,很多血泪经验就成了糖水大道理。也因为积压太久,即使只放是糖水大道理,慢慢也存了很多段。不管怎样还是发出来吧。

  公司一直在剧烈重组。以往我设计软件架构很少考虑人的交流因素。现在算是理解了著名的Conway’s Law: A design reflects the structure of the organization that produced it。这条定律的意思是:什么样的团队组织结构,最终就会开发出一模一样的软件架构。如果有四个团队合作开发编译器,系统最终一定会长成一个四阶段编译器。所以大型软件组织内,在重构系统之前往往先reorg团队。对分布式的团队,更加如此。前一阵很多人在Blog里写分布式团队的交流问题,用了很多招数,例如两边架起摄像头和大屏幕,形成一个虚拟的统一环境。

  到飞天团队,发现与以前在pFind倡导的工程实践没太多区别:SVN、BugFree、定期重构、单元测试、站立会议、代码review……所不同的是执行。飞天主力是微软出来的,有软件工程基因。制度和团队平台给力,就算是大三实习生也能大展拳脚,两三天内完成千核并行复杂算法的剧烈重构和测试。实际上pFind团队规模已经很大了。飞天内很多小team总共才四五条枪,而且大多是本科刚毕业甚至实习生,有些专注于统计机器学习的算法团队,工程产品也非常宏大。这是人际沟通和工程效率问题,不是学术或工程的非此即彼的投资方向选择。对pFind感情很深,希望后继者有勇气和智慧做到我没能做到的。

  敢提出傻问题是有责任心的表现。很多新人、边缘人、接口人都有交流障碍:不敢把点子或疑问拿到桌面上来,借口是:还不了解情况,等我彻底变成“自己人”再说。怕问错了显得不够牛,或者问对了牵涉别人的利益。明哲保身是动物本能,但它仅仅在黑暗森林低级生态环境下才算是最佳策略,在一个有序、专业、理性的团队里,过分谨小慎微只会显得无能,让别人放弃对你分享信息。反过来,直言不讳也是一种压力测试,可以借以观察团队氛围是否正常。

  tech lead最重要的素质是充分沟通的勇气和器量,“领导和下属之间应该’下棋’而不是’打牌’,在信息对等的情况下决策。尤其是坏消息,必须第一时间告知下属,坏消息往往传得很快,最好让下属从你这里首先获知。”反过来,最愚蠢的举动就是伤害团队对自己的信任。情绪管理、私人利益、交流效率都对信任感造成影响。

  网络公司的技术团队往往被分为前端团队、后端服务团队和基础平台团队。不同类型的团队交流和思考的方式不同。出色的基础平台团队,节奏感往往非常强,知道先做什么后做什么,一开始只做最难最重要的事。

  需求分析的时候,用户经常是在告诉你怎么做(How),这些信息没用,你要问清楚他们的本质需求(What/Why)。用户说要什么就做什么往往死得很惨。福特说:“如果最初我去问顾客想要什么,他们一定会说:一匹更快的马”。

  技术->项目->产品->服务,这是个漫长的进化过程。和一个陌生的技术团队聊,最重要的就是评估他们在这条打怪升级的不归路上位于何处。已经拥有成熟服务的团队会问你:“需要多大程度的可用性?我们的服务目前能达到五个 9,也就是一年无故停机最多5分钟。”(关于服务怎么运维,现在DevOps讨论很热,推荐看看这个

软件工程的经验教训

  很早起来开车送家人去医院看病。到单位的时候,牙齿还在打战,北京的天气凉下来了。这周安排和zk一起双人编程,他还没到,我先上来看看Google Reader写点BLOG。

  作为所里的内部培训师,我常被各个中心和课题组请去分享软件工程的经验。这是上周刚做完的一次报告的ppt。我会不断更新内容,感兴趣的同志可以隔三差五地关注我的工作主页的Technical Reports栏,下载最新版。

  收到越来越多的同事的邮件,和我讨论软件工程、系统架构和设计模式。作为国立学术研究机构,我们所处的环境的确不同于商业机构的软件研发团队。但从另一方面来说,总是有更多共性的问题在里面:如何挑选、培训和激励人才,如何做计划并执行……总可以做的更好,更有效率,更有成就感。

  我PPT里没深入写PM自己的心态问题。这是最近两年切身体会到的一个重点。软件项目压力很大,极端情况下,甚至会造成心理伤害。优秀的PM必须有器量和涵养,懂得欣赏优点,愿意信任同伴,既有发自内心的称赞,也有就事论事的提醒,还有开诚布公的道歉,在团队里营造出和谐的气氛来。如果碰到一个鸡贼刻薄的PM,大家心里充满恐惧和抱怨,就会只顾着关注PM想什么,逐渐丧失专业人士的主动性和独立见解。更深入点来说,是否愿意信任他人,也许正反映了PM本人内心深处的安全感。态度决定命运,对周围世界的基本看法,会决定一个人能否得到同事的尊重和喜爱。我最后悔的、常常反省的事,就是有几次在种种压力下冲别人吼,这往往有很大的负面影响。当然,人不是机器,情绪都是波动的,需要恰当的释放,也需要逐渐成熟。总之,PM要提高自我修养,防止负面情绪泄漏给无辜的同伴。

  刚好前两天网上到处都是创新工厂的那副“PM跪求研发”的图片,PM的心态好一点,项目就会顺利很多。zk来了,下次再聊。

PM跪求

PM跪求

软件中的隐喻(Metaphors)

  引子:老妈从深圳带来的《代码大全》,一直没看,不喜欢太厚的书(更喜欢作者早期的《Software Project Survival Guide》小册子,微软开发三部曲还是我大一第一学期花5块钱从地摊上淘来的)。今晚又犯病睡不着,索性听着音乐,找出来翻。的确把软件开发的事情都说完了。看到“隐喻”这一章有所感,上来敲点东西。

    

  隐喻(Metaphors)是XP编程的12个实践里很重要的一个,但是一直不像双人编程(Pair Programming)、重构(Refactoring)和持续集成(Continuous Integration)那么广为人知。

  其实这个概念是软件开发里最常见的现象和思维方式。《代码大全》里这样举例:

  计算机科学领域中有着所有学科中最为丰富多彩的语言。你走进一间安全严密、温度精确控制在20℃的房间,并在里面发现了virus(病毒)、Trojan horse(木马)、worm(蠕虫)、bug(臭虫)、bomb(逻辑炸弹)、crash(崩溃)、flame(口水战)、twisted sex changer(双绞线转换头)、fatal error(致命错误)……在其他领域里,你能遇得到这些吗?

  软件是一种看不见摸不着的抽象产品。因此我们不得不大量借用实体世界里的概念进行类比。例如在软件工程领域,随处可见各种建筑学的隐喻:architecture、scaffolding、construction;另一种常见的隐喻,是把软件项目当作生命体:incremental、iterative、adaptive和evolutionary。

  我们组内其实也在使用自己的隐喻体系。比如用“发车”和“跳”来形容pFind引擎的两种不同的搜索流程。

  其实,区分老手还是菜鸟很重要的标准,就是看他了解多少“行业黑话”。最初我在组内汇报到处写“bug”和“crash”这些词时,BOSS H很紧张、困惑,甚至有些愤怒。后来他就习惯了,明白这是工程开发中令人不快、但不可缺少的主题:某种意义下,编程的主要内容就是在有限成本条件下,尽可能有效地大量试错(胡思乱想:似乎创业也同样)。

  XP之所以强调重视隐喻,就是希望项目内建立统一清晰的概念词汇表。当提到某个词汇,在所有人脑子里都代表同样的逻辑概念。很多青涩的项目经理以为这种统一是理所当然的,他们错了。大量误会都源于鸡同鸭讲。

  对于我们生物信息这样的交叉学科,隐喻更是特别重要。生化学者和程序员简直就像不同的星球上的文明,需要很长时间才能彻底理解对方的意思。一个真实的例子:关于buffer这个词,在程序员世界里是一块预先申请好的内存区域,而对于生化领域来说,这表示做实验的缓冲溶液,我是在前线陪着生物学家杀老鼠做实验,花了三天时间才弄明白他嘴里的buffer不是我心里的buffer。有时不同的词汇又代表相同的意思,例如,生物学家喜欢说“高通量”,经过一段时间以后,我才能确认这就是计算机领域的“高吞吐”的绝对同义词。

  类似的,从事金融软件开发的哥们嘴里充斥着“期货”、“杠杆”、“抵押”、“融资融券”这种神秘密码。

  为了交流和思考,你必须把面对的专业领域里的术语迷宫搞清楚。对于传统行业,这种事也许只需要经历一次。对程序员来说,每个软件项目都是全新的思想历险,所以你要随时准备更新自己的隐喻词典。

  很多生物专业出身的学者学习能力都很强。他们要完成自己的研究,就必须对截然不同的众多领域都有所了解:从培养植物动物微生物,到临床小分子药物代谢,到遗传学和环境学,到化学试剂和各种分子式,到物理和精密机械领域的各种泵、质谱、磁场、超导题的原理,最后到Perl语言写软件处理大量信息……这就导致他们视野很宽,思维方式很全面。最关键的是,人不可能天生就是通才,出色的生物学者大多都善于跨领域交流和学习

  BTW 1:前面BLOG提过,程序员大都很着迷电影Matrix。因为这部电影把软件领域的隐喻反过来又映射到实体世界。电影名字本身就是一个很精彩的隐喻,Matrix在数学领域是“矩阵”的意思,在虚拟现实领域大量应用矩阵运算,比如《精品飞车》里的光影效果;而Matrix的另外一个意思是子宫,暗示电影里所有的人类都被放在那个黏糊糊的囊里养殖起来,以为自己生活在21世纪的地球,其实被接入了一个巨大的在线游戏,终其一生处在一个梦境,而Architect,那个机器,那个高等存在,控制着我们,随时以上帝的形象改变我们的命运,甚至kill掉我们的process(进程)。

  BTW 2:如果一个人开始仅仅守着自己的一亩三分地,不敢尝试未知领域,没勇气让Metaphors和外界进行碰撞的那一天,大概也就是他衰老的开始吧。

XP和项目管理

  越是不了解XP缺少实际TDD体验,甚至是已经脱离一线开发的人,越喜欢说“XP是反软件工程的”、“XP不要设计”、“XP让程序员开心,却是项目经理的噩梦”。引用一篇Robert C. MartinAgile Methods – The Bottom Line,专门论述了XP如何为项目管理提供强有力的支持。

  类似Robert C.Martin这样,敏捷阵营的领袖大多仍在参与软件项目的实际编码,所以XP很贴近软件项目的实际需要,例如设计模式、单元测试等。这两天在对质谱鉴定系统进行残暴的支解,各个模块拆得七零八落,但依赖了CppUnit,还是可以有条不紊地重构,又一次体会到TDD的妙处。上来敲感想。再一搜索,呵呵,原来以前写过类似的内容,几乎是重复了

软件工程相关转载三则

  Ai92翻译的这个版本的Martin Fowler的《设计已死?》很不错。其中总结的XP设计技巧是:

  

  • 持续保持代码干净、简单。
  • 重构,使你觉得任何有必要的时候都可以大胆的改进。对模式加深认识:不死搬硬套,要知道该何时用,以及如何逐步引入。
  • 着眼于应付未来变化的设计,知道现在做出的决策可能要过后进行修改。
  • 知道如何将设计传达给必要的人,用代码、图表和最重要的:交谈。

  摘录《可以不当工作狂吗》的一段内容

  “……哈佛商学院的Leslie Perlow,作为人种学者,对多个国家的几支软件工程师团队进行了一项研究。这几个团队在做类似工作时的工作效率几乎一样。但Perlow发现,这些团队工作方式不同,对成员的影响也截然不同。”

  “在印度,工程师们遇到问题时会直接找团队里的其他专家。他们之间相互的承诺关系使每个人的工作时间往往很长,因为每个人都觉得必须让同事找得到自己。”

  “在中国,工程师们工作时很少互相说话。所有的帮助请求都汇总到项目经理那里。这使得每个人都严重依赖项目经理。”

  “在匈牙利……”

  “Perlow说,这三个团队都相信没有其他的工作方式,他们只是按照全球市场的要求来行动。然而印度团队的做法会让人筋疲力尽;中国团队受制于上司;只有匈牙利团队的做法使员工拥有自己的生活……”

  梦想风暴在他的《乱弹设计》里写道:

  “……曾经的我就是一个为技术而技术的人,当一个项目启动的时候,我首先考虑的就是如何展现自己的功力,如何编写优雅的程序,而忽视了根本性的问题:需求。真正让一个软件产生价值的就是需求。少了需求,软件的意义也就荡然无存了。当一个人做事连自己的目标都搞不清楚的时候,不做错事,已经要感谢上天的眷顾了。没有正确的目标,其它的努力只是让自己在未卜之途上越走越远。有许多部影片为我们展示了邪恶科学家的威力,他们不是不努力,只是弄错了方向……”

  “……谈到设计,最好的设计标准还是那条经典的“高内聚,低耦合”。了解了这么多的设计手法,体会那么多的设计原则,到最后,基本上都能归结到这条标准上来。设计的过程是一个分分合合的过程,先是把系统分拆,再把功能相近的东西合并,这样就形成了一个模块,有人叫服务、子系统、类、组件、函数、方面……,都是一回事。设计者需要考虑的就是让(各个模块实现者)怎么去做这个游戏,以便让各人能够独立工作而不致于相互影响,这就需要请出“高内聚,低耦合”作为衡量标准。模块之间的合同就是我们常说的“接口”,它可能是函数调用,可能是参数传递,可能是共享数据,也可能是远程调用。总之,有了合同好办事,谁的问题谁负责……”

软件工程和业绩管理

  管理最终归结到人,所以必然和绩效联系。

  经济学的角度,人是贪婪的;行为学的角度,人是懒惰的。建立体制,确保企业对人力资源的投入和回报成正比,这就是管理。单纯树典型搞运动,要求每个员工阅读《把信送给加西亚》,而不改变工作流程和考核方式,都很表面,甚至被当作愚民政策。

  好的绩效管理不会破坏信任感,而会激发一部分人的成就感,使他们愿意在职责外加倍投入,这些人恰恰是可以重点培养的骨干。

  软件工程实施中,明确的考核倾向至关重要。没有谁完全喜欢规范化的东西,说到底,工程化管理是依靠增大个人工作量换来团队利益。所以需要管理层拿出态度和方案,让团队业绩和实施效果挂上钩。

  当然培训也很重要,软件工程培训的重点,应该是强调现代软件工程的最新进展,让员工忘掉大学教材里的官僚主义,熟悉版本管理工具、自动Build工具、BUG追踪工具、单元测试工具、UML建模工具……