We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
单一职责原则主要讨论的是函数和类之间的关系——但是它在两个讨论层面上会以不同的形式出现。在组件层面,我们可以将其称为共同闭包原则(Common Closure Principle),在软件架构层面,它则是用于奠定架构边界的变更轴心(Axis of Change)
calculatePay() 函数是由财务部门制定的,他们负责向 CFO 汇报。 reportHours() 函数是由人力资源部门制定并使用的,他们负责向 COO 汇报。 save() 函数是由 DBA 制定的,他们负责向 CTO 汇报。
尽管report hours和calculate pay有相似的需求, 都需要统计出勤日期, 但是本质上他们是对两件事负责, 一个Employee对三个actor(身份,角色) 负责, 这就不符合单一职责.
OCP 是我们进行系统架构设计的主导原则,其主要目标是让系统易于扩展,同时限制其每次被修改所影响的范围。实现方式是通过将系统划分为一系列组件,并且将这些组件间的依赖关系按层次结构进行组织,使得高阶组件不会因低阶组件被修改而受到影响。
猛地一看可能会被这个图吓到, 但是这个图所展现的层次依赖关系是非常清晰明了的. 入口/逻辑/数据/渲染层次清晰, 层和层之间解耦的手法都是经典中的经典
信息隐藏: 这种传递性依赖违反了“软件系统不应该依赖其不直接使用的组件”这一基本原则
LSP 可以且应该被应用于软件架构层面,因为一旦违背了可替换也该系统架构就不得不为此增添大量复杂的应对机制。
这个原则是在强调什么是子类型, 只有完全可以替换才是子类型, 像三角形和正方形, 设置他们的参数就可能统一, 那他们就不是可替换的类型
任何层次的软件设计如果依赖了它并不需要的东西,就会带来意料之外的麻烦。
在这种情况下,如果 D 中包含了 F 不需要的功能,那么这些功能同样也会是 S 不需要的。而我们对 D 中的这些功能的修改将会导致 F 需要被重新部署,后者又会导致 S 的重新部署。更糟糕的是,D 中一个无关功能的错误也可能会导致 F 和 S 运行出错。
接口隔离原则是说, 不要传递引用, 而是把自己需要的一小部分接口定义出来, 不要依赖自己不需要的东西
如果我们改了接口, 那么一定要改实现, 但是改了实现不一定会改接口. 我们需要让自己定义的接口比实现要稳定的多. 毕竟争取在不修改接口的情况下为软件增加新的功能是软件设计的基础常识。 (这一点要花费很大力气才能做到)
作者给出以下建议
Application 类是通过 Service 接口来使用 Concretelmpl 类的. 但是我们不想让Concretelmpl被感知, 所以在Service接口创建一个工厂, 返回service. 这条曲线将整个系统划分为两部分组件:抽象接口与其具体实现。抽象接口组件中包含了应用的所有高阶业务规则,而具体实现组件中则包括了所有这些业务规则所需要做的具体操作及其相关的细节信息。
需要注意
我们在软件系统中并不可能完全消除违反 DIP 的情见通常只需要把它们集中于少部分的具体实现组件中,将其与系统的其他部分隔离即可。 绝大部分系统中都至少存在一个具体实现组件 我们一般称之为 main 组化 因为它们通常是 main 函数所在之处。在 图 11.1 中,函数应该负责创建 ServiceFactoryImpl 实例,并将其赋值给类型为 ServiceFactory 的全局变量,以便让 Application 类通过这个全局变量来进行相关调用。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
架构整洁之道
单一职责原则
calculatePay() 函数是由财务部门制定的,他们负责向 CFO 汇报。
reportHours() 函数是由人力资源部门制定并使用的,他们负责向 COO 汇报。
save() 函数是由 DBA 制定的,他们负责向 CTO 汇报。
尽管report hours和calculate pay有相似的需求, 都需要统计出勤日期, 但是本质上他们是对两件事负责, 一个Employee对三个actor(身份,角色) 负责, 这就不符合单一职责.
OCP 开闭原则 THE OPEN-CLOSED PRINCIPLE
猛地一看可能会被这个图吓到, 但是这个图所展现的层次依赖关系是非常清晰明了的. 入口/逻辑/数据/渲染层次清晰, 层和层之间解耦的手法都是经典中的经典
信息隐藏: 这种传递性依赖违反了“软件系统不应该依赖其不直接使用的组件”这一基本原则
LSP 里氏替换原则 THE LISKOV SUBSTITUTION PRINCIPLE
这个原则是在强调什么是子类型, 只有完全可以替换才是子类型, 像三角形和正方形, 设置他们的参数就可能统一, 那他们就不是可替换的类型
ISP 接口隔离原则 THE INTERFACE SEGREGATION PRINCIPLE
在这种情况下,如果 D 中包含了 F 不需要的功能,那么这些功能同样也会是 S 不需要的。而我们对 D 中的这些功能的修改将会导致 F 需要被重新部署,后者又会导致 S 的重新部署。更糟糕的是,D 中一个无关功能的错误也可能会导致 F 和 S 运行出错。
接口隔离原则是说, 不要传递引用, 而是把自己需要的一小部分接口定义出来, 不要依赖自己不需要的东西
DIP 依赖反转原则 THE DEPENDENCY INVERSION PRINCIPLE
如果我们改了接口, 那么一定要改实现, 但是改了实现不一定会改接口. 我们需要让自己定义的接口比实现要稳定的多. 毕竟争取在不修改接口的情况下为软件增加新的功能是软件设计的基础常识。 (这一点要花费很大力气才能做到)
作者给出以下建议
抽象工厂
Application 类是通过 Service 接口来使用 Concretelmpl 类的. 但是我们不想让Concretelmpl被感知, 所以在Service接口创建一个工厂, 返回service.
这条曲线将整个系统划分为两部分组件:抽象接口与其具体实现。抽象接口组件中包含了应用的所有高阶业务规则,而具体实现组件中则包括了所有这些业务规则所需要做的具体操作及其相关的细节信息。
需要注意
The text was updated successfully, but these errors were encountered: