代码改变世界

Head First Object-Oriented Design and Analysis学习笔记(十)

2010-08-05 18:52  Aga.J  阅读(1370)  评论(4编辑  收藏  举报

第十章 

The ood&a lifecycle

Putting It All Together

前言: 

这一章是对全书的总结,把我们所有学到的东西都应用到一个程序的开发生命周期上,然读者可以更清晰地看到每个知识的应用场景,同时也梳理了知识体系。

案例分析: 

书里已经在各个章节不同程度上的使用了OO分析与设计的开发方法和技巧,现在就举出一个例子来集合所有知识。

 

案例描述: 

系统名为Objectvile Travel RouteFinder,目的是为了提供给旅游者一种更容易的方式来观赏Objectvile的景色。RouteFinder可以保存整个Objectvile的network of subway lines,还有每条line上的stations。Objectvile的subway是可以在stations之间往返,所有我们不需要考虑每条line的方向。

RouteFinder必须能从一个起点和一个终点,给出一条旅行的route。然后旅游中介可以打印出这条route,里面指出了应该乘坐哪条line,这条line经过什么station,并且旅游者应该在哪一条line下车并去另一条line上车。

客户系统RouteFinder可以比较容易的拓展,因为他们可能会加上新的旅游路线

clip_image002

以下是map的截图

clip_image004

 

问题提出: 

第一步我们需要做的就是根据statement写出这个RouteFinder的Feature List

clip_image006

 

问题解决: 

在这里,我们应该从系统功能实现者的角度出发,给出我们能实现什么功能,让这个系统呈现出什么功能,每个Feature就是一个系统内部给外部的功能。

下图是书里给出的答案

clip_image008

Feature list给出的是系统需要完成的big thing,这是根据客户的statement给出的,客户在statement中给出了系统需要完成的功能,我们将他们归类抽象出来,而这时候的feature可能会是多个requirement的集合,即多个requirement才构成一个feature

还要注意到Feature list is not just a list of hard problems you have to solve—it is a list of all the things your application has to be able to do, 重点就在最后一句话,给出了feature的目的,指出了系统能做的事

问题提出: 

第二步我们应该进行Use case diagram的分析,从第一步的what your app does 转到how your app will be used。这是个比较自然的转换过程, 从系统内部能实现的功能到外部可以使用的功能进行自然的过渡。

Important Point 

Your feature lists are all about understanding what your software is supposed to do, your use case diagrams let you start thinking about how your software will be used, without getting into a bunch of unnecessary details(feature list 关注的是你的系统能干什么use case diagram关注的是你的系统能被怎么用,就是能被干什么)

clip_image010

 

问题解决: 

书里给出的答案是

clip_image012要注意feature list中每个feature都需要搭配一个用例,这才能保证用例的质量。

Important Point 

1 Use cases reflect usage, features reflect functionality (书里再次强调了这一点,feature给出了系统提供的功能,use case反映了系统的使用,而在feature对应某个用例的过程中,可能用例不是直接使用这个feature,但是用例是依赖于这个feature的)

2 every feature in your system will be at least a part of addressing one or more uses cases in your use case diagram. But that doesn’t mean that the use case has to actually directly use that feature

3 use cases are requirements for how people and things interact with your system, and features are requirements about things that your system must do. Implement a system use case,you are going to need the functionality in the system’s features.(说到底还是在说featur是what system does,而use case 是how system is used)

 

问题提出: 

第三步是The Big Break-up,同样也是承接了上面做的工作来完成

clip_image014

问题解决: 

通过对上面的use case的分析,我们将问题分成几个独立的功能模块,注意模块要在功能上十分独立,每个模块只有一个responsibility。

书里给出的答案是

clip_image016

这里给出的模块名字十分的精辟,它涵盖了应该包含的事物和功能。

问题提出

第四步是requirment,我们在功能上进行了用例划分,在结构上进行了模块划分,接下来就是开始对每个小部分进行功能上的分析来完成系统。At this point , we need to take out big-picture view of the system, form our use case diagram , and refine that into requirements that we can begin to tackle.这是个获取requirement的过程

clip_image018

问题解决:

写出用例的用例描述(如果是采用用例驱动模式来开发)

写出feature的详细(如果是采用feature驱动的模式开发)

如果在写用例的过程中,对问题里的一些东西比如一些专有名称什么的,不明白或者不清楚,我们应该进行understand the problem的一个小分析。这样能帮助我们更好的写出用例。

书里给出的用例描述是

clip_image020

要注意到写用例描述时,必须要有一个输入,一个输出,一个起始点,一个终点,把整个flow都写出来。同时要注意到额外情况的发生,就好像前面在分析其他系统的用例一样。

问题提出:

第五步是进行domain analysis,也是使用了前面所完成的工作

问题解决:

根据前面的用例描述,我们从中抽取名词和动词,作为我们的候选类和候选方法。

clip_image022

问题提出:

第六步是Preliminary design,紧紧的跟在第五步后面,使用了第五步的分析成果

问题解决:

根据候选类和候选方法,给出基本类图。

clip_image024

这个时候就不仅仅把前面的候选类和候选方法写进类里面,而且要给出每个类之间的关系,多重性,继承性,实现性等等,最后得到的类的方法是否全面就由你的候选方法决定,而候选方法又由你的用例描述决定,而用例描述。。。。。。就是这样一直层层往上,可以说明前面的工作的重要性。

问题提出:

第七步就是编码implementation了

clip_image026

问题解决:

根据每个类进行编码实现,编码过程中的细节也要好好考虑。例如在书里提到,我们或许在addStation时会传入一个Station的串名,或者是一个Station的对象,书里考虑到如果是一个对象,那么就会expose the internal of your application,因为这样就可以操作这个对象了,而且目前的系统中并不需要用户使用station的对象,所有不需要将它作为一个对象传入。而且使用对象传入会使得代码十分紧凑。

clip_image028

在编码过程中我们要加入测试代码,才算完成某个部分的编码。

然后我们又要继续进行所谓的iterate,对每个用例或者feature进行详细的获取requirement,domain analysis, preliminary design,implementation.而在这个过程中你会发现,每当你进行一个用例的用例描述时,在描述里你会使用到超过一个的模块来帮助用例描述,也就是说你来来回回的在用例和模块之间跳转。其实这样的跳转是focus on code, then focus on customers之间的跳转。当我们将程序分成几个不同的模块时,我们在解决程序的结构上的问题,这时候我们focus on code。而当我们在分析我们的用例时,我们在解决用户怎样使用系统的问题,所以我们在进行用例描述时,即考虑到代码结构,又考虑到了功能,这样会使得我们的代码灵活而顾客满意

clip_image030

在编码阶段的最后,就是我们的test class了,进行测试是很重要的一环

Important point

1 you should only expose clients of your code to the classes that they need to interact with , classes that the clients do not interact with can be changed with minimal client code being affected.

2 sometimes the best code for a particular problem has already been written. Don’t get hung up on writing code yourself if someone already has a working solution

小结:

整个面向对象分析与设计的开发过程可以由下图清晰地展示

clip_image032

整个生命周期分为3个阶段,第一个阶段是分析阶段,目的是Make sure your software does what the customer wants it to do,这个阶段也是持续时间最长的阶段,可见分析是多么的重要。它这里的“分析”其实是一个概括性的概念,它涵盖了许多方面,包括需求获取,用例描述等等,主要有以下几点

(1) Feature List-----在较高抽象粒度上分析你的系统能做什么

(2) Use Case Diagrams-----分析出你的外部对象可以怎样使用你的系统,从分析过程中列出系统应该完成的大方面的功能和涉及到的外部对象

(3) Break Up the Problem-----将你的系统分成功能上不同的模块,然后决定解决模块的顺序

(4) Requirements-----给出每个模块的独立的需求,确保需求和系统big picture一致

(5) Domain Analysis------将用例描述中的对象和方法找出来,为后面类及其方法的设计做准备

第二个阶段则是开始接触代码的阶段,Apply basic OO principles to add flexibility,包括两个方面

(1) Preliminary Design----根据前面的Domain Analysis,对类及他们之间的关系进行初始设计,同时在代码编写中要注意使用上OO 的principles 和patterns

(2) Implementation----写代码,并且测试它。

最后一个阶段是Strive for a maintainable reusable design,文章并没有详细介绍

生命周期中还有一点就是Iterative Development,但是这的迭代不是对生命周期中每个阶段进行迭代,它指的仅仅是一部分一部分的完成某个阶段的任务

下面这张图是整个软件开发周期内可能会使用到的一些原则或者方法。

clip_image034

Feature List阶段:我们需要Talk to the customer,然后写出Key Feature List

Use Case Diagrams阶段:我们需要根据Key Feature List进行用例图的绘制,包括Exrernal Initiator,如果需要更进一步的信息,我们需要Talk to the Customer。

Break Up the Problem阶段:我们关注整个软件的Architecture,通过Analysis,使用Commonality的分析方法,将Problem分成小块,要注意每个模块只能负责一件事,所以有些功能可以通过Delegation来完成。

Requirements阶段:这个阶段我们会对抽取用例进行详细的用例描述,每个用例就是一个Scenario,它会有Exrernal Initiator来启动用例,同时要考虑Alternative Path来使得我们的程序更加健壮

Domain Analysis阶段:使用Textual Analysis分析方法,更加前面的用例描述完成基本的候选类和候选方法的选取

Preliminary Design阶段:从前面的Domain Analysis分析的来的信息,进行类的设计,要记住Encapsulation多变的,Encapsulation共性的,可以应用一些Design Pattern和Design Principles使得我们的类的结构设计更加灵活,更利于拓展,最后会得到一个完美的Class Diagram

Implement阶段:同样需要使用多种原则来完成代码实现,OO Principle,Design Principles,而在implement阶段,我们可以选取Feature driven或者Use case driven的开发方式来开发,最后就是test scenario。