OO design
OO view
Modeling the world as a series of messages that pass between objects.
1章 面向对象设计
目的
设计的目的是为了应付变化,易于扩展。减少对象之间的依赖。单一职责(合理分工)。高内聚低耦合。各种对象(模块)相互合作共同组成以一个整体,形成一个应用。
艺术性
设计是一门艺术,编排代码的艺术(强调艺术性)。
按今天的计划编写将来交付的代码,还要构建出以后发生变化的代码。
关注点
近期成本,远期更改的成本(综合考虑两者兼备)。
时间会产生变化(新的的需求)。
设计要降低变化带来的成本。
工具
原则和模式,是有利的工具。
强调
程序要有设计感 有设计是非常重要的。
设计原则
5个设计原则(solid)
单一职责原则
开闭原则
里氏替换原则
接口隔离原则
依赖倒置原则
两个后加的原则
不重复原则 DRY
迪米特法则 law of demeter,lod
设计模式
模式和原则的使用的成败取决于使用者(经验和了解程度)
设计是一个逐步发现的过程(敏捷开发 不断迭代)
不要过度设计(你想象中的未来 不是真正的未来)
概念: 技术债务 设计的 盈亏临界点
面向对象的应用程序由对象和他们之间传递的消息构成
对象由数据和行为(方法)组成
对象之间通过消息来调用彼此的行为
类 是为对象提供了一个蓝图
面向对象的基础是消息,最明显的组织结构是类
设计是保留可变性的艺术
Define change as
• Changes have no unexpected side effects
• Small changes in requirements require correspondingly small changes in code
• Existing code is easy to reuse
• The easiest way to make a change is to add code that in itself is easy to change
The code you write should have the following qualities. Code should be
• Transparent :The consequences of change should be obvious in the code that is changing and in distant code that relies upon it
• Reasonable :The cost of any change should be proportional to the benefits the
change achieves
• Usable: Existing code should be usable in new and unexpected contexts
• Exemplary :The code itself should encourage those who change it to perpetuate
these qualities
call true
2章设计具有单一职责的类
单一职责利于重用
要依赖行为,不依赖于数据(对数据用方法进行封装)
方法和类一样也要做到单一职责,只是这个单一职责的范围不同(类比方法大)
The impact of a single refactoring like this is small, but the cumulative effect of
this coding style is huge. Methods that have a single responsibility confer the following
benefits:
• Expose previously hidden qualities Refactoring a class so that all of its methods
have a single responsibility has a clarifying effect on the class. Even if you do not
intend to reorganize the methods into other classes today, having each of them
serve a single purpose makes the set of things the class does more obvious.
• Avoid the need for comments How many times have you seen a comment that is
out of date? Because comments are not executable, they are merely a form of
decaying documentation. If a bit of code inside a method needs a comment,
extract that bit into a separate method. The new method name serves the same
purpose as did the old comment.
• Encourage reuse Small methods encourage coding behavior that is healthy for
your application. Other programmers will reuse the methods instead of duplicating
the code. They will follow the pattern you have established and create small,
reusable methods in turn. This coding style propagates itself.
• Are easy to move to another class When you get more design information and
decide to make changes, small methods are easy to move. You can rearrange behavior
without doing a lot of method extraction and refactoring. Small methods lower
the barriers to improving your design.
3章 管理依赖关系
将类里的额外职责隔离起来(临时 很实用的技巧)
对象之间有消息的交互,这就产生了依赖,为了提高程序的灵活性要尽量的减少这些依赖。
依赖阻碍变化(不利于扩展)
依赖 产生 耦合
代码之间的耦合
代码与测试之间的耦合
知识是归发送方还是接收方
依赖注入
依赖反转(给接收方)
隔离是一个很好处理依赖的方法
对于依赖方向的选择(依赖于稳定的不变的
依赖于抽象 不依赖于实现)
可能发生变化
和 依赖的关系(权衡两者)
4 章创建灵活的接口
程序 由类组成由消息定义
选择好的消息模式(两个图)
Public Interfaces
The methods that make up the public interface of your class comprise the face it
presents to the world. They:
• Reveal its primary responsibility
• Are expected to be invoked by others
• Will not change on a whim
• Are safe for others to depend on
• Are thoroughly documented in the tests
Private Interfaces
All other methods in the class are part of its private interface. They:
• Handle implementation details
• Are not expected to be sent by other objects
• Can change for any reason whatsoever
• Are unsafe for others to depend on
• May not even be referenced in the tests
公共接口就是一种契约,他阐述了类的职责,是对职责的描述
接口对于ruby这种鸭子类型意义更大
一个类只应该依赖于那些比自己更不容易变化的类(更稳定的类)
公共方法,表示一种安全性(不易变化)
要什么,如何做的区别
寻求上下文独立
Ruby provides three relevant keywords: public, protected, and private. Use
of these keywords serves two distinct purposes. First, they indicate which methods are
stable and which are unstable. Second, they control how visible a method is to other
parts of your application.
面型对象设计的目的在于减少变化所带来的成本
5章鸭子类型
鸭子类型是指不会邦迪到任何特定类的公共接口
这种跨类的接口给程序带来了巨大的灵活性,采用更加宽容的消息依赖取代昂贵的类依赖
在ruby中,对于某个对象的的期望是以其公共接口定义的。
多态 单一物种有多种形态(高中生物讲的 岛上的各种麻雀)
6章通过继承获得行为
继承的核心是一种用于实现“消息自动委托机制”,他为无法理解的消息定义了一条转发途径
继承实现了一种代码共享
要找出抽象 然后创建抽象的父类
使用钩子消息解耦子类(减少对super方法的依赖,也就是减少对父类的依赖)
7使用模块共享角色行为
对象应该自我管理,像字符串类型自身就有大量方法,不要需要通过别的类(要让类自己说话)
里氏替换
对于一个健全的类型系统,其子类型必须能够替换父类型
继承的消息是自动的(免费的)而委托,必须了解消息,并明确的委托给另一个对象
开闭原则 对扩展开放 对修改关闭
8 章 组合对象
组合优于继承(这本书没提),组合的风险相对来说更小,更好控制,其两者各有优缺点
运用工厂模式更好的进行对象组合(复杂对象的构建组合)
组合(composition)and 聚合(aggregation)的概念和区别
继承与组合的利弊
9章 设计最划算的测试
编写可更改的代码是一门艺术,依赖于三个技能
1.理解面向对象技术
2.擅长重构代码
3.编写高价值测试
好的设计以最小的成本保留最大的灵活性(易于重构 对未来的变化提供开放点 不过度设计 未来的变化通过重构来实现)
持续的重构是为了让设计得以延续(变化的延续)
重构的概念 不改变代码的外在行为,而只是改善其内部结构
测试的意图(好处)
1.找出错误
2.提供文档 >这个文档是会随着程序自动更新的
不会像纸质文档或者代码中的注释会慢慢陈旧(不持续更新)
3.推迟设计决定
4.支持抽象
5.暴露设计缺陷
为什么不需要测试私有方法(公共接口 文档作用 私有方法不安全会变化 维护起来产生负担)
迪米特法则
不传递依赖
中间的对象是同一个类的话不违反迪米特法则(like hash.keys.sort.join)
使用委托可以解决一部分这样的问题(这样做也有负面效果)
Methods in the public interface should
• Be explicitly identified as such
• Be more about what than how
• Have names that, insofar as you can anticipate, will not change
• Take a hash as an options parameter
基于消息的设计(不以领域模型为中心)
基于消息的设计,是你设计生涯的一个转折点
消息代表需要的功能,由这些功能抽象组合出相关的类
消息往往代表着公共的接口
消息代表类与类之间的交互和依赖
你发送消息不是因为有了类,而是相反的
使用消息来发现对象
创建基于消息的应用程序
形成一个合理的意图
时序图
时序图很好的对消息进行描述,是一种很好的工具(描述与讨论的工具)
时序图是为了描述对象和他们之间传递的消息
用于暴露,实验并最终定义这些接口的工具
时序图是实验性的最终要被丢弃,不要依赖于他们
设计的目标
保证未来最大的灵活性,同事只编写满足今天需求的代码(两者的均衡 运用原则和模式等工具 根据经验和领域知识)