iT邦幫忙

2021 iThome 鐵人賽

DAY 4
0
Software Development

在 Ruby on Rails 中導入 Domain-Driven Design 是不是搞錯了什麼?系列 第 4

[DAY4] 一塊大千層蛋糕 — MVC 架構的橫切分層,以及為何需要縱切

先來看看一個預設 Rails 專案的預設資料夾結構:
https://ithelp.ithome.com.tw/upload/images/20210919/20108265vqg1oyF0g7.jpg

我們可以看到,他遵循著 MVC 架構,將各自的檔案分別放到不同的資料夾裡

單體式應用程式 (Monolithic application)

這樣的資料夾結構將整個專案視為同一個系統,而隨著專案的擴張和需求的改變,整個專案系統複雜度會呈指數成長,且因為每個 model 都在同一個資料夾中,所以會很容易沒有意識到需要好好管理model 間的依賴關係,時常出現雙向耦合的情況,而過多的耦合將導致測試難以撰寫,每次開發新功能的成本也急遽攀升。

舉個例子

以下是一個簡單購物系統的 ER-Diagram

https://ithelp.ithome.com.tw/upload/images/20210919/20108265FGmJpU55rl.jpg

在 Rails 中每個 table 都會對應到一個 model,假設現在需要顯示顧客最新訂單裡的所有產品

# Models
class Customer < ActivRecord::Base
	has_many :orders
end

class Order < ActivRecord::Base
	has_many :products, through: :order_product
	belongs_to :customer
	scope :successed_paid, -> { where(status: :paid) }
	scope :latest, -> { where(order_date: :desc).first } 
end
# Product Controller
customer = Customer.find(1)
products = customer.orders.successed_paid.latest.products

在專案前期,透過 rails 的 relation 可以很有效率地滿足需求,但當專案變大,這種寫法反而會造成許多問題。Order 上的 scope 或 method 可能會出現在任何一個 controller 或甚至是 view 上,這樣一來就會有很多地方依賴這個介面的邏輯,但如果未來有某一個依賴介面的地方有新需求,新需求與原本的邏輯不符,這時候很容易會去調整原本大家共通依賴的介面,又沒有找到並調整所有依賴此介面的地方,這時候就會導致原本的功能壞掉。

以上述的例子來說,顧客最新訂單裡的所有產品 在 Order 中管理,卻在 Product Controller 中取用,開發人員難以定義變動的範圍,也不易清楚掌握每個 model 間的依賴關係 (在我們的專案中很常出現雙向耦合的 model)

小結

如果整個程式架構是一塊水果千層,MVC 架構則代表各層餡料,像是對整體程式架構的橫切,而每層則有其各自的責任。此外還需要對這塊蛋糕縱切,對層中的餡料合理布局與管理。
https://ithelp.ithome.com.tw/upload/images/20210919/20108265uD3eyEVNTT.png
下一篇會總結前面遇到的問題,並說明為甚麼一開始我們的專案會選用 (貌似被我處處嫌棄的) Rails 來開發 /images/emoticon/emoticon19.gif


上一篇
[DAY3] MVC與散落各處的邏輯
下一篇
[DAY5] 病識感──當我們關注到測試
系列文
在 Ruby on Rails 中導入 Domain-Driven Design 是不是搞錯了什麼?30

尚未有邦友留言

立即登入留言