成本、质量与效率

这是一个过程,记录了2009年我的工作总结,具体每篇的发布时间丢失了,放这里自己回顾一下。

(一)

从需求分析,需求用例、变更管理到过程管理,花了两个月时间终于有了比较透彻的想法,最终所有的一切都得落实到成本、质量和效率上面。分析、技术、过程,仅仅不过是可用的武器罢了。

当投身到一个项目之中时,我们只应该有一个目标,那就是赢利。人员的组织带来的是成本的分布及总和的变化,架构及其它设计、过程是质量和持续改进的保障,贯穿在这其中的是效率。

众所周知,很多软件项目都是不赚钱的,赚钱也是通过无偿加班获取。那么,这其中到底有没有一种适当的模式来创造更多的利润呢,我想是有的,并且,在这个市场上,这样的模式将会挽救很多困境中的亏损项目。

传统的CMMI甚至Agile,前者只能简单地拆分和统计过程的成本分布和偏差率,后者事实上是通过改进项目成员的工作思考方式来精化生产,两者都没有揭示出项目内部各种因素的相互影响程度,以及问题的根源在哪里?最合理的改进点又在哪里?

这是一个大的思考方向,接下来第一步,我决定切入项目内部,作一个成本跟踪,然后再设法去改善它的分布以观测总成本的变化和质量效率边际。

关于效率,由于在开发过程中,主要和效率挂勾的是代码编写活动,基于海量的编码经验,我先总结出几条高效原则:

  1. 消灭“代码个性”——一个团队只使用一种风格书写代码——我知道这很难,所以,请使用代码生成器(如 CodeSmith)或安装代码辅助工具(如 ReSharper)。一致的代码风格将使我们可以在一分钟内完成原本可能超过一周的代码返工工作。不用Ctrl+H是笨蛋,不能用Ctrl+H是超级笨蛋。
  2. 保障实现——在开工编码时,应保证让编码者获取到足够实现功能的技术支持。也就是说,不知道怎么去写,那么就不要写,因为你写出来也可能等于没写,把你心情写糟了只是小事,大事是还得耽误测试人员一次回归次数。
  3. 禁止调试,除非万不得已——挂上一个进程,F10、F11一整天,就为了看几个变量的值?得了吧!写一个单元测试在其中Assert.IsNullEmpty,不是十秒钟内就检测出来了吗?!
  4. 使用构建与集成——都什么年代了,还要十个人头挤一盘菜。分拆、构建,然后组装。不需要你保障提交的代码能完美地工作,只需要保障你能够按时提交代码,完工之后,我们再来看它能工作到什么程度。我们是操作源代码,不是捏泥坯;我们可以修正&编译无数次,不是烧出来不好看就只得砸掉。
  5. 即时交流——一个项目中的所有编码者,都应该每三个小时集中交流一次各自的进展情况(重构之前,告诉组员一声会死人?报废别人的工作是可耻的),每天签入/合并一次代码。

(二)

本来关于第二章,这两天想法比较细化的,今天却遭遇三个小deadline,简直把我给整郁闷了,第一个:闷过去了;第二个:蒙过去了;第三个:挺过去了!

三个小时前,我用肯定的语气给同事们说,接下来的这个项目如果失败,一定是败在技术上。没想到三个小时后,我居然已经一知半解了……永远不要低估自己啊。。。

结果关于此系列的想法也给吓跑了一大半。先理个框框。

颠覆工时计划

项目开工之前,传统的做法是,估算工时。根据各个公司的规章制度、用人方式的不同,有“老板拍脑袋”、“项目经理豁客户”、“程序员干瞪眼”几种方式^_^ 不过,事实还是远没有那么的糟糕。比较科学的方法是需求基本确定(80%以上)的三点法估算,需求不太明确的情况下根据代码量估算,等等,由编码者操刀。
好了,现在我说:工时估算,就是项目失败的第一步。因为:\

  1. 需求在这时往往没有明确;
  2. 设计在这时往往没有开始。
    需求&设计才是决定实际工作时间的关键因素。在这两者都没有确定的时候,一个虚假的工时又有何意义呢?

