软件架构引言之项目管理的问题(转)
软件架构引言之项目管理的问题
很多朋友都有过或者正在管理一个或者多个软件项目,那么我的文章就从这个问题开始:如果单纯从表象来说,软件项目管理过程中暴露的最大问题是什么?
不同的人的会有不同的答案,但是大致这样的答案我想大部分人都是会认可的,那就是“进度拖延”。进度拖延当然是表象之一了,其他诸如质量不过关、功能不完整等等,我觉得都是和进度拖延密切相关的。很多项目经理都想去做那些认为是十分必要的事情,比如计划、测试等,但是“没有时间”。为什么会没有时间?等到项目总结的时候,我们总会罗列出一大堆的理由试图来说服自己,说服公司甚至说服客户。但是如果限定项目经理只从自己身上找原因的话,我想问题就不难找了。
这里,我用“丰田”的“五次为什么”方法来问这个问题,以及我觉得可能的回答:
一、为什么项目进度会拖延?因为没有按照项目计划进行!
二、为什么不按照项目计划执行?因为进度总会有拖延,缓冲时间总会被用光。
三、为什么在计划时候不规划得更细更贴近现实一些呢?再细也总有额外的工作出现。
四、为什么不充分评估每一个工作,让预料之外的工作尽可能少呢?因为确实无法评估下去了,很多认为是原子级的工作都会产生出各种问题。
五、没有可以参考的其他项目的项目计划吗?因为两个项目的不同点太多,很难重用。
问到这里,我想一般项目的核心问题也就显露在我们的面前。现在先不去谈论这个问题,我们用几个简单的例子让他更生动一些。
我们用一个非软件的事情举例,让大家为这个例子作一个详细的项目计划并评估出最精确的时间。
例子1:请大家评估各自把我的这篇文章重新打一遍的时间。
这个例子最简单了,拿我自己来说,我打字速度为每分钟30个汉字,所以这篇文章重新打一遍的时间就是文章的总字数3000/30=100分钟。加上中间休息的时间,最多就是120分钟。
答案相当准确,我想也不会有太多人有异议,但是下一个例子可能就有些不一样了。
例子2:请大家解开下列的方程式:x2+px+q=0, p=2, q=1
初中的方程式阿,但是很多人可能忘记它的通用求解公式了,不过我们假设大家都知道这个求解公式:-p/2±sqrt(p2/4-q)。评估时间的时候我们首先要知道我们打开计算器的时间,输入数据的时间,抄录结果,并且为了保证计算准确,我们需要进行验算。嗯,这样估算时间的权威性恐怕不如例子1那样令人信服了,而且我们经常需要因为算错而重新计算,超时恐怕很难会避免。
例子3:请大家按照我的引言,结合自己的项目实践,重新写一篇吧。
嚯!如果谁能准确估算这个时间,就应该是高手了。看看我们为了完成例子3需要我们作多少事情吧:制定写作提纲,勾画写作内容,评估打字速度和每一个内容的量…依我看,不用计算了,计算再多,这个工作的进度依然会被拖延。
这三个例子有区别吗?当然有!例子1的估算方法大家都掌握,而且执行过程中的变数最少,因为并不需要我们去做任何的探索过程(猜某个字的五笔字型不算,至少我用微软拼音)。例子2的不同点是解题的方法需要外部因素的介入,而且这个技术并不是每个人都掌握(或者记得),最重要的特点是每一个步骤我们都需要去估算它完成所需要的时间,如果我们已经计算过一次了,当然第二次就会估算的更准确一些。可是现实生活中的项目很少会给你机会重新做一遍。当你完成项目之后,跟这个特定项目相关的各种方法也就失去了它的作用,它唯一的价值就是潜入你的记忆中,成为所谓的“项目经验”,而这个“经验”也常常会在下一个项目水土不服。相比而言,例子2好歹是一些看得见摸得着的动作,评估起来也会有一点依据,而例子3则几乎是一个纯粹的大脑运动,要让大家凭空组装成一篇好看的文章,我看这个进度要估算也太难了,谁知道为了一个内容,我们要反复推敲甚至发呆多少时间呢?!
我们把话题拉回到篇首的五次为什么上来。软件项目甚至其他项目能够按时完成的最主要一点就是要做好“计划”,能否规划一个符合实际的项目计划,是项目成败最大的晴雨表。
要让项目计划贴近现实,首先我们需要把项目中所有的工作都罗列出来,然后把每一个步骤地工作进行细分,以致细分到“原子级”,也就是不能再分的程度,从软件项目来看,就是分到“文件”,分到“类”甚至分到“函数”级别。然后对这些“原子级别”的工作进行评估时间,累计综合,最后乘上一个系数(一般是2),就是最终项目所要花费的时间了
说起来容易,做起来难!光是要求把工作细分到原子级,就已经足以让一大批项目经理当场晕倒了。
我们再回来看例子2,如果解题的人忘记了这个求解的公式的话,前面估算的进度是否需要调整呢?回答是肯定的。这样的时间计算就需要考虑寻找资料的时间,只要找到公式,计算出结果就不是问题了,而找公式所花费的时间,在有通畅的网络连接情况下,包括网络搜索、询问同事等等方法,一个小时足矣!
如果说光是找一个公式就需要额外的一个小时的话,把例子2的题目修改成计算“傅立叶”
变换(非编程计算)又需要多少时间呢?显然跟解二元一次方程又不是一个数量级的工作了,我们除了寻找资料之外,大部分人还需要学习,没有高等数学基础的人恐怕更需要加入“研究”了。
从例子2就可以总结出如下几个现象:工作与工作之间可以有层次关系的,一个看似很简单的工作,很可能会隐含着巨大的工作量,在某些先决条件没有或者准备不足的情况下尤其如此。要准确估算一个工作所用的时间,首先我们就要把“折叠”起来的“工作树”尽可能完全“展开”,其次就必须要遏制工作中的“学习”、“研究”甚至“查询搜索”的工作量。总之,在实际项目开展的时候,就要尽可能让所有的工作都是单纯的,可以预测的,并且尽可能排除那些不可控、不可靠的因素。
换句话说,项目的每一个工作与时间的关系都必须是“线性”的。如果实在不能排除“非线性”的工作,也必须在“可控”的范围内,项目内部不允许有“不可控”的“非线性”因素存在。
一句话: 脑筋动得越多,事情做得越慢!
到底项目中究竟有多少因素是属于“不可控”呢?哪些又是属于“可控”的?哪些属于“线性”因素?要回答这个问题,我们首先来看一下我们目前的软件开发方式和流程吧:
(一)接单签订合同
(二)需求调研、分析
(三)架构设计、概要设计
(四)详细设计
(五)编码、测试
(六)交付、维护
大致六个步骤,其中三四五是和我们谈得开发过程相关联(其他部分我会在以后的系列文章中讨论)。首先我们看第三点和第四点,他们统称为“设计”,参考文献2中给出的“设计”阶段的目标是解决四方面的问题:数据结构,软件体系结构,过程细节,接口性质。
有经验的读者我想已经看出来了,传统的“设计”所解决的问题,有相当一部分应该归纳为现在的“架构”范围内。软件架构涉及的范围主要包括如下:
(一)应用程序的层次划分(比如界面层,存储层等),
(二)部分应用程序模块的划分(比如初始化模块,配置模块,权限模块等),
(三)部分应用程序模块的实现(权限、用户、组织机构管理等),
(四)函数库的实现,
(五)各模块、层之间的相互关系和通讯机制,
(六)相关的部分数据结构定义。
如此可见,上文中的第三和第四点最重要和最基础的工作基本就在“架构”范围内,剩下的工作,基本就是跟具体业务相关的了。
在上文的三个“xx设计”中,架构设计的时间最难控制和估算,概要设计和详细设计因为就是直接从需求条目演化而来,而且容易细化(以后我会有文章专门讨论),所以虽然也是属于“设计”这种“非线性”工作,但是“可控性”要比“架构”强很多。从个人的项目维护经验来看,维护过程中产生的问题,有相当一部分是因为用户需求突破了原先架构的能力所致,而正是这种问题,才是拖延时间最长,引起客户反映最强烈,也是维护人员最痛苦最头痛的问题。因此,“架构设计”我把它归类到“非线性”工作中,而且是“难点”工作。
我看到很多的公司软件部门都叫做“研发部”,用英文说就是research and development的部门,但是我很少看到有公司把research和development分开做两个部门的。这有什么关系呢?从上文我们可以看到,研究是一种非常耗费资源的工作,而且风险(尤其是技术风险)很大,很可能因为一个小技术难题不能突破而导致整个架构推翻重来,而开发的风险则要小得多,可控得多;另外一个大的区别就是研究并不直接创造价值,而开发则跟公司的收入密切相关。基于这两个理由,就足够把“研究”和“开发”完全分开成两个部门了。其他当然还有许多的区别,比如考核方式等。
分开之后的工作如何分配?很简单,就是把“软件架构”和其他有难度的“非线性”工作统统交给高手云集的“研究”部门去做;具体项目相关的业务和实现(“线性”的工作)交由“开发”部门去做,因为他们对技术要求不高,而且成本较低。说到这里,我是不是在主张每一个公司都需要专人去“研究”技术呢?恰恰相反,我主张大部分公司都不需要设立“研究”部门,至少大部分公司不要去研制甚至试图研制所谓“自己的”软件架构。因为软件架构相比具体业务有一定的独立性,并没有一种“特别适合”于某类业务的“软件架构”存在,即使有,它也是应该经过N个项目的M年考验之后才会出现(N*M>10年)。我相信SAP会有这样的架构,但是国内公司基本不会有(也许有,但是请大家理解我的怀疑)。现在市面上有很多开源的架构存在,选一个吧,然后去培训你的员工,不断地培训,指导他们能够熟练地将这个架构应用到项目中去为止,即使这样,你的总花费也还远远小于请一个“高手”开发一个失败架构的投入。
如何来选择一个现成的架构已经不在文章讨论范围之内了,因为我接下来要谈的是“如何开发一个自己的架构”,不过也不用慌,如果你的开发语言是java的话,那么恭喜你,很多好用的开源架构都是java的,比如spring MVC,struts/webwork,tapestry;如果你用的是.net平台,那么微软已经帮你做了一个浅层的封装,或者干脆用.net的petshop或者Duwamish的架构就可以了