[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


<<:  [第五天]从0开始的UnityAR手机游戏开发-如何在Vuforia创建可辨识图片

>>:  DAY19 搞样式--CSS Gird 怎麽用(上)?

CSS微动画 - 了解Animation并做出更多效果吧!

Q: 是时候表演真正的技术了? A: 要动起来是少不了animation属性的! 本篇开始将使用a...

Day7-Go回圈

前言 回圈基本上是每个程序语言必备的函式,藉以回圈来达成反覆或是循环的动作。而 Go 语言的回圈种类...

ISO 15408&SAMM&CMMI&FOCI

通用标准(ISO 15408)指定了评估IT产品而不是供应商资格的标准。 -通用标准评估 FOCI(...

[Day11] Custom HTML5 Video Player

[Day11] Custom HTML5 Video Player 影片播放控制器 需要用到的技巧与...

Day 26-Unit Test 应用於 Async Code-2 (情境及应用-6)

Unit Test 应用於 Async Code-2 - 用程序码讲故事(测试码 Exception...