有一个必须接受的事实就是:一个系统的程序员,他真正的工作时间是无法估算的。系统是一个有机的整体,任何一个新功能的加入和修改,如同器官移植一样,手术台上动刀子的结束,并不意味着移植的成功。

所以,我们必须放弃传统的工时估算计划。改为“成本估算计划”(本人独创,如有雷同,巧合之外实属抄袭)。

首先,根据客户的需求紧急程度,与客户协商一个deadline是必须的。请注意这点:根据deadline,增加项目组人员数目是应该的,但人员数目与产出存在着边际效应。根据大多数IT项目管理书籍的看法,超过12~15人的团队会很恐怖。沟通成本、代码独占、意见分歧……等等。最好维持在10人以内。

然后,我们需要制定的是关于这个项目的“赢利目标”,也就是成本估算。按照我的想法,可以分为A、B、C三个档次。A为赢利最高,C为最低,也就是最大能接受的成本开销。

成本大致包括:项目成员的工资、差旅补助、加班补助等人力成本,硬件折旧成本,公司管理费用及杂项支出。

根据这个成本估算,得出项目的计划时间。

接下来要做的就是评估这个时间的科学性,让它与需求数目、架构设计、编码量评估进行对比,如果有超出,至少,我们可以在此刻提前宣布:这个项目很难赢利——然后再想办法与客户进行协商。而不是超期半年之后宣布它已成为“问题项目”。

基于自己的经验和水平,我可以肯定地说,绝大多数项目在经过详尽的分析和设计,在过程中严密控制之后,是可以按期完成的。

那,是不是每次都把赢利目标定为A甚至A+、A++就更好呢?No!我们是受过高等教育的新一代,再去搞“人有多大胆,地有多大产”那一套,就贻笑大方了^_^

首先,两个概念,(我定的),“估算成本”,与“实际成本”,是两回事,最终的成本支出,不是估算成本而是实际成本;并且,“估算成本”越低,“实际成本”可能就越高。

这就牵涉到了标题中的第二个词语:质量。欲知后事如何,且听下回分解嘻嘻~

(三)

不得不说,因为了解了一个新的概念“成本动因分析法”,这系列的想法有一部分被抛弃,并且思维处于卡壳状态。在开始我试图使用最基本的微观经济学原理来阐述,现在发现在生产质量管理中的一些方法与软件项目管理有所交叉,而我对此的知识是完全地缺乏。

与此同时,一组敏捷专家也正在日本考察丰田汽车生产,想从中发掘出一些精益生产模式应用到软件开发之中,可惜,这些专家带回来的第一组消息都是些废话:日本精益实施情况考察

接下来需要花费一些时间学习一些生产作业方面的知识,当然,不会往这方面引得太深入,第一这是希望分享给大多数都是技术出身的项目管理者的,第二我也不专业,唯恐误导,阅读这方面的文档只是因为一般的程序员不会去读,也没有联系起来的意识,所以,引用+解释+对比权当参考。

基本上我希望在这系列文章中思考出一个形状的东西包括:

  1. 技术选择对成本、效率的影响
  2. 质量的标准
  3. 质量与成本的合理比例
  4. 重复操作对效率的利与弊
    计划花上一年的时间来研究这些问题,最好在业余时间开发一套软件来跟踪数据。首先,我想通过手上的一个新项目的记录,来获取一些成功或失败的经验。

这是一个 Wap 2.0 站点开发项目,上周拿到需求,很简单,但因为从来没做过此类项目,预计技术风险很大,并且,交付日期是7.30(7.3国内才有第一个 Wap 2.0 站点发布),上周四花了四个小时看资料,确定了基础开发技术为XHtml + .NET Framework 3.5,很侥幸因为多看了些资料,否则差一点选择了大家都不熟悉的 WML。随后与几个成员分享了 XHtml 语言特殊规范,比较简单,算是可以上手了。

说一下为什么选择 XHtml。因为 XHtml 与 HTML 相似,而 WML 有自己的标识符规则。虽然都比较简单能够马上上手,但里面关键的一点在于:初学和熟练是两回事。这体现在1000行 XHtml 代码因为我对 HTML 完全熟练所以错误为零,而初学的 WML 却可能出现“虽然只有个位数的错误但因为我不精通所以得花上数倍写代码的时间去排错”。这就是区别。

