应用架构的最佳实践

应用架构的本质

架构这个词,我们经常会聊起,那什么是架构呢,这个问题,我相信十个人会有二十种答案,我想翻一翻Neal Ford的《软件架构》找一找定义,但又一想,貌似他的定义不如知乎来的更篇幅少,于是我得到了这样的回答:软件架构这项工作的实质就是:如何将系统切分成组件,并安排好组件之间的排列关系,以及组件之间的相互通信的方式。还不错的定义,这句话基本可以描述成下面这样

架构 = 组件 + 相互关系 + 指导原则

对于应用架构而言,同样适用,代码就是我们“组件”,整体工作就是要如何处理模块(Module)、组件(Component)、包(Package)和类(Class)之间的关系。简而言之,应用架构就是要解决代码要如何被组织的问题。

好的应用架构,也遵循一些共同模式,不管是六边形架构、洋葱圈架构、整洁架构,都提倡以业务为核心,解耦外部依赖,分离业务复杂度和技术复杂度。

业务为核心

我们很多的老兵,看到这个词的时候,会很不理解,为什么在应用架构层,还要讲业务为核心呢,我写的代码不就是在解决业务问题吗,怎么不是以业务为核心呢,同时会给我丢过来这样一个代码。

我看了下,这种代码很优秀,我们可以清晰的看出,这段代码 应该是用户根据档位进行提现,执行了下面几个步骤

  1. 校验提现的档位是否正确

  1. 判断是否是新手档位,

  1. 校验用户绑定信息

  1. 扣减金币

  1. 给用户打钱

典型的过程式代码。他可以解决非常多的场景,像我们熟悉的spring,最复杂的refresh 方法,基本上也就是这样的写法。

但是这类的写法会有两个问题,第一个是,会丢失领域知识,第二个是,代码的业务语义表达能力比较弱。我们可以选择另外一种方式替换这种过程式代码。

最佳实践

分层结构

所有的复杂系统都会呈现出层级结构,如果网络协议不是四层,而是一层,意味着,你要在应用层去处理链路层的bit数据流会是怎样的情景吗?同样,应用系统处理复杂业务逻辑也应该是分层的,下层对上层屏蔽处理细节,每一层各司其职,分离关注点,而不是一个ServiceImpl解决所有问题。

对于一个典型的业务应用系统来说,我们会做如下层次定义,每一层都有明确的职责定义:

  • 应用层(Application Layer):主要负责获取输入,组装上下文,调用领域层做业务处理, 发送消息通知等。

  • 领域层(Domain Layer):主要是封装了核心业务逻辑,并通过领域服务(Domain Service)和领域对象(Domain Entity)的方法对App层提供业务实体和业务逻辑计算。领域是应用的核心,不依赖任何其他层次;

  • 基础实施层(Infrastructure Layer):主要负责技术细节问题的处理,比如数据库的CRUD、搜索引擎、文件系统、分布式服务的RPC等。此外,领域防腐的重任也落在这里,外部依赖需要通过转义处理,才能被上面的App层和Domain层使用。

包结构

包结构应该有如下表现:

常见的包形态

层次

包名

功能

必选

infra

repo

处理数据库等存储的实现

infra

config

配置信息

infra

sender

埋点等消息发送的实现

infra

controller

处理请求的实现

application

service

组装上下文,调用领域层做业务处理

application

sender

消息发送的定义,由infra层实现

domain

entity

领域模型的定义

domain

factory

模型的创建

domain

service

领域能力

依赖倒置

在我们上面的层次里,我们可以很明显的发现,我们的依赖关系完全是一种内外层次的关系。如果用图形来表达出来,就是下面这样,所有的关系都是在由外向里依赖。

这样做有什么好处呢,主要体现在两个方面。

首先,在我们的理解里,最核心的是业务,我们所做的一切都在围绕着业务场景,技术的实现完全要服务于业务场景。举个例子,存在着一个给用户发送验证码的业务场景,因此我们需要调用一个三方的服务,把验证码发出去。这里发送验证码这个业务场景,是上游,这个场景不存在了,我们调用三方发验证码的实现,也就没有意义了,而如果场景一直存在,可能会发生的变化是,我们会根据三方服务的价钱变动,更换不同的厂商,厂商变了,调用服务的具体方式也会发生变化,因此从变化频率的角度来看,我们将技术的实现放在最外层,让他向内依赖更稳定的业务场景。

另外,我们从副作用的角度来理解,在整个层次里,infra 里定义了所有的基础实现,而我们最有可能发生难以预料的异常场景,就是在infra 里,比如说,数据库突然连接不上了,消息中间件突然挂掉了,这是我们难以预料,但却可能随时发生,是典型的副作用,因此我们将可能存在副作用的模块放在最外层,保证里面的domain层,可以进行能力上的单测,同时让他向内依赖无副作用的业务核心逻辑。

模型定义的方法

事件分析

通过事件风暴的方法,进行业务问题的拆解。最后得到领域模型。

能力下沉

建模一定不是可以一蹴而就的,我们的模型具备哪些能力同样不是一簇而就的。所谓的能力,简单说就是我们的实体他应该具备的方法有哪些, 或者说我们的domainservice 应该有哪些发放。我们可以采用能力下沉的方法,反复迭代,所谓能力下沉就是,经过我们一定的拆解,发现在不同的case 里,我们会发现存在着step ,有着很大的共性。这个时候,我们可以考虑做个抽象,去思考它是否是归属某个领域的某个能力,去做个能力的下沉。这个时候可以沉淀到 domain service 做个能力,也可以沉掉到domain 里做个能力,这里取决于粒度。如果他横跨多个模型,那只能是domainservice ,如果他很内聚,同时他很自洽,那就可以放进模型里。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值