面向对象葵花宝典

概念

结构化设计

结构化程序设计的主要特点是抛弃goto语句,采取“自顶向下、逐步细化、模块化”的指导思想

人脑存在人类短期记忆一般一次只能记住5-9个事物,这就是著名的 7+- 2原理

面向过程

面向过程是一种以“过程”作为中心的编程思想,其中过程的含义就是“完成一件事情的步骤

面向对象

更加侧重于对现实世界的模拟

面向过程中有“程序=算法+数据结构”的经典总结,

面向对象也有类似的总结:“程序=对象 + 交互”。其中对象就是具体存在的事物,而交互则是事物之间的相互作用、互动等。

中文“可扩展性”对应英文有两种解释:extensibility 和 scalability,extensibility指系统需求变化后,能够比较容易的扩展以支持新需求;scalability指系统访问压力增加后,能够通过简单的增加更多硬件设备以支撑访问压力,又翻译为“可伸缩性”。 本文的可扩展性是指extensibility。

软件质量

类是本,代码是末,只有清晰地掌握了类的概念,才能写出好的代码。

那究竟何为类呢?

物以类聚人以群分。

类就是一组相似事物的统称。

首先:请看“一组”,思考一下为什么是“一组”,不是“一个”?

其次:请看“相似”,思考一下为什么是“相似”,不是“相同”?

最后:请看“统称”,思考一下为什么是“统称”,不是“名称”?

第一个玄机——“一组”:一组的玄机在于“多个“,单个事物无法成为类。

一个很简单的例子:“人“可以是一类,但“我”就不是一个类(那又是什么呢,请看后文分解?)

第二个玄机——“相似”:相似的玄机在于“比较像,但不完全相同”。

还是“人”这个例子:奥巴马和克林顿都是美国总统,都是人,有很多相似的地方,但他们两个绝对不是完全相同的。

第三个玄机——“统称”:统称的玄机在于“统”,也可以叫做“通称”,统称要能够概括这多个事物。

还是上一个例子:奥巴马和克林顿的统称可以为“人”、“男人”、“总统”,但不会统称为“奥巴马”,因为奥巴马是一个具体的人了。

类的定义玄机我们已经基本解读,看起来已经比较清晰了,但不要高兴太早,还有一个更大的玄机:我们怎么划分类?

只要有相似点的就是同一类

站在你的观察角度,具有相似点的事物就是同一类

对象

定义对象为“一个具体的类”,但这是否意味着必须是先有类后有对象呢?

  • 现实对象:你能看到的物体都可以称为现实对象;
  • 现实类:对现实对象的归纳总结;
  • 软件对象:软件实际运行过程中存在的对象;
  • 软件类:软件设计过程中归纳总结出来的类;

葵花宝典_07.01

抽象

第一个层次:对象 抽象成 类。

例如奥巴马和梅西抽象成“人”,这一层的抽象主要是将“属性类似”的对象抽取成类。

第二个层次(或更高层次):将 类 抽象成超类

例如人和猪抽象成“动物”,这一层的抽象主要是将“行为类似”的类抽象成父类。

抽象最主要的作用是“划分类别”,而划分类别的主要目的其实还是“隔离关注点,降低复杂度”

封装

第一个问题是:我们要封装什么?

第二个问题是:我们为什么要封装?

  • 封装数据的主要原因是“保护隐私
  • 封装方法的主要原因是“隔离复杂度

继承

抽象:是分析和设计过程中的一个动作,一个技巧,通过抽象得出类

继承:是实现过程中的一个动作,基于抽象结果,通过编程语言的特性,完成抽象图的模拟。

多态

多态屏蔽了子类对象的差异,使得调用者可以写出通用性的代码,而无需针对每个子类都需要写不同的代码。

完整流程

1. 管理流程

瀑布模型、螺旋模型、迭代开发、敏捷、RUP

2. 技术流程

需求模型 -> 领域模型 -> 设计模型 -> 实现模型

l 需求模型

通过和客户沟通,结合行业经验和知识,明确要求客户的需求。

l 领域模型

基于需求模型,提炼出领域相关的概念,为后面的面向对象设计打下基础。

l 设计模型

以领域模型为基础,综合面向对象的各种设计技巧,完成类的设计。

l 实现模型

以设计模型为基础,将设计模型翻译为具体的语言实现,完成编码。

需求模型

需求:对客户来说有价值的事情;

功能:系统为了实现客户价值而提供的能力;

例子

POS机:“买单”是需求,“商品扫描”、“金额汇总”、“收银”等是功能,因为买完单后顾客就能将产品拿走;

汽车:“驾驶”是需求,“发动机”、“刹车”、“加速”等是功能;

打印机:“打印”是需求,“进纸”、“设定”、“与电脑连接”等是功能;

需求分析 518 方法

5:5W,即When、Where、Who、What、Why

1:1H,即How

8:8C,即8个Constraint,包括性能Performance、成本Cost、时间Time、可靠性Reliability、安全性Security、合规性Compliance、技术性Technology、兼容性Compatibility

提取功能点

是动词——提取出来,就成为了系统的功能。

用例 use case

NEA 方法

1) 正常处理(Normal):通过和客户沟通,分析需求的正常流程;

2) 异常处理(Exception):在正常处理流程的步骤上,分析每一步的各种异常情况和对应的处理;

3) 替代处理(Alternative):在正常处理流程的步骤上,分析每一步是否有其它替代方法,以及替代方法如何做;

领域模型

1)发掘重要的业务领域概念

2)建立业务领域概念之间的关系

总结找名词、加属性、连关系