今天想到 GPRS 的速度,站点肯定不可能使用 ORM 不说,还必须有 Page Cache 支持才行,这一块我们也不太熟(其实我们都没有 Web 站点开发的经验),这是当前最大的一个风险。

成本,不说了,五个人一月薪水总和为主,不会出差,只要按期完成,就能保证赢利。所以,目标很简单,就是争取7.30交付。

质量,因为客户对质量要求不高(只图快,即使有些 Bugs 也可以容忍),那我们可以以“保障正常数据通过测试”为达到质量要求。前端的站点则需要保证很高的响应速度和适当的分辨率,这些是客户事前完全不能想到的,但事后绝对会崩溃的。需要引入压力测试,这我们以前也没有做过,常用的浏览器中只有 Opera 能访问 Wap 2.0 站点,手机模拟器还不知道如何做压力测试。这是第二个风险。

同事希望这能成为我们组第一个赢利的项目,目前我能想到最快的方式就是使用开源 CMS 系统改改直接拿来当后台……明天需求评审之后再说吧……

(四)

挂了三个项目,太多工作要做了,实在没空有什么想法。感慨一下今天的经历:

因为项目的缘故去MS面试,对方问我:“你们至今的项目都是亏损,你打算怎么改善?”我就照前段时间的想法谈了。

什么样的人,做什么样的事;信任,建立良好的团队关系,非常重要。我近段时间工作状态也不是很好,得检讨一下。

面完下来后和老Ben等人嗑了一通瓜子,又谈了我的想法,老Ben又开始唠叨“框架框架”,又开始怨我,然后竟然与Linda同学一起欢呼我天朝近期的海外投资,大有天朝人民真的站起来了之兴奋感,(很遗憾很快就被我严厉打击,唉,我真是太不爱国了)

一切都是模模糊糊的。有些想法是不是太超前太理想化了,都得实际检验才行。希望 7.30 我可以把这个项目交付出来吧。

God bless!(哈哈,写完这句想起,年初的时候Jeff与Ben两个家伙去文殊院烧香,现在连我也要喊基督了,哈哈哈)

最后竟然忘了记录项目的进度了,因为我挂的项目有点多,今天才开始做设计,组员们也卡在我这边,等着架构和数据库出来。SO,今天加班。下午和Ben讨论的时候,问了Ben在MS的其它项目组是怎么做的?Ben说他们使用的DAO-富血模型。这基本上和我的想法一样,即Domain Model(以前我们使用的是NET Tier,贫血模型即Table Model,本来当初我设计的Domain Model,因为没有ActiveRecord的开发经验,最后Jobs使用NET Tier解决了DAO层设计师),3月份做一个基础项目时我坚持使用ActiveRecord,感觉效果还不错,大家也马上上手了。这次的WAP项目,依然采用ActiveRecord,然后在CodePlex上找了一个Utilities程序集,基本上满足了我们所有Common操作。明天准备举行一次设计会议,给大家介绍ActiveRecord的关联(只有一名新来的应届生未使用过),所有的Domain Model代码使用我写的CodeSmith模板一次全部生成,省时,省力!

把CodeSmith的ActiveRecord模板share给大家,继续赶工去了:

(五)

至目前为止我们都处于实际进度与计划进度提前一天的工作状态。昨天上午开了一次设计会议10:00~11:30,下午花了20分钟进行了一个方案搭建的小会,随后完成了Domain Model的创建,通过了所有的构建和初始化测试,然后把4月份写的一个权限框架加进来时发现了问题,动态代理产生的新类,在ActiveRecord的NHibernate映射中提示找不到新类的名称。只得放弃AOP的框架。

所有的数据访问都创建了测试,所以不用在UI上进行测试了,这一块省了最多的时间。

今天上午直接找同事谈了新的UI设计方案,将他的工作减少到只做一个控件。另一个同事已经开始做模块了。
另外想说的是:从用户的角度出发,永远是对的;从程序员的角度出发,在开发周期内,都不一定是对的。
太忙了,有些事情到交付后再来总结。

(六)

至今为止,这个项目主要是卡在我手上。我的事情太多了。想把手上的工作分出去,遇到以下问题:

