温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

设计讨论:依赖倒置,与 “I'll call you”

发布时间:2020-04-13 23:55:15 来源:网络 阅读:549 作者:winters1224 栏目:开发技术

问题来自于我和同事在一个跨系统交互设计上的分歧。


同事的设计,基本上是这样的:

设计讨论:依赖倒置,与 “I'll call you”


这种设计很常见,其基本思路就是:服务端接口需要什么数据,客户端就传入什么数据。这种设计的优点在于简单:开发简单,交互简单。但是它的缺点也很明显:扩展性低。一旦服务端对某个业务中的业务-数据依赖关心进行了修改,则客户端很可能也要跟着修改。例如,如果系统B中,完成业务B1需要的数据不再是D1而是D3,则不光系统B要改,系统A也要改。如果还有系统C/D/E/F也调用了这个接口,那么这些系统都面临着修改代码的风险。


实际上,不仅仅是系统间的服务,在系统内部服务的设计上,这种思路也很常见。我曾经见过一个用作金额计算的类。它的计算公式是a+b/c-d^e,而它对外暴露的方法居然就是public BigDecimal calculate(BigDecimal a, BigDecimal b, BigDecimal c, BigDecimal d, BigDecimal e)。当公式需要扩展为a+b/c-d^e-f时,其中的麻烦可想而知。


造成这种风险、麻烦的原因就在于:这个设计不仅简单的实现了客户端对服务端的业务依赖,而且将服务端内部的控制依赖也暴露、延伸到了客户端。


客户端对服务端的依赖,是一种业务上的“正向”依赖。没有服务端提供的服务,客户端的业务也无法正常的进行下去。

但是,我们在做设计的时候,不应当简单的临摹业务流程。业务流程从A到B,系统设计就画两个方框+一个箭头;这是在为现在的自己偷懒。更不应当把业务流程中的依赖关系过度的延伸出去;这简直是在为三个月后的自己挖坟。


对这一个系统的设计,我的观点就是:系统B把业务-数据间的依赖关系全部收到自己的系统中去。如下图。

设计讨论:依赖倒置,与 “I'll call you”


即,客户端在调用时,提供一个数据主键。服务端根据自己的业务需要,按主键去查询出所需的数据。


这样做的缺点是复杂。代码会复杂,交互也更复杂。由于多了一次交互,性能上会有下降。另外在分布式事务方面还有一点小隐患。

但是这样的优点,恰恰就是易于扩展。只要新业务所需数据仍然落在数据集合D内,那么系统A无需任何改动。


带来这个优点的,就是依赖倒置。虽然在业务上,是客户端依赖于服务端的功能;但是在设计上,是服务端依赖于客户端的数据。并且,这种依赖只是简单的数据依赖。这也是所谓的“好莱坞法则”:Don't call me, I'll call you! 


实际上,同事的设计和我的设计,在我们的系统中都已经有了实践。到目前为止的结果,是按同事的思路设计的另一个系统服务已经经过了二次改造,归入我的思路中了。而按我的思路设计的另一个系统服务,目前在做性能上的优化。


遗憾的是,我没有说服他。他仍然坚持己见,只是在客户端调用接口时,将数据集合D一次性提交到服务端。

这种思路算一个折中。但是,如果服务端所需数据集超过了数据D呢?按他的方案,客户端仍然需要修改;按我的方案,在客户端没有开通对应的查询接口时也需要修改。只不过,客户端是我负责的系统(也许这也是我一直跟他争执的原因之一吧),而这个系统中,已经规划了“每个资源都应有查询服务”。


附,分布式事务上的一点小隐患在于:如果在客户端调用服务端的那个事务中,主键key所对应的数据有部分还未提交,那么,通过查询接口是无法查询到这部分数据的。弥补措施是在服务接口中把这一部分数据传过来,作为“优先”配置或数据,覆盖查询接口中查到的结果。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI