SUMTEC -- There's a thing in my bloglet.

But it's not only one. It's many. It's the same as other things but it exactly likes nothing else...

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

最近在看两本书,一本是敏捷软件开发,另外一本是微软团队的成功之路。两本书都是还没有看完一半,但是都有了不少的体会,觉得自己的思路开阔了不少。

以前总以为做架构师,或者做项目经理一类型的职业,都需要有非常深入的技术知识。后来发现不是这么一回事,这种高级位置上面的职业需要有一种总体的把握能力。正确的讲,并不是不需要深厚的技术知识作为基础,相反,技术知识非常重要,但是处于不同的层面,就有不同的东西需要关注。在架构层面,或者项目层面上,需要关注的实际上并不是技术,而是诸如组织团队、分配资源、管理项目等等。

在这两本书里面我们都可以或多或少的看到背后所关注的“人”的问题,怎么样让人发挥最大的创造力,使团队成功的关键之一。当然大家的创造力必须统一到一个大方向上面,这就是领导者的职责所在。有时候我们会有这么一些经历:上司不赋予你和你的团队以明确的权利和责任,整个项目不关注与用户的沟通,项目进度和想象当中的差别很大,以及团队内部不良情绪在蔓延。

如果你和你领导的团队没有明确的权利与责任,那就比较容易做事缩手缩脚,对于一些明显会出问题的地方没有人愿意指出或者不知道该向谁指出,当真正出现问题的时候没有人能够承担,即使有人承担了,那也会有一种替罪羊的感觉。在这么一种环境里面,每个人都会觉得什么时候倒霉的事情就会落到我的头上了。
如果拥有了明确的权利和责任,还需要用合适的方式去分配。其实自己最清楚自己的实力,如果让大家坐下来进行商讨,也许会得到更满意的结果。每一个人能做什么不能做什么,不应该决定于他所在的位置或者在公司呆得时间的长短,而应该是专业方面的知识水平。如果你把一些其实你没有能力控制好的事情把握在自己的手上,最后有可能倒霉的是自己。

项目最终是否成功,是看你对设计是否满意呢,还是看用户对需求的实现是否满意?明显是后者。你的产品赚不赚钱,看你的用户满不满意,用户则只关心他想要的东西你有没有给他,至于里面的技术细节则是一点都没有兴趣关心,因此开发的时候一定要立足于满足需求这一点。然而过去的软件工程方法,在这方面我看是有缺陷的。里面虽然有需求分析,但是这里的分析一共只进行一次,并且期待着尽量在整个开发阶段封闭需求。之前我的一个Post也说到了,除了需求随着时代的变化会变化之外,客户看到了一个发布之后就可能对以前的需求有了新的了解,也会产生变化。从这个方面来说,封闭需求就是不明智的一件事情。然而封闭需求还会导致一件非常不好的事情,它会让我们轻易的陷入从一开始就把各个细节设计清楚。事实证明,很多时候不要说客户,连我们这些开发人员对于整个东西是什么,而我们却总是对自己的思考能力过于高估,而对想象能力过于低估。最后我们想出来很多很多的功能,但是有好一部分却不不符合需求,此外还会有很多没有用的东西出现。开发的过程需要尽快发布新的原型,让用户去进行实际体验,看看有什么不符合的。其实传统的软件工程学里面也说到,项目越是进行到后面的阶段,修改编码尤其是修改需求变化方面的代码代价就越大,这一句话确实是对的。然而过去的很多方法比如瀑布模型,却企图把需求封闭在一个特定的阶段(需求分析阶段,顶多是到设计阶段),一旦到了编码就不允许对需求甚至设计进行修改。这是一个愚蠢的方法,除非你确实是这一个方面的专家,有着丰富的经验,并且引领着行业的潮流,你说了就算。不幸的是很多时候不是你说了算,而是客户说了算,就算你说你的设计多名优秀,客户说不要那就是不要。封闭需求、设计之后,一旦用户对最终产品不满意,那么实际上还是需要回到需求分析阶段,这个时候代价就非常的大了。所谓的敏捷开发的其中一个目的就是希望让需求变化来的越早越好,减少在开发后期才出现的需求变化。不停地进行迭代,尽量缩短每次发布的周期。在每一次迭代完成之后,让用户去亲身感受一下,可以让你知道这一阶段的设计是否就是客户想要的东西。因此一个项目要成功,和用户进行沟通实际上是很重要的,这种沟通越频密越好。

有人就会说了,我的用户在十万八千里以外,不可能经常来我们这里进行体验。如果说请求对方指派代表是不可行的,那么也需要考虑在项目团队内部设立一个专门进行模拟客户的角色,这个人必须熟悉这一个市场。如果没有人熟悉,那么就专门找一个人来熟悉这方面的工作。这一个角色总得由人来担任,就像编码人这个角色总得由人来担任一样。


