iT邦幫忙

2021 iThome 鐵人賽

DAY 3
0
Software Development

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

[DAY3] MVC與散落各處的邏輯

上回說到 Fat Model 的邏輯散落在各處,那這回就要來說說散落在哪、以及造成這種現象的原因。

Rails 的 MVC

MVC(Model–View–Controller)是一種軟體架構,主要是將軟體系統分成三個部分,使得程式分工容易,利於團隊的擴張。

更多關於 MVC 的文章可以參考以下
Model、View、Controller 三分天下

接著我們看看 Rails 官網的教學,以下是顯示一篇文章的 model、controller 跟 view。

Model

class Article < ActiveRecord::Base
end

Controller

class ArticlesController < ApplicationController
  def show
    @article = Article.find(params[:id])
  end
end

View

<h1>Listing articles</h1>
 
<table>
  <tr>
    <th>Title</th>
    <th>Text</th>
  </tr>
 
  <% @articles.each do |article| %>
    <tr>
      <td><%= article.title %></td>
      <td><%= article.text %></td>
    </tr>
  <% end %>
</table>

寫起來很方便快速,但卻有個致命的問題,在 view 中可以直接拿到 model
接著我們加入一些情境,加速程式腐化的速度
假設現在收到一個需求是想要計算文章的數量,並跟著文章標題一起顯示,而且2個小時後就需要 demo!

最快的做法是在 controller 上新增這個邏輯並在 view 中取用

Controller

class ArticlesController < ApplicationController
  def show
    @article_count = Article.count
    @article = Article.find(params[:id])
  end
end

View

<h1>Listing articles</h1>
 
<table>
  <tr>
    <th>Title</th>
    <th>Text</th>
  </tr>
 
  <% @articles.each do |article| %>
    <tr>
      <td><%= "#{@article_count}. #{article.title}" %></td>
      <td><%= article.text %></td>
    </tr>
  <% end %>
</table>

這時候會衍生兩個問題,第一個是如果很多不同的 view 都會使用這個邏輯,這段 code 必須複製過去,違反 DRY 原則,第二個是如果顯示上有許多這樣的調整,controller 上會有許多邏輯,instance variable 也會無止境的擴張。

接下來可能會想要把 controller 上的邏輯收進 model 中。

Model

class Article < ActiveRecord::Base
	def display_title
		"#{count}. #{title}" 
	end
end

View

<h1>Listing articles</h1>
 
<table>
  <tr>
    <th>Title</th>
    <th>Text</th>
  </tr>
 
  <% @articles.each do |article| %>
    <tr>
      <td><%= article.display_title %></td>
      <td><%= article.text %></td>
    </tr>
  <% end %>
</table>

於是 model 和 view 便有了耦合 /images/emoticon/emoticon20.gif

隨著專案越來越大,view 中會參雜許多邏輯,加上 model 和 model 間也會有許多的關聯,久而久之便會變成一坨大泥球。

後記

在 Rails 中提出的解決方法是透過 presenter 這個設計模式去解決這個問題,所有的顯示邏輯應該被包在 presenter 中而不是在 model 上,model 不應該知道 view 的存在,不過如何實作也是需要好好設計!

下一篇會分享 Rails 預設的資料夾結構如何加重這個問題 /images/emoticon/emoticon08.gif


上一篇
[DAY2] 聽說 Rails 開發很快速?
下一篇
[DAY4] 一塊大千層蛋糕 — MVC 架構的橫切分層,以及為何需要縱切
系列文
在 Ruby on Rails 中導入 Domain-Driven Design 是不是搞錯了什麼?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言