从接口设计看业务分层

发布时间 2023-09-19 11:33:01作者: ~鲨鱼辣椒~

最近在做功能更改时,发现一个接口设计很有趣,其中涉及一些代码设计方面的值得思考的内容。

背景

以下是一个相对简单的优惠券列表功能。不同的优惠券具有不同的描述,而描述内容会受到一定的业务规则影响。例如,满5元可用的兑换券将显示为"满5.01可用",而无订单限制的兑换券将显示为"仅支付0.01元"。

image-20230919100504959

用户模型大致如下所示

image-20230919102434397

从后端的角度,查询接口提供统一的数据接口,按照业务模型将数据返回,前端特殊的显示需求由前端进行处理,但是这样处理存在两个问题,一是如果多种移动端(iOS、android、小程序)那么就需要各个移动端各自处理,导致逻辑分散且无法统一;二是如果显示需求发生变更,iOS和Android需要升级新版本才能获得新功能。

基于以上两个问题,决定通过后端接口直接返回所需的显示数据,让前端根据数据进行显示。这样,如果显示需求变更,只需后端进行相应更改即可。

代码实现

按照经典三层架构来设计,请求层,业务处理层,数据层各领其责,显示相关逻辑在服务层中进行处理,经过上线测试,功能符合预期,没有出现任何问题。

image-20230919104244446

但是上面的代码隐隐透漏出坏味道,因为显示逻辑侵入了优惠券查询业务中。如果以后有其他显示业务逻辑,必然也会在同一处进行处理,导致代码逻辑越来越复杂。

那么如何解决类似的问题呢?回归到我们的代码设计,我们既希望保证查询逻辑的职责单一,又要实现显示逻辑。合理的业务分层可能是一个解决方案。

从领域驱动设计的角度来看,我们的核心业务是用户优惠券的查询,而额外功能是与显示相关的需求。因此,我们可以按照以下方式进行代码分层:

image-20230919110113680

按照以上代码分层,既能确保核心业务逻辑的职责单一,又能隔离显示相关需求的实现。当然,领域驱动中各层的命名并不重要,但这种分层隔离的思想值得在业务代码中借鉴。

当然肯定还有其他的方式可以对上面的代码进行一些优化更改,但是回过头来再看我们的代码实现,有一个原则需要贯穿始终,那就是职责单一,接口的职责单一某种程度上意味着代码腐化程度的高低。