代码改变世界

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

2010-07-22 22:46  Aga.J  阅读(1384)  评论(0编辑  收藏  举报

   最近在看《Head First Object-Oriented Analysis and Design》,就做下笔记吧,不知道为什么自己很喜欢OOAD的书,也很喜欢做这样的工作,希望也喜欢OOAD的朋友可以和我聊聊吧

第一章

Well-designed apps rock

Great Software Begins Here

这一章使用了一个例子来逐步引导读者进入面向对象设计的世界,例子从一开始的臃肿,复杂,不灵活,通过一步一步的面向对象分析设计的过程,到达一个可拓展,对象松散耦合,有弹性的程序。

案例分析,吉他店需要一个系统来帮助完成吉他搜索。

Guitar

{

 private:

       //属性。。。

 Public:

       //对应属性的Get和Set方法。。

}

Inventory

{

  Private:

       List guitars; //保存已有的吉他

  Public:

       Void addGuitar(String,double,String,String,String…);                     //新增加吉他,填入属性

       Guitar getGuitar(String);                     //根据某个吉他的序列号匹配吉他

       Guitar search(Guitar g);               //根据特定吉他来查找是否有该吉他。

}

在Inventory类中,addGuitar是通过输入许多参数,然后构造吉他类对象来完成的,search则对吉他的属性进行一个一个的匹配

(1) make sure your software does what the customer wants it to do

潜在错误:在用户进行search时需要对吉他对象进行初始化,而初始化又是通过字符串的参数传递来完成,这时候用户输入错误时(比如大小写的问题),就会让系统无法完成查找。

问题提出

1 每个参数都用字符串,可以用常量或者对象来代替吗?

2 查找函数的返回不应该是一个list吗?

3 Guitar类和Inventory类对对方的依赖程度都很高,需要重新构造吗?

问题解决:(在这个阶段要完成的任务是满足用户的需求,所以不用过多的考虑设计问题,但是可以应该oo principle来使得我们的程序从一开始就有良好的设计)

1 定义枚举类型,把吉他的部分属性设置为枚举的值,这样在传入参数时就不会有前面的错误出现。(枚举有组于类型安全也有组于值安全)

2 List search(Guitar g);返回串

(2) apply basic oo principles to add flexibility

潜在错误和问题提出:

1 好像search函数参数传入那里有些参数是不必要的,但是又对构造Guitars对象是必要的

问题解决:

1 对search所需的参数,即Guitar类的某些属性,进行封装,封装成另一个类,GuitarSpec,然后在原来的Guitar类里声明一个GuitarSpec的属性成员就可以(封装也可以将app分成多个逻辑模块,并且保持各个模块的相对独立,just like you keep the data in your classes separate from the rest of your app’s behavior, we can keep the generic properties of a guitar separate form the actual Guitar object itself,封装:protect information in one part of your application from the other parts of your application)

(3) strive for a maintainable reusable design(这个阶段专注于软件的可重用性和可拓展性)

潜在错误和问题提出:

1 如果为吉他类加入“吉他弦的条数”这个属性成员的话,那么我们必须修改代码的很多地方。(1)GuitarSpec类必须添加numStrings属性和getNumStrings方法(2)Guitar类的构造函数要改变,因为传入的参数要包括numStrings(3)Inventory的addGuitar方法也要进行参数修改,还有search方法体中要添加一条新的关于numStrings的比较条件。问题就在仅仅在GuitarSpec类中添加了一个属性成员,却要对剩下的所有类进行修改!显然,并没有很好的封装guitar来使得它和其他部分独立开来。各个类之间都互相依赖,所有没办法脱离其他类来单独使用一个类,所有现在的代码是不利于重用的。

问题解决:

1 根据上面的问题可以得到下面的解决方案:(1)修改Guitar类,使得其属性成员GuitarSpec被很好的封装,脱离Guitar类的构造函数(2)改变Inventory类的search函数,不直接在这个函数里面比较,而是委托GuitarSpec类来完成比较{委托使得代码更加reusable,也使得每个对象worry about its own functionality,rather than spreading the code that handles a single object’s behavior all throughout your application,防止在整个程序里哪里都可以处理某个对象的行为,也就是防止波纹效应,一个典型的例子就是类自身的equal方法}

问题解决过程:在GuitarSpec类中添加属性成员和方法成员,修改其构造函数,修改Guitar的构造函数,使得传入的参数为GuitarSpec对象。修改search函数,调用GuitarSpec类的match方法来完成匹配,具体的匹配过程在类里的match方法里实现

Important point

1 好的软件应该不能用太多重复的代码,并且每个对象都很好的控制和完成他自己的行为,这样会容易扩展

2 对象之间要松散耦合 open for extension closes for modification,使得代码更加易于重用

3 First.do what the customer wants it to do(前期的需求分析要做好)

4 Second. Well-designed,well-coded,easy to maintain,reuse,extend(设计和写代码时要时刻提醒自己这点,也就是使用OO principles来增加灵活性,使用pattern来使得系统maintainable和reusable)

5 Greate software in 3 easy steps:(1) make sure your software does what the customer wants it to do (2) apply basic oo principles to add flexibility (3) strive for a maintainable reusable design,

6 在初期对用户需求分析时,千万不要过多的考虑具体设计。Do not create problems to solve problems.

7 each object is interested in doing its job, and only its job, to the best of its ability.(每个对象都必须做他应该做的事,而他应该做的事就是这个对象的类名所指示的)

  Each object should represent a single concept

8 Encapsulation allows you to hide the inner workings of your applicant’s parts, but yet mike it clear what each part does.

9 Anytime you see duplicate code, look for a place to encapsulate

10 loosely coupled is when the object in your application each have a specific job to do, and they do only that job. So the functionally of your app is spread out over lots of well-defined objects, which each do a single task really well.

小结:第一章所用的软件工程过程方法和RUP有很大差别,不可以完全根据这样的过程来进行软件分析设计。文中还提到OOAD的相关知识(1)使用用例图和用例来帮助我们找到用户需求。(2)类图和时序图帮助我们找到设计上的问题,保证系统的健壮性(3)使用封装,组合,委托,来使得系统maintainable和extensible

杂记:封装能让系统更灵活,比如增加属性,封装能使得我们对系统的改变变得很容易(它是怎么实现这个灵活性的?对不必要代码的删除和代码简化--进行了封装,使用OO的principle)

让系统的复杂代码简化并且让它灵活后,接下来就是要让它可重用和可拓展(使用pattern)

保留可拓展的地方,考虑到用户可能需要的新功能,保留为这些功能服务的接口,同时让我们所做的系统的其中的东西可以作为以后为其他系统服务的东西

针对这个例子,需要做到 部分类的构造与整体类的构造函数独立,界面类里的实现不要涉及到其他类应该实现的东西,只要进行委托就可以了(ask another object to handle the ),然后通过其他类完成自己的事来达到task界面类的功能delegation lets each object worry about equality on its own.this means your object are more indepencent of each other,or more loosely coupled.Loosely coupled objects can be taken from one app and easily reused in another, beacause they are not tightly tied to other object's code,rather than spreading the code that handles a single object's behavior all throughout your application