今天去看一个同事的代码,他对DAO不熟,还在Page上写数据访问,让我十分郁闷。准备明天花半个小时让他熟悉EA、CodeSmith,然后DAO的生成和修改可以让他做。

另一个同事虽然才毕业(88年12月生的,Faint哦),但是基础好多了,准备让他熟悉ActiveRecord,因为他手上的工作已经做完了,接下来就协助进行我们这边的Domain层的调试和单元测试编写了。哈哈,我正好是这个小兄弟的导师,以后会是我们组的一主力哦^O^

这样会快很多。

另外我们会举行Development Meeting,集中讨论开发中遇到的技术问题,并且使用统一的控件——这样解决一个问题,就解决了所有的问题。

最近事情一堆一堆的,感情上也有了新的目标,慢慢来吧。

(七)

这周有很多突破性的想法,实在没时间写。先列个提纲吧:

  1. 关于积累——很多时候项目组谈到积累就是指有源代码的框架或类库,其实,积累应该是各种开发的技术细节及技术选型。这个项目结束后我会制定一套覆盖所有技术细节和选择的开发指南,为每个程序员评价技术成熟度。以后的项目,就照着这个指南去勾选最成熟的技术,新的选择引入时,先在指南上加入,再评价。
  2. 领域模型的巨大优势——KAO,连抽象工厂都可以通过模型映射实现,华丽啊~~~有空更新到我那个技术博客上去。
  3. 约束需求的是测试——目前测试人员的观念还没转换过来,以为我在给他们找麻烦。今天给我报Bug说和需求不符,我问Test Case里写清楚了吗,如果是这样的话你为什么不写到Test Case里呢?他终于明白是怎么回事了。
    新看到的一篇文章,觉得这三位大大的话真是无力,也许这标志着,我更加的脚踏实地了。

于丹:40岁,我想明白一件事

送给三位大大的话,其实理想,就是成为被自己热爱的人。

(八)

今天早上我被彻彻底底地打击了!!!!唉!这确实不是我的问题!!太有戏剧性了!!!

(九)

真是天有不测风云,眼见着这个项目加点劲就可以按期交付了,结果因为一点非技术原因,公司宣布必须停止~~MMD,又长见识了

昨天中午很愤然地给死党打了一个小时的长途,死党正在家里等生孩子,说是个儿子~~然后又YY以后来成都工作的愉快团聚~唉,快一点过来吧~

唯一的好处就是现在手上只挂两个项目了。那个延期七个月的项目客户又有了新“想法”,今天和F讨论了一下,是关于工作流的,和我去年七月的想法完全一样,就是,客户希望在运行时刻改变流程的状态(原始需求是“到一定的时间自动结束”,F认为有些流程是需要选择下一个办理人的,所以与客户确定为“已经排定下一步办理人的流程可以设置自动结束时间”)。

今天我们又继续分析了一下,发现这个应该不会很简单。“时间上的自动结束”只是一个任务,参见我以前写的目标导向设计,客户的真实“目标”是“流程自动化”,时间只是“自动化的条件之一”,之所以提出时间,是因为他们目前只想到了时间——也就是说,就算我们今天完成了时间上的自动结束,明天他们也会提出以其它方式来结束流程,因为在未来他们又想到了新的方式,然后,我们又需要在成百上千个文件中修改我们的代码。

说到这里,大家不是要说,ops,难道我们就这样被客户牵着鼻子走吗?当然不是。只要分析出“有条件的自动结束”,并提供多条件结束,那么我们的程序就能轻易地适应未来的改变了。

进一步分析,“自动结束”也只是一个任务,除非整个业务活动完全结束,它的结束只是为下一步骤的开始做铺设。所以,这里隐含的目标是“让下一个办理人在条件许可的情况下开始工作”。那么,我们就认为“结束”这个动作事实上是不需要的(也正是因为如此,客户提出“自动结束”而不是“自动按结束按钮”),我们也不需要设计一个“结束功能”,而是,直接启动下一个办理人的工作入口。

造就这一系列问题的主要原因是这个工作入口(在工作流里称之为待办事项 Work Item)的创建逻辑是“上一步步骤结束之后”。

