第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记

本章从一个吉他库存小程序开始,逐步改进,介绍了一些面向对象设计的核心思想。

初始场景

故事是这样开始的。。。。。。

有个老板是卖吉他的,它想要一个程序能管理和搜索他的吉他库存。

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第1张图片
吉他店老板

设计公司很快给出了最初的设计方案,有两个类:

  • 吉他类:存储每一把吉他的特征
  • 库存类:管理吉他库存
第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第2张图片
吉他类
第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第3张图片
库存类

此外,还给出了这两个类的具体代码实现。但是某些代码似乎有点“坏味道”,特别是库存类中的 search 方法,非常长、非常复杂。

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第4张图片
search 方法

在模拟测试中,程序竟然没有按照预期工作:一把吉他明明存在,但是在库存中却查找不到

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第5张图片
测试出现问题

软件开发的终极问题

到目前为止,这个程序肯定是有问题的。

这时候,三个程序员出场了,他们对如何修改这个程序提出了各自的看法,似乎都有道理。

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第6张图片
三人讨论

他们三个人的讨论引出了终极问题:

  • 什么是伟大的软件
  • 怎么设计出伟大的软件
第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第7张图片
终极问题

伟大软件满足两个标准:

  • 符合用户的要求
  • 可维护、可重用、可扩展

设计伟大软件有三个步骤:

  1. 首先满足用户的功能要求
  2. 引用 OO 原则
  3. 进行良好的设计

修正错误并改进

为了满足用户功能要求(伟大软件的第一步),要先修正原先程序中存在的错误,让程序首先能跑起来。

错误找到了,是字符串字面量大小写引起的

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第8张图片
出错的地方

对于如何修正这个错误,三个程序员又进行了讨论,他们认为在修正错误的同时,可以进行小的设计改进

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第9张图片
讨论

下面是三个改进的地方:

  • 改进之一:用枚举常量替代字符串字面量来表示吉他的特征,这样可以避免拼写错误问题
  • 改进之二:对于那些只能用字符串的特征,搜索的时候先将它们都转换成小写,然后再比较
  • 改进三:原先的搜索功能只能返回第一个符合特征条件的吉他,现在可以将所有符合条件的吉他都返回

当然,每一次修改完都应该进行测试,这次测试实现了预期目标。

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第10张图片
测试

这一小节的核心思想是:软件开发一开始专注于实现功能,完成功能前不用太过在意设计问题。有点小的设计也无妨,但是实现功能是前期的重点

单一责任原则和封装

到目前为止,程序已经跑起来了,而且实现了预期的功能,但是仍然有一些地方似乎有问题。

如果要搜索具有某些特征的吉他,需要先用这些特征创建一个吉他对象,然后传给库存类的 search 方法进行查找。

问题是:一个完整的吉他对象有序列号和价格这两个属性。而搜索时创建的吉他对象并不需要这两个属性

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第11张图片
搜索吉他

为什么会这样?对于这个问题的分析引出了一个重要的原则:单一责任原则!

三个程序员进一步讨论,认为吉他对象承担了太多的责任,应该将特征部分放到另外一个对象中去

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第12张图片
Paste_Image.png

他们新创建了一个规格类,将吉他的特征部分放到这个类中

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第13张图片
规格类

这里还隐藏了一个原因:规格特征很容易发生变化,因此应该将他隔离出来,后面将会看到。

现在给库存类的 search 方法需要传送一个规格对象,而不是吉他对象,不再有多于的参数了!此外,比较的时候也是用规格对象,而不是吉他对象。

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第14张图片
修改搜索方法

再次测试目前为止的代码,一切正常。

这一小节先引出了单一责任原则,最后告诉你用封装隔离变化,这些变化可能包括信息或者行为

复用

目前的代码已经不错了,但是它是不可复用的。

现在老板想增加一个“琴弦数目”的特征,对于目前这几个类,会造成什么影响呢?

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第15张图片
增加属性

影响如下:

  • 规格类:需要增加“琴弦数目”属性,并增加相应的存取方法。(规格类的改动不算太大)
  • 吉他类:吉他类的构造函数会接收一系列特征值,因此要增加一个参数以接收“琴弦数”;此外吉他类还需要创建规格对象,也需要增加这个参数。(吉他类的责任太多,创建规格类不应该是他的责任。同时他对规格类了解的太多。)
  • 库存类:库存类 addGuitar 方法接收一系列特征值作为参数,因此也需要修改;此外,search 方法比较吉他的特征,要考虑新增加的属性。(库存类也是对规格类的细节了解的太多)

牵一发而动全身,说明代码的组织有问题

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第16张图片
很难复用

这一节的最后又引出了另外一个概念:委托。

委托最根本的目的就是划分责任,让每个对象只做自己该做的事情

重构代码

第一步:增加新的属性

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第17张图片
增加新属性

第二步修改:给吉他对象注入规格对象,而不是在吉他对象内部创建规格对象,解除强依赖

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第18张图片
解耦

第三步:将库存类 search 方法中的比对特征工作移动到规格类中,进一步解耦

第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记_第19张图片
解耦

最后再次测试,一切正常,得到一个设计良好的程序。


总结:开发设计三部曲

  1. 快速实现功能
  2. 用 OO 原则进行封装
  3. 重构、解耦

你可能感兴趣的:(第01章 - 良好应用程序的基石 - 《深入浅出面向对象分析与设计》读书笔记)