如果我们能够真正的从客户这个角度来考虑问题,我们就会发现我们以前的很多设计方法是有问题的。比如说我们会产生一大堆的文档,从细小到如何对数据进行排序的函数开始设计代码,在设计里面为以后可能出现的需求变化留下“钩子”。为什么说这样做有问题?

我们首先看看文档,难道用户需要的是文档吗?需要看看你的FooStory是派生还是引用JokeImplement的设计文档吗?还是TempleteMethod/MVC/Decorate之类的词语在某个文档中出现会让他升官发财?统统都不是!他要的是能够正确运行并且提供他所需要的功能的软件。软件才是中心,不是吗?有人也许会说,UML之类的东西是为了让我们的设计更加清晰。可是这些UML图最终还是要转化为代码的,如果你的代码设计的充分好,就会有比较好的自解释能力,就算什么地方有不太容易理解的地方,在代码里面添加简单的注释基本上都能够解决问题。反过来说,当你的程序因为Bug或者其他原因需要进行调试和修改,你觉得你首先要读的是UML图还是代码呢?代码永远都只有一种解释,但是文档则难免会有二义性存在。思考完这些问题,我得出一个结论:我们应该围着代码转,然后产生文档,而不是围着文档转,然后产生代码。

接下来看看设计的方向。因为我们错误的从一开始就把整个需求确定下来,甚至到了毛细血管的程度,所以我们会不自觉地首先实现最为底层的东西。这个惯性很好解释,因为我们需要编译通过。如果class a里面使用了class b的实例,如果首先写class a,肯定无法立即编译通过。如果我们要一次过完成一个可编译的版本,那么从上面开始写,三天三夜不眠不休都不可能完成。所以我们就从class b开始我们的工作。但是这样却需要等你将整个系统的所有部分(至少是主要部分)都完成了之后,才可能发布一个可以给用户演示的版本,需要的时间通常会非常漫长。如果我们反过来从顶层开始往下写,只要我们设法保证每天都能够产生一个可用版本,那么随时都可以拿出来给用户演示。实际上一些很细节的功能用户一开始并不会很清楚,所以我们也不可能很清楚,一些东西也许并不会出现,另外一些东西也许没有考虑进去,还有一些则并不是你原来想象的那样。如果一开始就埋头做哪些细节的功能,很可能最后会发现,有很多东西其实就是在浪费你的青春。至于怎么进行自上往下的设计,留着以后再讲。

另一个我们比较容易犯的错误,就是留“钩子”。这个错误我也一直在犯,并且总是忍不住会犯。很简单,你的经验告诉你,需求是会变化的,因此需要考虑为以后的需求变化预先进行设计。这是一个非常愚蠢的想法,当我明白这一点之后我简直是无地自容。前面我们已经看到了,在整个开发的过程中,需求就会不断地变化。这种变化就像一串随机序列,根本就无法把握。你以为它会是那样的,甚至可能客户一开始也那样以为,接下来没几天客户机说不是那样的。如果你能够在一开始就能预测这种变化的方向,你就有能力应用瀑布模型,你就可以封闭需求,你就可以简单的面对客户今天说要这个明天说不要那个的情况。事实上明显不是这样的,需求的更改不可能按照你的设想去进行的。如果说今天你要设计的软件的需求,你都不可能预见,那么你凭什么那么自信的认为你知道明天的需求要变成什么?“即使最后发现需求确实不是向着你想的方向发展,那这些代码顶多是没有用,难道还会有害么?”我认为是有害的,因为它影响了你的重构。很多时候我们解决某一类特定的问题可能会有好多的方法,比如我们可以Templete或者Strategy等等,每一种解决方法都有它的侧重点和副作用。假设我们把Templete用在了这些地方,到最后也许我们的需求变化要求我们使用Strategy,那么要从整个设计里面拔除已有的Templete相关的代码将会是痛苦的。实际上问题可能还会更严重,假如你这个Templete是在一个组件里面,拔除这个Templete很可能会对另外一个使用这个组建的系统产生影响,最后你不得不修改另外几个系统,重新deploy。当然,这个也许是极端的情况,但无论如何它肯定会对你未来的修改或者重构造成障碍。

好了,今天只是一个粗略的笔记,详细的内容日后再写,来日方长嘛。本来还想画一些图,让页面更加rich一点,但是已经霸占JGTM的19'一天了,不好意思霸占下去。回到另外一台17'的显示器,就完全没有了画图的激情与欲望了。还是看看书算了……

posted on 2004-09-07 23:57  Sumtec  阅读(2852)  评论(16编辑  收藏  举报