最近在代码审查时,会发现一些校招新同学会把一些步骤当做 Service
的方法,在 Facade
层对这些步骤进行编排来完成一个完整的功能。这显然是不太正常的。
Facade
层通常作为前端或者其他服务调用的入口,主要负责参数校验、构造底层服务所需的参数、结果转换等。
不应该将单个业务功能拆分到 Service
中,在 Facade
中对这些方法进行编排,最终完成一个业务功能。
Facade
作为门面,本身不应该有业务逻辑,业务逻辑应该放在 Service
层。Service
的每个方法应该能够独立完成一个相对完整的业务意图,而不是提供某个功能的多个步骤,让外部去组装。
这就像很多地方提供的“最多跑一次”的政策,完成一个业务,跑一次就可以;不需要每一次只完成某个意图的一个步骤。
这就像你在自助咖啡机购买一杯咖啡,你只需要选好类型,支付即可。咖啡的制作可能包括加热水、加咖啡粉、加牛奶、搅拌等步骤,不应该每个流程都需要你知道或者参与。咖啡服务应该是完整的,而不是每个步骤都需要你去按一个按钮去编排。
就像货币兑换服务,你去兑换的窗口去将人民币兑换为泰铢,一般服务是完整的,一般都是把人民币给他们,他们直接给你对应数量的泰铢即可。
而不需要你自己去查询汇率,计算可以换取的数量,自己去他们柜台去拿出钱,自己数,然后自己对自己说“欢迎下次光临”。
门面相当于大众点评的里,用户可以在这里看到目标店铺的位置、开关时间等信息。
你甚至可以在大众点评、美团上下订单,但是还是需要目标店铺提供对应的餐饮服务。
参考《代码整洁之道》 第六章 对象和数据结构一节的一个案例:
封装1:
public interface Vehicle{
double getFuelTankCapacityInGallons();
double getGallonsOfGasoline();
}
封装2:
public interface Vehicle{
double getPercentFuelRemaining();
}
第二种接口定义方式更好,我们不应该暴露数据细节,应该以抽象的方式表达数据,要对定义的接口稍加斟酌。
这主要包括几个方面:
1 设计接口原则尽量隐藏复杂度(最小知道原则)
2 Service 层提供的方法应该表达完整的业务意图(如我要查看油箱还剩多少百分比;而不是提供两个接口,一个是查询总有量是多少,然后再查询当前有量有多少再自己去计算),而不是某个步骤。