View on GitHub

离散型 UI

代码防腐实用技术

离散型 UI

这一类的需求是展示一个界面。界面上可以非常很多个块。每一块的业务逻辑都可以分离到一个独立的Git仓库里。

称之为离散型是因为“离得比较开”,块与块之间非常独立。

例如下面这样的界面

order-details

数据集成

我们可以使用服务端数据集成的方式来实现这个需求。

data-orchestration

这种集成方式

UI集成

我们可以使用客户端UI集成的方式来实现这个需求。

ui-orchestration

配送信息,付款信息,买家信息的Git仓库同时提供服务端进程,以及客户端的组件。从进程部署上是两个,从Git仓库的角度是一起的。 这种做从一端到另一端贯通的做法,一般也称为“竖切”。

这种集成方式

数据当成UI来集成

虽然在服务端做集成,但是把接口定义成UI一样的黑盒。

例如,这样的伪代码

function getOrderDetail(): Record<string, any> {
    return {
        buyer: getBuyerDetail(),
        fulfilment: getFulfilmentDetail(),
        payment: getPaymentDetail()
    }
}

数据在服务端完成聚合,但是聚合的过程是简单的粘合,就像 UI 组件组合成大界面一样。

这种集成方式

依赖倒置的服务端API

负责集成的服务端API可以在依赖关系上被倒置

server-plugin

服务端API进程在调用关系上不改变。但是从依赖关系上,服务端API的Git仓库不再完成具体业务,而是下沉为底层的“通用数据网关”。

依赖倒置的客户端

负责集成的客户端Git仓库也在依赖关系上被倒置

client-plugin

客户端的Git仓库不再完成所有的具体业务,而是留出界面插槽(Slot),由买家信息,配送信息,付款信息在界面上做填充。 那为何还需要客户端的Git仓库呢,因为仍然需要说明,买家信息,配送新信息,付款信息在同一个页面上的相对布局。

规范型 UI

离散型 UI 如果其界面有规律,例如我们从某打车软件的截图来看:

order-list

似乎可以抽象成规则性组件的重复。那我们可以把规范的条目数据定义成接口,然后使用依赖倒置。统一由订单列表来把规范的条目数据读取出来,渲染到界面上。

repeated-ui-dependency

读取订单列表的时候用 RPC 聚合,也可以是订单列表提供一个数据库,由每个业务线负责写入。这两种做法不改变 Git 仓库之间的依赖关系,从 Autonomy 的角度来说也是一样的。

repeated-ui-runtime

小结

从 Autonomy 的角度来说,使用 UI 做为接口,比使用数据做为接口更能自主变化。 因为展示细节变了,拿 UI 做为接口的情况,接口大概率是不需要修改的。 除非展示需求正好改的是界面布局这样的大尺度上的东西。

如果不使用依赖倒置,每个新需求写在哪个 Git 仓库里,会有一些争议性。比如用数据集成的方式来做这个界面,我们可以在业务API这个Git仓库里做所有的需求,因为它有所有的数据。 那配送信息要做一些日期格式化的调整是去改业务API的Git仓库呢,还是改配送信息的Git仓库呢。 在使用依赖倒置的情况下,接口需要显式地提炼出来,并有意去最小化接口部分。 从而可以让更多的需求改动封闭在更上层的依赖关系里完成,更多去改实现代码,而不是改接口代码。

拿UI做接口,依赖倒置,目的都是让接口改得少。从而使得跨团队的沟通量变小,提高 Autonomy。