打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
「深入討論」認識 MVC﹣View 與 Controller(上)


View 和 Controller 的關係相比起與 Model 的關係更加密切,因為這兩者都是跟用戶直接溝通的,而 Model 則是在用戶看不到的地方工作。維基為 View 給出的定義就是

any output representation of data

意思就是把資料顯示出來,這可以是以圖表形式,亦可以是表格形式等等。而 Controller 則是

mediates input, converting it to commands for the model or view

即是 Model 與 View 之間的溝通橋樑,

在用戶端接收了命令之後,Controller 就會把命令發送到 Model 去,然後從 Model 拿到結果之後就把結果傳送到 View 去,把資料顯示給用戶看。

當然,實行起上來仍然會有很多模糊的地方。View 裏可不可以有代碼呢?我不直接答你,用例子答你。例如如果我想把 Timestamp 變成一個可讀的格式才顯示給用戶看,這個可以在 View 裏面寫嗎?西杰看過在 PHP 中有兩個常用的 View 風格,第一種是在 Controller 直接使用 template,把變數傳遞到 template 中處理;第二種是為 View 建立一個 Class,然後把變數傳遞到 Class 中處理,最後再在 View 的 Class 中使用 template,把處理好的數值傳送到 template 裏顯示,在 template 中不用再處理。

例子:

第一種寫法:

<?php$time = time();include_once('index.phtml');?>
//index.phtml<html>	<head>		<title>MVC</title>	</head>	<body>		Today is: <?=date('M j, Y', $time)?>	</body></html>

第二種寫法:

<?php$time = time();class View{	public function render($data){		$formattedTime = date('M j, Y', $data['time']);	}}$view = new View();$view->render(array('time', $time));?>
<html>	<head>		<title>MVC</title>	</head>	<body>		Today is: <?=$formattedTime?>	</body></html>

第一種寫法好處是比較簡單,而且很直觀,我只需看一看 template 文件就可以知道日期的格式是什麼,不需再翻閱 View 的 Class 代碼。第二種寫法雖然比較複雜,但要做更複雜的系統卻便利得多,例如如果我需要提供兩種“界面”,一種 HTML 給網頁瀏覽者閱讀,另一種是 JSON 給開發者使用,那麼我不用重寫 Controller,而只需要寫兩種 View 就可以了,這提高了代碼重用度。

西杰比較常用的是第一種方法,原因有二,一是我比較喜歡直觀的 template,不用四處找檔案才知道輸出的格式,二是因為現實世界中我們其實不太可能可以用同一個 Controller 應付兩種使用者(AJAX 的出現或會有所改變,因為使用 AJAX 的系統 Controller 只需回應 Javascript,跟提供 API 給開發者無異),我經常要寫兩個 Controller 給不同的讀者使用,那麼我為什麼還要做兩個 View 呢?

這裏只先探討一個問題,就是 View 中應該有沒有代碼存在,其實這個問題沒有一個比較確實的答案,要看看你編寫的風格以及系統的需求。下次我們還會繼續探討 View 及 Controller 的關係!


「深入討論」認識 MVC﹣View 與 Controller(下)

上一節討論了 View 內應否有 Logic 的代碼,這一節就會討論 Controller 內應否有 Logic 的存在。

Controller 的工作是什麼呢?它負責從 View 中接收指令,然後把指令發送到相應的 Model 處理,在 Model 處理完成後就再把處理結果發回到 View 去。要注意的是,這個模式跟傳統的 MVC 有點分別,分別在於傳統的 MVC 裏,View 是以 Observer 的身份來觀察 Model 的改變並直接從 Model 處拿取資料,而不需經過 Controller 的。

一個常見的問題是,Controller 裏應該有 Logic 代碼嗎?這個西杰可以肯定的答你,不該!我們應該遵從 Fat-Model-Skinny-Controller 的原則,這可以令你的代碼更易被重用。Controller 應該做的只是從不同的輸入來源分析參數,並把這些參數傳到 Model 處理。試想想,如果你把 Logic 放到 Controller 中,Model 只是純粹一個 Data Structure,那麼當你想新增另一個輸入來源就會令你改動很多地方才能完成任務,甚至要你重新測試你本來就寫得完美的 Logic,費時失事!

另一個常見的問題,User authentication 應該是 Controller 做的工作還是 Model 做的呢?這個問題兩派的支持者相若,有的認為用戶驗証並不是 Business Logic 的一部份,是 Application 的 Logic,然而西杰比較認同 User authentication 應該放到 Model 中處理,因為還是那個老問題,User authentication 應該是每個界面都要進行的程序,從重用性去想,這放在 Model 可以減少需要改寫的代碼。

然而,其實還有一個更好的做法,就是利用 Aspect-Oriented Programming (AOP) 的思想去實現,AOP 是一種鼓勵分開 Cross-cutting concern 的思想,Cross-cutting concern 的意思是一個涉及系統多處的邏輯,例如一個系統可能在很多地方都需要 “log 低” 做過的動作,那麼 log 就是一個 Cross-cutting concern。而 User authentication 其實跟 log 很相似,都是需要在系統多處進行的動作,如果我們可以把它封裝成 Annotation 的形式來做的話,代碼會簡潔易明得多。

public class User{	public void add(UserObject me, String username, String password){		if (me.isAdmin()){			//add a new user...		}	}}
public class User{	@AdminOnly	public void add(UserObject me, String username, String password){		//add a new user...	}}

對比一下以上的代碼,第二段的 add() 只需要專注做新增用戶的動作,並不需要像第一段一樣要加個 if 來檢查用戶是否有權限新增用戶,程式看起來就簡潔得多了。

編寫 Controller 的要求其實和 Model 及 View 都差不多嚴謹,其主要思想就是代碼重用,Skinny-Controller 就是最佳做法。然而,Controller 和 Model 的角色有時會有所模糊,解決的方法就是利用 AOP 來把代碼分開,這樣就不至於令 Controller 或 Model 其中一個太過臃腫了。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
ABAP Objects Design Patterns – Model View Controller (MVC) Part 2
Adding a model — ASP.NET documentation
Alex‘s space: MVP vs MVC
从MVC在前端开发中的局限性谈起
MVC模型引导WEB设计
Getting Started With ASP.Net MVC
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服