软件架构设计原则一切都是为了下面这两点,别忘了。
这一篇文章我们将要来谈谈 DIP 依赖反向原则。
根据 wiki 它的定义如下 :
高层次的模组不应该依赖於低层次的模组,两者都应该依赖於抽象介面。抽象不要依赖细节,细节要依赖与抽象
之前的同事在分享这个主题时要提到个要点,我觉得很赞 ~
那这里先来问个问题,高层次与低层次是指啥呢 ? 我自已的定义是这样 :
简单说个例子,如果以购物车结帐,则我们可以定义成以为两个高与低模组 :
我知道应该有人会有点 confuse,因为在不少人的专案中根据分层架构,上面的应该都是放在 service 层里或是直接在 controller 层里,然後他们会觉在同一层的东西,应该没有分高、低层次,而只有在 sevice → model 这才是高、低。
我同意我以前也有这样的想法,但和我接触到烂 code… 就发觉… 走到那都会碰到 service 层的 cycle dependency,就觉得如果 :
将分层定义为高层次与低层次要有个前提假设,那就是你实作上真的有分层
以我现在大部份的三层架构,大部份的东西都会挤在 service 层,而这时相信我,他真的要分清楚里面的高层次与低层次… ( 通常这代表可以在拉个层级了 ),不要单纯的用分层来判断,不然你真的会写到怀疑人生。
这里简单给个违反 DIP 的范例,假设我们有个处理订单结帐的模组,然後他里面要使用 atm 来付款,那这里的问题在於 ~ 如果今天要新增信用卡付款,那这里就会需要修改,事实上这里也违反了 OCP 开放封闭原则。
而这里 DIP 违反了『 高层次 ( OrderCheckout ) 依赖低层次 ( AtmPayment ) 』,这就会导致,如果不在提供 atm 或是新增信用卡付款,这里都需要大改。
// Bad
class OrderCheckoutService{
order: any
constructor(order: any){
this.order = order
}
execute(){
const payment = new AtmPayment() <-----!!! 这个依赖了 AtmPayment
payemnt.execute(this.order)
}
}
首先要先将高层次的 OrderCheckout 所依赖的抽象个 interface 出来,并且低层次的 AtmPayment 也依赖这个 interface。
interface IPayment{
execute(order: any): void
}
class ATMPayment implements IPayment{
execute(order: any){
console.log('ATM pay')
}
}
然後在将高层次的 OrderCheckout 修改成如下,这样就算这个订单之後要改用 line pay 或啥的,就只要新增一个低层次的付款模组,然後在依赖 IPayment 并实作,高层次模式在指定使用就好了。
class OrderCheckoutService{
order: any
constructor(order: any){
this.order = order
}
execute(payment: IPayment){
payment.execute(this.order)
}
}
const orderCheckoutService = new OrderCheckoutService('order')
orderCheckoutService.execute(new ATMPayment())
老样子,来问一下三个问题,来加深记忆
这个原则基本上帮我们解释了,『 高层次模组与低层次模组要如何解耦 』,这也代表它是往软件设计原则中的『 低耦合 』前往。
像咱们公司的 service 层基本上就没有符合 DIP,这也导致以下两个问题 :
这里事实上有几个知识点可以连结 :
我年轻时是从 php laravel container 那得到的知识,可以参考一下。
>>: TailwindCSS 从零开始 - 增加 Base 样式
延续昨日 今天来完善我们的 我的专案的功能吧! 首先这是目前的我的专案 再来新增2个按钮 嘟嘟噜新增...
识别威胁 在前面的概论中,我们知道威胁是外来的,他必须配合资产才会产生风险,所以资产与威胁是相互之...
DAY20 MongoDB Oplog 玩坏它 把手弄脏,亲眼於本机见证节点同步跟不上 本篇的目的就...
今天要分享的故事是关於我在今年初开始经营粉丝专页的收获! 进入正题 虽然现在的年轻人更偏好使用 In...
正文 今天要来开机器,先去下载server版的Ubuntu 20.04 iso,因为以前自己做环境练...