代码改变世界

OOA&D实践之路——真实案例解析OO理论与实践(三、降低风险)

2008-12-11 07:32  T2噬菌体  阅读(5692)  评论(16编辑  收藏  举报

查看本系列全部文章:
《OOA&D实践之路——真实案例解析OO理论与实践》索引贴

风险无处不在
      在上一篇文章中,我们写出了一张特性列表。然后是不是就可以做需求分析了?很遗憾,还不可以,我们仍有许多工作要做。拿到特性列表后第一件事,就是要尽量降低风险。这里先不长篇大论风险如何如何,我们先做,从做的过程中体会降低风险的涵义。

DRY
      这里,首先要引入一个OO原则——DRY。

      DRY原则,全称Don't Repeat Yourself,指:在系统中,每一个信息或行为片段应该仅仅存在一份,且存在于合适的地方。

      对于这个原则,很多朋友将其理解为“不要出现重复的代码”,这是很片面的理解。其实,OO本身并不是仅仅关于如何写出优秀的代码,而是关于如何开发出优秀的软件。所以,很多OO原则并不是仅仅代码层面的原则,而是可以应用于整个开发过程的。下面来着重看看这个原则的深层意义,以及讨论其在降低风险中的应用。

如何利用DRY降低风险
      在所有的开发风险中,有一种风险,是由于同一个信息或行为片段分散于系统的不同地方,从而导致重复劳动,并且给修改和维护造成隐患。
      下面,分别通过例子来描述两种不良后果。
      1.重复劳动
      例如,在特性列表中,如果两个特性本身应该是一个特性,但被误认为是两个不同特性。那么所有基于特性的分析和设计都存在重复劳动,即对同一个特性,做了两遍分析和设计,直到发现重复为止。这个代价是巨大的。
      2.修改和维护隐患
      例如某一代码段完全相似,但是出现在程序的诸多地方。这些相似的代码段一定是完成完全相同的功能,于是有着“同生同灭”的特点,即如果某段代码要修改,一般来说所有这段代码的重复代码都要修改。这就给维护带来很大隐患。

      DRY原则正是针对这种风险的一个解决方案。关于DRY在代码中的应用,暂且放下,这里只看它在特性列表整理中的应用。显然,根据DRY原则,要求特性列表中的特性不能具有重复,那么我们再仔细看看我们的特性列表:

      1.可以将各种原料信息发布到系统上
      2.加盟商和连锁店可以通过系统在线定料
      3.加盟商和连锁店通过网络进行注册,总店负责人审核后才可以正式使用系统
      4.系统需要一个管理员,可以对系统进行管理
      5.使用购物车功能进行网上定料
      6.定料完成后生成定料单,并可以打印

      仔细检查,不难发现2和5其实是在描述一个特性,于是我们将2和5合并成一个新的特性:加盟商和连锁店可以使用购物车功能在线定料。另外,可以看出,“总店负责人”和“管理员”其实是一个概念。整理完后,得到如下新特性列表:

      1.可以将各种原料信息发布到系统上
      2.加盟商和连锁店可以使用购物车功能在线定料
      3.加盟商和连锁店通过网络进行注册,管理员审核后才可以正式使用系统
      4.系统需要一个管理员,可以对系统进行管理
      5.定料完成后生成定料单,并可以打印

      再仔细检查,已经没有重复特性。这样,我们就应用DRY原则规避了第一种风险:重复劳动的风险。下面给这种风险下一个定义:
      重复劳动风险——指由于重复特性的存在,导致对同一特性进行了一遍以上的分析设计过程。最终导致资源浪费,开发效率降低,可能导致无法按时交付。

知之为知之 不知为不知
      在使用DRY整理完特性列表后,下一步就是要规避第二种风险:概念模糊。

      概念模糊风险——指由于开发人员对于某一领域知识不熟悉,而将某一个概念想当然,继而根据这个想当然的结果进行分析设计。如果其想法错误,则会导致系统无法正常使用或无法完成业务既定目的,从而导致返工或项目失败。

      很明显,一般来说开发人员并不是业务专家。所以对于领域业务不熟悉是很正常的,作为一个合格开发人员,应该谨遵孔老夫子“知之为知之,不知为不知”这一教诲,谨慎负责对待不熟悉的概念,而不能从字面臆想。正确的做法是,首先审视特性列表,对于不熟悉或拿不准的概念,去请教领域专家或客户。下面继续以我们的项目为例。
      经过对特性列表的分析,我们找出以下疑问或模糊概念:
      1.原料(都是什么原料,需要分类么?)
      2.加盟商和连锁店(两者有什么区别?定料业务流程一样么?)
      带着着两个疑问,我们再次拜访了客户。具体交谈就不说了,最后我们得到了如下结果。
      1.原料主要就是些炸粉、调料之类的配方需要保密的烹饪原料,没有太特别的,不需分类。
      2.加盟商和连锁店不是一个概念,加盟商直属总公司,连锁店可能直属总公司也可能直属某加盟商。加盟商和直属总公司的连锁店直接向总公司定料,不直属的的连锁店向相应加盟商领取原料。连锁店按原价定料,加盟商按照等级分为5级,每级折扣不同。
      经过以上一番了解,我们基本把模糊概念搞清楚了,并且经过这么一了解,我们的特性列表随之改变:

      1.可以将各种原料信息发布到系统上
      2.加盟商和连锁店可以使用购物车功能在线定料
      3.加盟商和连锁店通过网络进行注册,管理员审核后才可以正式使用系统
      4.系统需要一个管理员,可以对系统进行管理
      5.定料完成后生成定料单,并可以打印
      6.直属连锁店按原价定料,加盟商按照等级分为5级,每级折扣不同

      我们认为加盟商级别和折扣是很重要的特性,于是把它加到了特性列表里。

保证我们能够实现
      上面我们已经避免了两种风险。现在再来看一种风险。举个例子,如果一个建筑设计师,设计了一座新型别墅,其中有一条特性是:院子里有一个季节调节装置,可以随意将院子里的季节调节为春夏秋冬中任意一个季节。你们认为这个特性怎么样?很酷的创意对不对?但是如果你是别墅的客户,你会这么想?我想你不会和设计师一起为这个非常酷的特性而激动,你会首先问设计师要怎么实现这个功能。没错,可以调节季节的院子是很棒,可以不要忘了,最终我们的别墅是要建筑在实际中的,而实际总会有诸多约束不能让每一个想法变成现实。
      同上。无论我们设计的东西多么天花乱坠,最终都是要编码实现的。所以,我们要保证所有的特性可以在编码层级上有解决方案。即使我们不能马上知道精确的解决方案,但也要大体知道怎么实现。由此引出了第三种风险:

      实现能力风险——指由于某项特性不能由具体技术解决带来的风险。这种风险包括两个层面,第一是现有技术完全解决不了。第二是由于开发团队没有解决方案。这种风险可能导致项目延期甚至失败。

      要规避这种风险,就要逐一审查我们的特性是否可以在现有技术范围内解决。仔细审查后,第一个层面应该是没有问题,所有这6种特性都可以在现有技术内解决。但是对于特性2,我们存在一定问题。因为当时我们都没有设计购物车的经验,一下子不知购物车是如何实现的。
      为了解决这个问题,要做如下工作。这里要注意,我们在这里可能讨论了很多细节,但是我们要避免提前进入细节。所以,这里讨论的所有细节并不是要进行分析或设计,而仅仅是通过头脑风暴的方式大约有个谱。这个“谱”往往和最终的实现有很大不同,但是至少我们知道这个特性通过某种方式可以实现。
      在遇到这种风险时,首先要做的是查找相关资料。在查找了一些资料后,我们了解到购物车一般分为Session实现方式和数据库实现方式。这两种方式特点不同,前者支持未登录购物,确不能保存客户购物信息。而后一种又必须登录后才能购物。这里涉及到客户的利益,所以要由客户决定。
      于是,我们询问了客户,得到的答复是“未登录时要可以定料,而且也要保持定料信息。”这句话有点模糊,但大体可以知道客户的意思,于是我们改写成如下一段话“未登录的用户可以使用购物车,但不能下定料单,登录后才可下单。登录用户可以保持购物车中信息。”我们拿给客户看,并进行了一定描述,客户认同了这个决策。
      这个确定后,我们就要讨论一下具体解决方案了。我在这里再次说明,以下的讨论不是分析或设计,而仅仅是让我们对棘手的问题更清晰一些,从而心里有个谱,避免实现的时候不知如何是好。
      在经过一番讨论后,我们都同意的解决方案是“未登录的用户使用Session处理购物车,登录的使用数据库存储购物信息。当用户登录时,如果Session中有将购物信息,将Session中的信息转入数据库。”
      这个讨论可以到此为止了。因为我们不需要太精确,我们只要大致心里有个谱就行了。

重点总结
      1.特性列表完成后,我们首先应该降低风险,而不是做分析或设计。
      2.重复特性存在风险。可以用DRY原则处理。
      3.存在模糊不清概念的特性存在风险。请仔细询问客户,不要想当然。
      4.不知如何实现的特性存在风险。一定要保证对每条特性的实现方式心里大致有个谱,但不需很精确。