回过头来看看对象世界与真实世界的差异吧。对象世界里,在这个时刻,这个工作对象才能够参与到这个工作流程中来,事实上,他在真实世界中是一直存在的。假如没有工作流程序,办理请求人在Nn不在的时候,如果默认的规章告诉他可以直接去找下一个人Nn+1,这个流程依然是有效的,那么他就会去找Nn+1这个人把事情处理了,以此类推。然而,在对象的世界里,因为Nn这个人不存在,整个流程已经卡住在了Nn,事情再也无法继续了。

我的想法是,在整个流程发起时,就必须承认N系列的所有的人的“存在性”,这些待办事项都将被创建,然后,有一个“激活”的自动功能。

现在就很简单了,所谓的“自动结束上一步骤”就已经变为了“自动激活下一步骤”,只要在当前应处理人登录时检查他的待办事项是否应该激活,这些条件有可能是时间,也有可能是其它什么信息(只需要提供一个激活接口,就解决了)。

这样做的好处时,解决了我们不知道在何时去“结束”一个步骤。对工作流熟悉的朋友的会很快明白这个问题所在,不太熟悉的可以再看看:

  1. 在目前的所有工作流中,驱动因素是人,人的操作,驱动着流程的进行;
  2. 一旦某个流程无法继续(非系统故障),一定是某个点上的人离开了这个系统;
  3. 那么,如何把已经失去驱动因素的流程驱动起来呢?
    大部分的解决办法都是使用第三方的自动程序去定期询问,然后将它结束掉。这样效率很差,并且不同步。一旦下一个待办人在这个轮询程序的间隔期恰好需要工作了,那么他不得不等待,更多的实际情况时,他们根本就不知道有这样一个轮询程序的存在,所以,他们就彻底地迷惑了:时间到了,条件也满足了,为什么它无法点击(客户一般说:按钮是灰掉的^O^)?

直接把这个人的动作做为激活的因子,事情就全部解决了。你不进入系统性,就不激活,你进入了,就证明可以进行操作,那么就给你在这一刻创建操作所需的所有条件。

其实不是很想去做工作流相关的系统。只是把去年的想法总结了一下。

PS:网上看到的新的好文,又发现一个大牛叫胡健

建造无错软件:契约式设计引论

项目回顾:一个开发人员的观察与思考

新方法学(Martin Flower写的,敏捷的起源)

(十)

三天换了三个项目,这速度简直能把人给折腾疯。没想到这么快就把MS的项目接过来了,过去人家直接一句话“你们开始确定需求吧”就开工……这个效率……压力狂大,MS的一个EM亲自带项目,自称“十年来带项目从未出过问题,这次别给我翻了”。

关于成本控制,今天也学了不少,预算确定,时间确定,还可以在需求范围内控制总成本的支出——从MS的EM那学来的。接下来到八月第二周的主要任务就是确定需求范围。

今天给MS提出要做需求管理和变更管理,他们同意了,具体的,我希望用User Story的方式来进行需求描述。

现在狂疲惫,眼皮直打架。忙着写交接文档,手上前三个项目都积累了不少技术点,争取也能尽快整理出来——在这方面我觉得我有点强迫症,非笔记本、非Blog,好像我就下不了笔了…………应该是下不了键盘~
Tracy推荐的一款笔记本,Acer Timeline轻薄本,13.3英寸,1.6Kg,可持续导航8小时

(十一)

现在这个系列差不多是我的工作日记了,继续。

需求比我想象中要简单一些,Microsoft在我头上安排了一名Project Manager和一名Architect,所以我基本上只需要与他们确认需求和架构在旧系统PMS改造的可行性就OK了。

今天主要做的工作是理清了PMS(Project Management System)在新需求中与其它现有系统的关系。作为项目管理系统,去年做PMS最初是把所有的项目建设相关全部拉通,后来出了很多问题,一些做过的东西被砍掉,放到其它系统中,对我们形成了很大的浪费。所以,这次必须确定新需求的系统边界。

上午与PM开了个需求小会,因为去年离职的缘故,对PMS很多东西的现状我是不太清楚的,然后我发现了一个问题:在这边的三人维护团队只有一个同事清楚所有的需求变更,另外一名测试对现有系统的功能了解得不是很全面,还有一名开发人员现在几乎不能承担任何任务。所以,在那个同事忙的情况下,我们的讨论进展得很缓慢。于是我让测试参加了我们的需求讨论——我的原则是,验证功能完成的不是Use Case,而是Test Case。

