分布式系统或者清楚的分层系统中,客户端与服务端的职责需要界定,直接影响到了接口的定义。
原则一:客户端对细节透明
细节要封装成类型,让客户端依赖于类型(比如Enum,抽象类的子类,接口的实现类)来明确行为。客户端尽量做到只调用,简化调用。
在开发接口时,尽量做到对客户端友好。比如SNS模块中,以前发送微博的内容交给了客户端,客户端需要了解如何去构造微博的内容。考虑的东西很多。现在对于客户端都透明。客户端只需了解发送的类型
理解了这条原则,学习设计模式的时候,就会发现各种模式的目的都是客户端不依赖细节。将细节或变化的内容抽取到类中。
备忘录模式,如果不使用备忘录模式,客户端依赖需要了解具体的过程的状态值。备忘录模式的一个很好的场景是游戏状态保存,当打怪失败后,可以基于保存的状态重新开始。类似需要记录中间状态的场景都可以使用。
同样,如果不使用责任链,客户端需要了解各种角色并决定哪个角色来审核具体的请求。这样细节对客户端不透明。
责任链模式类似于数据结构中的链表。当前节点持有下一个节点的指针。如果超出当前节点的处理范围,就调用下一个节点的处理方法去处理。直至处理完。
常见的责任链比如需要层层审批的流程:比如请求(比如请假,加薪的额度)需要经理到总监到CEO审批。
广告系统的过滤也满足。
责任链是一个典型的自己聚合自己的示例。UML中一定要明确聚合,关联,依赖。
迭代器模式目的是当需要提供多种迭代方式,比如按从前到后,从后到前,从高到矮,从胖到廋,index等方式将迭代器封装好,客户端不需要关心迭代的细节,需要迭代器模式。
自定义迭代器通常用于遍历聚合体。
另外一个特点是高级语言都提供了一些现成的迭代方式,比如默认foreach就是将集合中的元素按照index去迭代。这导致迭代器模式的使用场景减少。Martin Flower甚至建议去掉该模式。
原则2 :分布式系统,FE与BE之间的通过存在overdelay。通常FE中不循环调用BE的接口。而是重构让BE接口支持批量元素处理。注意一点,并不是批量接口就可以一次调用把参数全部传给BE. 如果FE与BE是基于HTTP请求,还要考虑到请求参数的大小限制。所以,最好是在前端做batch调用。
原则3:分布式系统,存在FE与BE分别bounce的情况,如果功能的实现涉及到了FE,BE的修改,则bounce的顺序是BE->FE. 这样就会存在一个时间差,即BE bounce而FE未bounce完成这个时间段,所以,对于BE API,就需要同时支持新旧signature并且@Deprecated旧的signature, 当FE bounce完成后,就可以将旧的signature去掉,再次bounce BE。
注意,错误的方式为了保持开发阶段方便,比如FE与BE为了避免频繁的API约定。而将API的签名做成可扩展。比如参数是一个自定义的类,可以在里面塞任意多的属性来扩展。但是这种方式无法做到新旧兼容。