1、"和其它阶段的关系"的再思考。
上一篇的末尾我们简单的讨论了细节需求阶段和其它阶段的关系。对于软件过程的各个阶段,不同之处只是注重的焦点不同而已。在业务建模阶段,我们关注于系统的整体需求;在细节需求阶段,我们更关注于需求的细节部分。其它的阶段也是一样,架构阶段,所关注的当然是如何设计出一个合适的架构;到了设计阶段,注意力就转移到了如何设计方面。
当然,焦点的不同,导致了各个阶段所需要的技能和工具也不尽相同。业务建模阶段需要你有整体的把握能力,你可以使用简单的用例图,基本的用户素材等工具。细节需求阶段则要求你能够充分的挖掘需求和进行良好的沟通。相应的,在架构、分析、设计等阶段,也会有不同的需要。
各个阶段的实质就是注重点的不同,这对于大多数的软件开发而言都是一样的。不论你采用的过程是传统的,还是迭代的。
2、架构
Martin Fowler在他的ISA中写到:
I’m using architecture to mean the important design decisions, the ones that shape most aspects of a software system. These are often the harder decisions to change later on in the project (although often not as hard as people think). As a result these are ones where it’s useful to start in the right direction, and thus knowing about architecture is a valuable skill for any software developer.
架构并不神秘,无非是一个决策而已,只是这项决策对软件特别重要就是了。软件开发人员可能根本没有主动的进行架构设计,但是他的行为,已经潜移默化的进行了;而还有一些人,总在谈论着架构,但是并不了解这个词的含义。
春运就要到了,学生也要赶着回家。如何选择回家的交通工具就是一个重要的决策。路程的远近、不同交通工具的价格都是显式的,比较容易知道的。而以往的经验也告诉你,火车票比较便宜,但是比较紧张,花费时间较长,整个过程也不舒服;飞机票比较贵,但是容易买到,花费时间少,整个过程很舒服。这时候你就要做出正确的决策,为回家选择一个正确的架构。你可能考虑的因素有哪一些?以下就列出了一些可能的因素:
拥挤程度,大家都知道春运时那种情况;
购买票的难易程度,火车票需要很早就要预定了;
是否有额外的渠道,比如你能够买到飞机的学生票;
经济实力,经过了一个学期的花销之后,现在还剩多少生活费;
根据这些因素,以及这些因素对你的影响程度,即优先级,你可以自己估算出一个或几个可能的架构方案。而这种架构的选择,直接影响到你之后的行为,也影响到行为的结果。
开发软件和买票回家又能有什么区别呢?一样要考虑成本、结果、时间。所不同的只是复杂了:需要专业技能,有很多不确定的因素。
那么我这里谈论架构的问题,和需求有什么关系呢?在上面的例子中,大家可以看到架构是根据什么决定的?是因素。因素的本质是什么?就是需求。因素,就是需求。所以,需求决定架构。上一篇中,我谈到说,在进行细节需求之前,一定要定出架构。当然,这时的架构可能只是一张草图。为什么?因为我们已经进行了业务建模,对项目有了一定的认识,对用户的需求也有一定的把握,成本、范围、时间等要素也都清楚了(如果你还不了解这些,请你回到业务建模阶段,你的工作还没有结束)。这个时候,决定架构的因素已经形成了,可以进行架构的设计了。
需求能够决定架构,架构反过来也能够影响需求。最明显的一个例子就是用户界面的设计。虽然用户界面主要来自于需求,但是不同的架构对用户界面也会有影响,例如基于浏览器的客户端,和基于Windows界面客户端能够提供的界面就不同。
在XP中,这种的架构设计,被称为Architecture Spike。为什么叫做Spike呢?就是说你需要专研,解决一些主要的问题,但你并不是提供一个完整的解决方案。例如,在项目的初期,如果你对新近的服务器和操作系统不了解,你肯定会花时间去了解,去试用,去测试;如果对数据库不了解,你也肯定会试着使用看看。这种行为,就是Spike。所以呢,架构的设计只是很初步的设计,而不是一个完善、定型了的设计。这一点要注意。
架构的选择和开发人员的经验和能力非常有关系。一般来说,它需要开发人员具有相关的经验。提供架构的厂商多如牛毛,如何选择,也是一项学问。比如,数据仓库的平台,选择的品种就很多;而Web Server的选择也是五花八门;操作系统也是一样。这些又都是和架构息息相关的。
3、模式
武功有招式,下棋有棋谱。不论是招式,还是棋谱,都是针对某一种问题的特定解决方案。在软件开发领域,这种解决方案就被称为模式。
"每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心,这样,你就能一次又一次的使用该方案而不必做重复的劳动"[AIS,77]
这句话源自模式的鼻祖――Christopher Alexander。而在软件开发领域,最值得一提的著作,就是GoF写的『设计模式』一书。在该书中,作者描述了23种的设计模式,可以说,这些模式奠定了面向对象设计的基础。而另一本值得阅读的著作,就是Martin Fowler所著的『分析模式』。
在软件设计中,我们遇到各种各样的问题,我们可能缺乏经验,或能力有限。这非常的正常。但是现实是,我们生产出的代码由于设计方面的缺陷,往往不够清晰,容易出错,难以扩展。相信只要是开发过软件的人,都遇到过这种问题。于是,我们就希望能够看看其他人,是如何处理这种问题的。这里的"其他人"指的可能是技术专家,也可能是经历过同种问题的人,他们对你遇到的问题有能力,有经验来解决。他们提出的解决方案往往是非常成熟的,能够解决你目前遇到的问题,也能够解决你目前尚未遇到的问题。
这对你的吸引力是很大的。那么,我们谈论模式,模式来源于何处呢。注意,模式是针对某一类的问题的解。这里的问题,所指的就是需求。比如说,客户希望能够在软件中实现不同的税率计算方法,那么,我们很自然的就可以想到Strategy模式;当客户的产品有一个很复杂的单位换算机制的之后,我们也能够很自然的想到Quantity模式。使用模式,能够使我们迅速的把握需求的解决方法。另一方面,模式往往告诉我们比目前的问题更多的方面,因为模式都是大家的经验沉淀。如上所说,它还可以解决你目前没有遇到的问题。因此,我们还可以从模式中发现出更深的需求。
另外一点也很重要,虽然它和需求的关系不大。模式往往都有一个模式名称。这就形成了一种沟通的语言。比如我们在下象棋的时候,只要说"马后炮",谁都知道这是什么意思,绝对不需要呢详细的解说每一步棋子的走法。对于软件开发也是一样的。我和我的同伴会心的一笑,说:"Factory Method。"两个人都能够理解这是什么意思,因为这是一种共通的语言,它代表了背后隐藏的各种类的关系和代码实现。这在软件开发中非常的重要。当然,这有个前提,大家都对模式有一个通透的了解。
4、简单设计
模式属于设计的一环,所以前面我们讨论的其实就是设计和需求的关系。这一小节我们还是讨论这个话题。但是侧重点有所不同。XP中有一个原则:KISS。不是kiss哦。它是Keep it simple and stupid的缩写。除了XP,其它的敏捷方法都提倡简单设计,反对过分设计(over build)。也就是说,针对目前的需求,设计目前的软件。
很多的软件人员都是完美主义者,他们喜欢完美的设计,然后把这种设计提供给用户。这种思想就是过分设计的开始。不必要的功能浪费了客户的投资。我们在做需求的时候,很经常发现开发人员随意的向客户推销一些新功能,或是在设计时,过多的考虑未来可能出现的需求变动。
所以,简单设计的意思,就是要针对目前客户提出的需求进行设计,不要过多的考虑目前没有提到的功能。
5、如何统一
细心的读者看到这里可能已经是疑窦丛生了。一边是鼓励使用、设计最完美的方案;另一方面,又强调简单。似乎是自我矛盾。不错这其中是由矛盾的地方,但也有一致的地方。因此,在使用先进的模式和保持设计的简单性之间,我们需要权衡。
一次,我们看到了一个关于权限设置的模式,我们觉得这个模式非常的好,它提供了类似于UNIX操作系统那样的权限控制,可以很随意的增加组、用户,并能够在文件级别上设置权限。我们如获至宝,觉得这是一个非常有用的模式。于是,我们花了一些时间将之实现,并打算应用于新的软件中。
在实际中,我们发现没有一个用户需要如此强大的功能,他们所需要的可能仅是密码控制,或是简单的用户管理。如此复杂的功能对他们来说没有任何的意义。完美的模式在现实中遭到了冷遇。
实际上,用户目前不需要这项功能,并不意味着他以后不需要这项功能。用户的计算机程度提高的很快,我们估计,再过那么一两年,用户可能就非常需要这项功能来管理他那日益庞大的员工队伍了。但是目前,这项功能对用户来说,设置复杂,所以他们并不愿意接受这个"有价值"的功能。
最后,我们想到了一个解决的办法,我们为这一项功能定义了一个通用的接口。通过这个接口,你可以实现复杂的功能,也可以实现简单的功能。总之,你只要是实现了接口的方法就行了。接口的方法很多,但是在目前的简单的实现中,可能就仅仅是一个返回语句,并没有很多的实现。相应的,用户的也仅仅需要使用简单的方法,诸如addUser(),updatePasswd()等。界面也做了简化的处理。
通过这种方法,我们可以在用户需要的时候,替换掉权限模块,对其它的应用并不影响。当然,其中有很多的细节需要注意。在完成之后,我们还发现了另一个副产品:整个的权限控制模块是高内聚,低耦合的。
模式,就好比螺帽的设计图纸,它规定了螺帽的技术规格,但是没有规定具体的尺寸。对应于不同的需要,我们可以设计出不同大小的螺帽以供使用。图纸只需要一份就可以了,并不需要为每一种尺寸的螺帽画一张图纸。
因此呢,一个经历了实践检验的模式,往往功能强大。但是它可以有多种不同的实现。有哪一条法律规定你必须完全的实现一种模式呢。在实际使用中,你需要权衡模式使用的成本和效益。你会发现,在很多情况下,你还是实现了模式,但只是模式的一个框架,或一部分,但是这在目前就够用了。而当需求变动,或新的需求出现的时候,你可以很方便的在原有搭起的框架上添砖加瓦。一切都是那么的自然。比如,在一个进销存的软件中,存在一个运输选择算法,目前的运输途径就一种,但是很有可能会增加新的途径。这时候,你就决定采用Strategy模式。但是你只是实现了一个简单的框架,只有一个具体子类,来实现目前的算法。当新的运输途径出现时,你需要增加一个算法,你就可以再增加一个子类,只要实现的接口相同,改动是不会影响到系统其它的部分的。
延伸阅读
文章来源于领测软件测试网 https://www.ltesting.net/