由于不能确定很多细节的东西,这次我们只把所有新需求涉及到的系统理清了,并且与相关的负责人进行了沟通,与工程公文的负责人沟通时,才了解到当初不少流程被砍掉的原因:凡是具备法律效用的流程,必须形成公文(转公司领导审批),所以,子系统和部门级的系统是无权处理的,故砍掉——接下来我们就需要确认哪些流程会是法律效用的了,这可以避免后期又被砍掉……(结果是,需要访问的客户今天不在)。

简单说下这次的项目需求:我们以前的PMS仅提供了简单的项目流程管理和数据采集,现在,客户在业务上架设在项目管理之上的计划部门需要从资本的角度对整个项目进行掌控,比如所有项目的预算控制、变更,实际进度追踪,物流明细……等,目前最复杂的就在于,同样的预算变更操作会根据项目的实际进度深入造成几何级数的业务&数据影响,比如说已签定金额的承包合同,未到货的采购合同等等~~暂时还没有想到好的办法来解决。

下午没什么事,研究了一下Mock测试技术,将Type Mock、Rhino Mock、Moq都下载了一份,写了基于Moq 3的测试,发现它实在太有用了,尤其是前期接口开发时,创建的模拟对象能够完成我们实际的操作测试,从而在接口设计期间就能发现错误。Mock可以广泛应用在数据库替代和工作流,希望它能给这个项目带来效率。

Moq,采用Lambda语法,相当的“简略”
http://code.google.com/p/moq/

(十二)

尝试使用用户故事(User Story)的方式撰写需求描述……用户故事的定义是:

  • a written description of the story used for planning and as a
    reminder
  • conversations about the story that serve to flesh out the
    details of the story
  • tests that convey and document details and that can be used to
    determine when a story is complete
    对于每一个用户故事,包括三个方面:
  1. 描述:对用户所需功能的描述,谁会使用,如何使用;
  2. 讨论:关于这个功能,与用户、分析师、团队成员的讨论记录;
  3. 确认:确定这个功能的验收标准,这个标准是让用户确定所需功能已经完成。
    每个用户故事都是独立、不依赖的。

第三点很重要,我们不但要明白用户的需求,“该做些什么”,还要再次确认一下“功能完成后,目标满足了吗?”

比如说这次的新需求,对进行项目额度预警、设计变更、请购到货明细查看这些功能实现之后,“项目资本控制”这一总体目标是否已达成?

不要惧怕用户会因为询问而(期望大增)将需求成倍的增加,我们可以从当前可行性的角度出发去拒绝一些需求点,或者将其延后到下一期开发计划中。做的事多了,整个工程都会延期,这是双方都明白并且不愿意看到的事情。重要的是保证所做的功能都是必须的、围绕着用户目标、不可替代的。

有意思的是我的工作被分割成两个方面:一方面是实际意义的、为团队开发提供支持的需求分析文档,另一方面是形式主义的、为客户讲解的幻灯片。

组里的一个同事Rusty每天都会有让大家神经崩溃的“事件”发生,以至于今天我把MSN签名换成了“Rusty是个人才,演郭靖的人才”。原因如下:

1.Rusty今天中午吃了一份Ben点的“青瓜皮蛋”,然后说:这不是黄瓜吗?它还有一个名字叫青瓜?

2.Rusty说:毛肚不是海产吗?

3.Rusty说:银耳不是黑色的吗?为什么这个银耳是白色的呢?

Ben:你到底是富家子弟还是官宦子弟?!

我:晋惠帝?

Ben:平常多读点书好不?

Rusty:我不喜欢读,听你们说挺好的。

Linda:都是常识啊常识!

Jerry:(无语向苍天)

Rusty:遇到事情不说,显得很高深,我明白了!

我现在是彻彻底底地折服于“个体的差异”了。今天上午我就花了一个小时给这位“郭靖”讲解了一下旧系统和新需求……

郭靖:我就是想听这个。

,
© 2018 Silent River All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero