作者poopoo888888 (阿川)
看板PHP
标题[心得] MVC,令人搞不懂的MODEL
时间Mon Mar 17 21:03:08 2014
自学web开发两年,对MVC一直一知半解,常在想怎样设计系统会最漂亮。
整理了一下目前的理解,以Model出发跟各位分享。
其中有写错的部份也期待各位前辈指教。
http://blog.turn.tw/?p=217
---------------------------------------------------------------------------
Q1: 一个model对应到资料库一张table对吗?
不对。虽然大部分framework实作都会将一张table对应到model内一个class,但「一个
model对应一张table」比较像是在描述ORM之类帮助简化资料库SQL操作的class,
而model是「处理跟某张table相关任务的class」。
差别何在?一个model可能会处理到多张table的资料,也可能一张table都不碰,纯粹处理
一串商业逻辑。举例来说,可能会有个负责整理行销资料的model叫Marketing,从多张
table捞资料出来,整理之後丢给controller。而资料库中可能有,也可能没有「marketing
」这张table。
Q2: 可是我写专案几乎一个model对应到一张table啊?
因为实务上一个服务常会对应到一个model,而提供这model所需的资料常常就只是一张
table。所以许多情况下的确是一张model对应到一张table没错。
但也不能说是「一张」table。model内常会去join其他相关的table对吧?
所以说「model对应到一张table」或是「model就是一种ORM」都是不精确而误导的说法。
虽然写起来常会有这种错觉。
Q3: 那你用一个不会误导又精确的说法描述model给我看?
「model是layer」。不要把MVC中的M跟VC想成平行的分工关系,把VC跟M想成上往下的几层
layer。VC最靠近使用者、下来是M、再下来是database。
所以VC要取得资料库的资料都要透过model,而不同任务有不同model。
Q4: 听不太懂,谈点别的好了。从Rails社群流出一句很流行的MVC原则「fat model,
skinny controller」,你对此有什麽想法?
这句话对初学者有帮助,对进阶者有害。
「fat model, skinny controller」这句话可以提醒初学者尽量把code丢进model
别丢进controller。你再看一次我Q3的回答,一个应用程式的最重要部份
(商业逻辑、安全性、效能)本来就是跟资料库互动的那层layer,也就是
model,所以把code丢进model别丢进controller可以暗示初学者写出reusable的code。
但是把太多code写进model会形成god pattern,也就是某个model跟神一样负责绝大部分的
任务,导致维护起来有困难(想像你初学PHP把全部code写在同一份档案的恐怖情况)。
Q5: 又说code要尽量丢进model,又说model内code太多很不好,不然code到底要丢哪?
library以及helper。现在大部分的framework都预设有放library以及helper的地方。不使
用framework的话你也可以自己开这两个资料夹。
多个model常做的同几件事可以包起来写成library,而单纯的资料格式转换
(甚至是产生相关html/css)之类的任务可以写成helper。
让model主要专注在商业逻辑(这是最花功夫的地方),其余的搬到library、helper、
或是有些framework称之为third_party或package的什麽地方都好。
别丢进controller!更别丢进view。
Q6: 好吧。可是我开发时在controller跟model内真的会不小心就写掉大部分任务,这样写
真的比较快阿。你开发时,上面说的你自己有没有都做到?
没有。原因有两个。一,实务上的确很难在一开始就把架构想清楚,所以一堆任务会丢给
model。二,常常越往下写才发现某些任务是共通的、某些任务一开始只是「简单」处理资
料转换,写到後来变成「复杂的」处理资料转换,我认为这时再把它拉出来成为library或
helper即可。重构本来就是不断在做的事情,时机到了就做。
Q7: 我知道library跟helper的地位何在了。但,library跟helper的差别又何在?
软体开发时,有时会写几个function或method解决某些任务,有时候觉得这样太松散,
会包成class。library常常是class、helper常常是一组function。以我自己来说,常在
controller或view使用helper,在model使用library。
Q8: 关於model,最後有没有要提醒的?
不要在model里面用session variable。用下去,那model根本不再reusable(其他
controller用之前还要先设定好相关session)。连unit testing都毁了。解决之道是
dependency injection。session variable某种程度来说根本就是global variable,滥用
global variable是很不好的。
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 114.37.251.200
1F:推 chenstin:推一下 03/17 22:51
2F:推 taikobo: 推分享 03/18 10:09
3F:推 DongFeng:PUSH 03/18 14:15
4F:推 world294:Good..ZF2 用过吗? 03/18 14:42
PHP只用过CodeIgniter Q_Q
之後想学Laravel :D
※ 编辑: poopoo888888 来自: 1.171.161.139 (03/19 15:26)
5F:→ tails32100:Laravel看起来很神啊.... 03/20 18:48
6F:推 roycsw:推心得~! 03/23 12:01
7F:推 see7di:$_ENV定义全局变数就好了 不要GLOBLE 04/10 00:03
8F:推 see7di:框架是为了提升开发速度 别拘尼于它反受其害 04/10 00:07