名词 属性 备注
顾客 NA 对于POS机来说,并不需要识别顾客的相关信息,因此在领域模型中,顾客是没有属性的
收银员 国籍、编号 “国籍”由找名词步骤中的“中国人”提炼
商品 条形码、名称、价格 名称和价格并没有在用例中体现,但毫无疑问这是商品最基本的属性
扫描仪 NA 扫描仪是POS机的一个输入设备,POS机不需要识别扫描仪的相关信息,因此在领域模型中,扫描仪也是没有属性的
钱(现金) 数量,币别 从领域分析的角度来讲,“现金”更专业一些
信用卡 卡号 NA
会员卡 会员号、积分、有效期 NA
小票 交易信息、POS机信息、收银员信息 小票的属性在用例中并没有详细体现,但有经验的分析师能够很容易识别出来
买单(交易) 商品列表、日期时间、总额、支付信息 这里的属性看起来和“小票”一样,是因为“小票”本质上是给客户的一个交易记录。这里为了更加符合软件系统的属于习惯,可以将“买单“改为“交易”。
键盘 NA 和扫描仪类似,POS机不需要识别键盘信息
屏幕 NA

设计模型

静态模型又可以称为“类模型”,主要关注系统的“静态”结构,描述了系统包含的类, 以及类的名称、职责、属性、方法,类与类之间的关系。

动态模型关注系统的“动态”行为,描述类本身的一些动作或者状态变化,以及类之间如何配合以完成最终的业务功能。只有结合静态模型和动态模型,我们才能够真正的将一个系统描述清楚。

静态模型和动态模型对于后续的编码也具有不同的指导意义。静态模型主要用于指导类的声明,包括类名称,属性名,方法名;而动态模型主要用于指导类的实现,主要就是每个方法内部的具体实现。

类模型

问题
对象从哪里来?

什么时候用设计模式?

如何判断设计是否正确?

什么样的设计才是优秀的设计?

第一步(照猫画虎):领域类映射 — 告诉你类从哪里来

领域模型找名词,用例分析找动词。

第二步(精雕细琢):应用设计原则和设计模式 —告诉你如何设计“好”类

首字母 英文简写 英文名称 中文名称 说明
S SRP Single Responsibility Principle 单一职责原则 对象应该只具备单一职责
O OCP Open/Close Principle 开放/封闭原则 认为“软件体应该是对于扩展开放的,但是对于修改封闭的”的概念。
L LSP Liskov Substitution Principle Liskov替换原则 认为“程序中的对象应该是可以在不改变程序正确性的前提下被它的子类所替换的”的概念
I ISP Interface Segregation Principle 接口隔离原则 多个特定客户端接口要好于一个宽泛用途的接口
D DIP Dependency Inversion Principle 依赖反转原则 依赖于抽象而不是一个实例

设计原则主要用于指导“类的定义”的设计,而设计模式主要用于指导“类的行为”的设计

第三步(照本宣科):拆分辅助类 —告诉你如何和你的开发框架结合起来

内聚和耦合

内聚关注模块内部的元素结合程度,耦合关注模块之间的依赖程度。

1. 内聚

cohesion refers to the degree to which the elements of a module) belong together.

http://en.wikipedia.org/wiki/Cohesion_(computer_science))

cohension 也指 凝聚力。

l 判断团队凝聚力时,我们关注团队成员是否都专注于团队的目标;判断面向对象模块的凝聚力时,我们同样关注元素是否专注于模块的目标,即:模块本身的职责!

l 判断团队凝聚力时,我们还会关注团队成员之间是否互相吸引和帮助;判断面向对象模块凝聚力时,我们同样关注元素间的结合关系;

像 DAO 层,都是依赖于其他模块完成本模块的工作。

2. 耦合

coupling or dependency is the degree to which each program module) relies on each one of the other modules

http://en.wikipedia.org/wiki/Coupling_(computer_science))

3. 高内聚低耦合

低内聚:

Person类改变后,虽然这个改动和Coach、Director都没有关系,但Coach和Director类都需要重新编译测试部署

高耦合:

对于高耦合的模块,可能本身并不需要修改(低内聚是每次自己都要修改),但每次其它模块修改,当前模块都要编译、测试、部署,工作量同样不小。

4. 冲突

我们详细来分析一下为什么高内聚和低耦合是冲突的。

对于内聚,在一个类的层面上,一个类只有一个方法,这个模块内部内聚性很高。但是在这个类同一层的抽象上,这个模块(以类为模块)的需要大量依赖其他的模块。这是一个高内聚高耦合的模块。

同理,对于耦合来说,最弱的耦合是一个类将所有的函数都包含了,这样类完全不依赖其它类,耦合性是最低的。但这样会带来一个明显的问题:内聚性很低,于是整个设计就变成了“低耦合低内聚”了。由于低内聚,整个类的变动同样非常频繁。

对于“低耦合低内聚”来说,还有另外一个明显的问题:几乎无法被其它类重用。原因很简单,类本身太庞大了,要么实现很复杂,要么数据很大,其它类无法明确该如何重用这个类。

SRP 原则 – 单一职责原则

有很多翻译叫做: 一个类只做一件事。一个类只有一个变化的原因。

但是这个太难满足了。

我们从语义上说。什么叫职责?

“职责”是站在他人的角度来定义的,而不是自己定义的。

所以类的职责:

1) 类的职责是站在其它类的角度来定义的;

2) 类的职责包含多个相关功能

一个类只负责一组相关的事情

SRP不能应用于聚合类,那么如何保证聚合类的设计质量呢?

OCP 原则 ??? – 还是不能理解。。

open for provider extension,closed for consumer modification

0%