架构整洁之道
2018-11-16 10:29:30 0 举报
AI智能生成
架构整洁之道
作者其他创作
大纲/内容
软件架构
整洁架构
在架构设计时,我们应设计出干净的应用层和领域层,保持它们对业务逻辑的专注,
而不掺杂任何具体的技术实现,从而完成领域与技术之间的完全隔离,
这一思想被 Robert Martin 称之为整洁架构(Clean Architecture)
而不掺杂任何具体的技术实现,从而完成领域与技术之间的完全隔离,
这一思想被 Robert Martin 称之为整洁架构(Clean Architecture)
该架构思想提出的模型并非传统的分层架构,
而是类似于一个内核模式的内外层架构,由内及外分为四层,包含的内容分别为:
而是类似于一个内核模式的内外层架构,由内及外分为四层,包含的内容分别为:
企业业务规则(Enterprise Business Rules)
应用业务规则(Application Business Rules)
接口适配器(Interface Adapters)
框架与驱动器(Frameworks & Drivers)
注意“企业业务规则”与“应用业务规则”的区别,
前者是纯粹领域逻辑的业务规则,后者则面向应用,
需要串接支持领域逻辑正常流转的非业务功能,通
常为一些横切关注点,如日志、安全、事务等,从
而保证实现整个应用流程(对应一个完整的用例)。
前者是纯粹领域逻辑的业务规则,后者则面向应用,
需要串接支持领域逻辑正常流转的非业务功能,通
常为一些横切关注点,如日志、安全、事务等,从
而保证实现整个应用流程(对应一个完整的用例)。
特征
层次越靠内的组件依赖的内容越少,处于核心的 Entities 没有任何依赖。
层次越靠内的组件与业务的关系越紧密,因而越不可能形成通用的框架。
Entities 层封装了企业业务规则,准确地讲,它应该是一个面向业务的领域模型。
Use Cases 层是打通内部业务与外部资源的一个通道,
因而提供了输出端口(Output Port)与输入端口(Input Port),
但它对外的接口展现的其实是应用逻辑,或者说是一个用例。
因而提供了输出端口(Output Port)与输入端口(Input Port),
但它对外的接口展现的其实是应用逻辑,或者说是一个用例。
Gateways、Controllers 与 Presenters 其本质都是适配器(Adapter),
用于打通应用业务逻辑与外层的框架和驱动器,实现逻辑的适配以访问外部资源。
用于打通应用业务逻辑与外层的框架和驱动器,实现逻辑的适配以访问外部资源。
系统最外层包括框架和驱动器,负责对接外部资源,
不属于系统(仅指限界上下文而言)开发的范畴,但选择这些框架和驱动器,|
是属于设计决策要考虑的内容。这一层的一些组件甚至与要设计的系统不处于同一个进程边界。
不属于系统(仅指限界上下文而言)开发的范畴,但选择这些框架和驱动器,|
是属于设计决策要考虑的内容。这一层的一些组件甚至与要设计的系统不处于同一个进程边界。
按照整洁结构设计出来的系统所具有的的特征
独立于框架:这些系统的架构并不依赖某个功能丰富的框架之中的某个函数。
框架可以被当成工具类使用,但不需要让系统来适应框架
框架可以被当成工具类使用,但不需要让系统来适应框架
独立于UI:这些系统的UI变更起来很容易,不需要需改其他的系统部分
独立于数据库:我们可以轻易将这些系统使用的Oracle、SQL Server替换成MySQL,因为业务逻辑与数据库之间已经完成了解耦
独立于任务外部机构:这些系统的业务逻辑并不需要知道任何其他外部接口的存在
组件构建原则
组件聚合
复用/发布等同原则
软件复用的最小粒度应等同于其发布的最小粒度
共同闭包原则
应该将那些会同时修改,并且为相同目的而修改的类放到同一个组件中,
而将不会同时修改,并且不会为了相同目的而修改的那些类放到不同的组件中
而将不会同时修改,并且不会为了相同目的而修改的那些类放到不同的组件中
共同复用原则
不要强迫一个组件的用户依赖他们不需要的东西
组件耦合
无依赖循环原则
组件依赖关系图中不应该出现环
自上而下的设计
稳定依赖原则
稳定抽象原则
一个组件的抽象化程度应该与其稳定性保持一致
软件架构是什么
底层设计细节共同支撑了顶层的架构设计,底层设计信息和高层架构信息不可分割,他们一起构成了整个软件系统
软件架构的终极目标就是用最小的人力成本来满足构建和维护系统的需求
会持续低估那些好的、良好设计的、整洁的代码的重要性,最典型的口头禅就是“暂时先写死,后续再优化”,可以每次上线之后这段代码就没人再提起了,自然重构的时机也不会再有了。都忙于开发新功能,新功能都做不完,哪里还有时间去重构老的代码,而且老的代码运行的好好的为什么要改?如此往复循环,系统里面就一团乱麻,代码持续腐化,生产效率下降,整个项目环境恶劣,无法留住人,新来的一看烂代码呆不了几天就走了
编程范式
结构化编程:对程序控制权的直接转移进行了限制和规范
面向对象编程:对程序控制权的间接转移进行了限制和规范
函数式编程:对程序中的复制进行了限制和规范
面向对象的五大设计原则
SRP:Single Responsibility Principle单一职责原则
任何一个软件模块都应该有且仅有一个被修改的原因
任何一个软件模块都应该只对某一类行为负责
在类中的一切都与该单一目的有关,即内聚性。
这并不是说类只应该含有一个方法或属性。
这并不是说类只应该含有一个方法或属性。
类中可以包括很多成员,只要它们与单一的职责有关。
当类改变的一个原因出现时,类的多个成员可能多需要修改。也可能多个类将需要更新。
当类改变的一个原因出现时,类的多个成员可能多需要修改。也可能多个类将需要更新。
单一职责原则主要是讨论函数和类之间的关系,但是它在两个讨论层面上会以不同的形式出现。
在组件层面上,我们可以将其称为共同闭包原则(Common Closure Principle),
在软件架构层面,它则是用于奠定架构边界的变更轴心
在组件层面上,我们可以将其称为共同闭包原则(Common Closure Principle),
在软件架构层面,它则是用于奠定架构边界的变更轴心
OCP:Open Closed Principle开闭原则
类应该对扩展开放但对修改封闭。
“对扩展开放”指的是设计类时要考虑到新需求提出时类可以增加新的功能。
“对修改封闭”指的是一旦一个类开发完成,除了改正bug就不再修改它。
“对扩展开放”指的是设计类时要考虑到新需求提出时类可以增加新的功能。
“对修改封闭”指的是一旦一个类开发完成,除了改正bug就不再修改它。
通常来说可以通过依赖关系的抽象实现开闭原则,比如接口或抽象类而不是具体类。
通过创建新的类实现接口来增加功能。
通过创建新的类实现接口来增加功能。
在项目中应用OCP原则可以限制代码的更改,一旦代码完成,测试和调试之后就很少再去更改。
这减少了给现有代码引入新bug的风险,增强软件的灵活性。
这减少了给现有代码引入新bug的风险,增强软件的灵活性。
OCP是我们进行系统架构设计的主导原则,其主要目标是让系统易于扩展,同时限制其每次被修改所影响的范围。
实现方式是通过将系统划分为一系列组件,并且将这些组件间的依赖关系按层次结构进行组织,
使得高阶组件不会因低阶组件被修改而受到影响
实现方式是通过将系统划分为一系列组件,并且将这些组件间的依赖关系按层次结构进行组织,
使得高阶组件不会因低阶组件被修改而受到影响
LSP:Liskov Substitution Principle里氏替换原则
一个对象在其出现的任何地方,都可以用子类实例做替换,并且不会导致程序的错误。
换句话说,当子类可以在任意地方替换基类且软件功能不受影响时,这种继承关系的建模才是合理的。
换句话说,当子类可以在任意地方替换基类且软件功能不受影响时,这种继承关系的建模才是合理的。
因此,所有的子类必须按照和他们父类相同方式操作。
子类的特定功能可能不同,但是必须符合父类的预期行为。
要成为真正的行为子类型,子类必须不仅要实现父类的方法和属性,也要符合其隐含行为。
子类的特定功能可能不同,但是必须符合父类的预期行为。
要成为真正的行为子类型,子类必须不仅要实现父类的方法和属性,也要符合其隐含行为。
一般来说,如果父类型的一个子类型做了一些父类型的客户没有预期的事情,那这就违反LSP。
比如一个派生类抛出了父类没有抛出的异常,或者派生类有些不能预期的副作用。
基本上派生类永远不应该比父类做更少的事情。
比如一个派生类抛出了父类没有抛出的异常,或者派生类有些不能预期的副作用。
基本上派生类永远不应该比父类做更少的事情。
LSP可以被应用于软件架构层面,因为一旦违背了可替换性,该系统架构就不得不为此添加大量复杂的应对机制
ISP:Interface Segregation Principle接口隔离原则
指出客户不应该被强迫依赖于他们不使用的接口。
当我们使用非内聚的接口时,ISP指导我们创建多个较小的内聚度高的接口
当我们使用非内聚的接口时,ISP指导我们创建多个较小的内聚度高的接口
当你应用ISP时,类和他们的依赖使用紧密集中的接口通信,最大限度地减少了对未使用成员的依赖,并相应地降低耦合度。
小接口更容易实现,提升了灵活性和重用的可能性。由于很少的类共享这些接口,为响应接口的变化而需要变化的类数量降低,
增加了鲁棒性。基本上,这里的教训是“不要依赖你不需要的东西”。
小接口更容易实现,提升了灵活性和重用的可能性。由于很少的类共享这些接口,为响应接口的变化而需要变化的类数量降低,
增加了鲁棒性。基本上,这里的教训是“不要依赖你不需要的东西”。
DIP:Dependency Inversion Principle依赖反转原则
第一,高层次模块不应该依赖于低层次模块;他们应该依赖于抽象。
第二,抽象不应该依赖于细节;细节依赖于抽象。方法是将类孤立在依赖于抽象形成的边界后面。
如果在那些抽象后面所有的细节发生变化,那我们的类仍然安全。这有助于保持低耦合,使设计更容易改变。
第二,抽象不应该依赖于细节;细节依赖于抽象。方法是将类孤立在依赖于抽象形成的边界后面。
如果在那些抽象后面所有的细节发生变化,那我们的类仍然安全。这有助于保持低耦合,使设计更容易改变。
0 条评论
下一页