Feature of Good Design (1) 优秀设计的特点(一)
Code reuse 代码复用
-- Challenge: tight coupling between components, dependencies on concrete classes instead of interfaces, hardcoded operations
-- Solution: design patterns
-- 挑战:组件之间的紧密耦合、对具体类而不是接口的依赖、硬编码操作
-- 解决方案:设计模式
• However, sometimes making components more complicated
然而,有时会使组件变得更加复杂
-- Three levels of reuse: a piece of wisdom from Erich Gamma
-- 三个层次的重用:Erich Gamma 的智慧
• Lowest: classes
最低:类
• Highest: frameworks
最高:框架
• Middle level: design patterns
中层:设计模式
Feature of Good Design (2) 优秀设计的特点(二)
Extensibility 可扩展性
Change is the only constant thing in a programmer's life
-- 变化是程序员一生中唯一不变的事情
• We understand the problem better once we start to solve it
一旦我们开始解决问题,我们就会更好地理解问题
• Something beyond your control has changed
你无法控制的事情已经发生了变化
• Objectives/requirements have changed
目标/要求已改变
-- Prepare for possible future changes when designing an architecture
-- 设计结构时为未来可能发生的变化做好准备
Good Design Principles (1) 良好的设计原则(1)
Encapsulate what varies 封装不同的内容
-- Identify the aspects of your application that vary, and separate them from what stays the same
-- 识别应用程序中不同的方面,并将它们与保持不变的部分区分开来
-- Main goal: minimize the effect caused by changes
-- 主要目标:最小化变化造成的影响
-- Isolating program parts that vary in independent modules, protecting the rest
-隔离独立模块中不同的程序部分,保护其余部分
-- Encapsulation on a method level
-- 方法级别的封装
-- Encapsulation on a class level
-- 类级别的封装
Good Design Principles (2) 良好的设计原则(2)
Program to an interface, not an implementation 对接口编程,而不是实现
-- In other words, depend on abstractions, not on concrete classes
-- 换句话说,依赖于抽象,而不是具体的类
-- The design is flexible enough if you can easily extend it without breaking existing code
-- 如果您可以轻松地扩展它而无需破坏现有代码,那么该设计就足够灵活
-- A possible approach
- Determine what exactly one object needs from the other: which methods does it execute?
确定一个对象到底需要另一个对象什么:它执行哪些方法? - Describe these methods in a new interface or abstract class.
在新的接口或抽象类中描述这些方法。 - Make the class that is a dependency implement this interface.
使作为依赖项的类实现此接口。 - Make the second class dependent on this interface rather than on the
concrete class.
使第二个类依赖于该接口而不是具体的类。
Good Design Principles (3) 良好的设计原则(3)
Favor composition over inheritance 优先考虑组合而不是继承
-- Challenge of inheritance
-- 继承的挑战
• A subclass can't reduce the interface of the superclass
子类不能减少超类的接口
• When overriding methods you need to make sure that the new behavior is compatible with the base one
重写方法时,您需要确保新行为与基本行为兼容
• Inheritance breaks encapsulation of the superclass
继承破坏了超类的封装
• Subclasses are tightly coupled to superclasses
子类与超类紧密耦合
• Trying to reuse code through inheritance can lead to creating parallel inheritance hierarchies
尝试通过继承重用代码可能会导致创建并行继承层次结构
SOLID Principles
SOLID 1: Single Responsibility Principle 单一职责原则
A class should have just one reason to change
一个类应该只有一个改变的理由
-- Try to make every class responsible for a single part of functionality,and make that responsibility entirely encapsulated
-- 尝试让每个类负责一部分功能,并完全封装该职责
• Main goal: reducing complexity, and reducing risks
主要目标:降低复杂性并降低风险
SOLID 2: Open/Closed Principle 开闭原理
- Classes should be open for extension but closed for modification
类应该对扩展开放,但对修改关闭
-- Keep existing code from breaking when implementing new features
-- 在实现新功能时防止现有代码被破坏 - A class is open if it can be extended by subclasses
如果一个类可以通过子类扩展,则该类是开放的 - A class is closed if it is 100% ready to be used by others
如果一个类 100% 可供其他人使用,则该类已关闭 - A class can be both open (for extension) and closed (for modification) at the same time
一个类可以同时开放(用于扩展)和封闭(用于修改)
-- Not necessary to be applied for all changes
-- 无需应用所有变更
SOLID 3:Liskov Substitution Principle 里氏替换原理
-
When extending a class, ensure the capability of passing objects of the subclass in place of objects of the parent class without breaking the client code
扩展类时,保证能够通过子类的对象代替父类的对象,而不破坏客户端代码
-
The subclass should remain compatible with the behavior of the superclass
子类应该与超类的行为保持兼容
-- When overriding a method, extend the base behavior rather than replacing it with something else entirely
重写方法时,扩展基本行为而不是完全用其他东西替换它
-
Especially critical when developing libraries and frameworks
在开发库和框架时尤其重要
-
A set of checks
一组检查
- (a) Parameter types in a method of a subclass should match or be more abstract than parameter types in the method of the superclass.
子类方法中的参数类型应与超类方法中的参数类型匹配或更抽象。 - (b) The return type in a method of a subclass should match or be a subtype of the return type in the method of the superclass.
子类方法中的返回类型应该与超类方法中的返回类型匹配或者是其子类型。 - (c) Types of exceptions should match or be subtypes of the ones that the base method is already able to throw.
异常类型应该与基方法已经能够抛出的异常类型匹配或者是其子类型。 - (d) A subclass shouldn't strengthen pre-conditions.
子类不应强化先决条件 - (e) A subclass shouldn't weaken post-conditions.
子类不应削弱后置条件 - (f) Invariants of a superclass must be preserved (least formal rule of all)
必须保留超类的不变量(至少所有正式规则) - (g) A subclass shouldn't change values of private fields of the superclass.
子类不应更改超类的私有字段的值。
- (a) Parameter types in a method of a subclass should match or be more abstract than parameter types in the method of the superclass.
SOLID 4: Interface Segregation Principle 接口隔离原则
Clients shouldn't be forced to depend on methods they do not use
不应强迫实现代码依赖他们不使用的方法
-- Make interfaces narrow enough that client classes don't have to implement
behaviors they don't need
-- 使接口足够窄,以便实现代码类不必实现它们不需要的行为
-- Break down "fat" interfaces into more granular and specific ones
-- 将"胖"接口分解为更细粒度和更具体的接口
SOLID 5: Dependency Inversion Principle 依赖倒置原则
- High-level classes shouldn't depend on low-level classes, and both should depend on abstractions
高级别的类不应该依赖于低级别的类,并且两者都应该依赖于抽象 - Problem: business logic classes tend to become dependent on primitive low-level classes
问题:业务逻辑类往往会依赖于原始的低级类 - Suggestion: changing the direction of dependency
建议:改变依赖方向 - Approach
- Describe interfaces for low-level operations that high-level classes rely on, preferably in business terms
描述高级类所依赖的低级操作的接口,最好用业务术语 - Make high-level classes dependent on the interfaces, resulting in a softer dependency
使高级类依赖于接口,从而产生更软的依赖关系 - Low-level classes implement the interfaces, dependent on the business logic level
低级类实现接口,依赖于业务逻辑级别
- Describe interfaces for low-level operations that high-level classes rely on, preferably in business terms