被人忽略的Model

MVC不是一種設(shè)計模式,而是一種指導(dǎo)原則,簡單講就是一個應(yīng)用系統(tǒng)被劃分為M(數(shù)據(jù)模型model)V(視圖view)和C(控制器controller)三個部分,每個部分都有比較清晰的職責(zé)劃分。MVC指導(dǎo)原則下開發(fā)的系統(tǒng)代碼邏輯清晰,容易擴(kuò)展并且可復(fù)用。

在大多數(shù)時候,并沒有一種代碼級別的約束讓你的程序看起來是MVC的思想,多數(shù)時候是靠程序員自己的“自覺”,維護(hù)一種看起來有序、可復(fù)用的模式。

最近我接觸到一個系統(tǒng),發(fā)現(xiàn)在controller里有大量的業(yè)務(wù)邏輯,這些業(yè)務(wù)邏輯包含了對表單數(shù)據(jù)的過濾,session的存取,當(dāng)然還有大量的數(shù)據(jù)庫的讀寫,甚至包含了數(shù)據(jù)庫的事務(wù),就像是一個“全棧工程師”,包攬了一個項目的大部分業(yè)務(wù)邏輯,view和model只能望洋興嘆,后來接手的程序員則更是痛苦,因為老板要求系統(tǒng)支持手機(jī)端的API,他如果是懶惰的人(也許不是懶惰,只是因為沒時間),就會把當(dāng)前的controller復(fù)制一遍,起個新的名字(極可能的名字是原有的action名稱后面加上2,好點的加上_mobile),刪除傳遞變量給模板的部分,最后返回一個json格式的字符串;勤奮的人(也許不是勤奮,只是因為重構(gòu)的時間比較充足)會新建一個service層,把大部分的業(yè)務(wù)邏輯轉(zhuǎn)移到service里,然后新建一個action,使得原來的action和手機(jī)端對應(yīng)的action都調(diào)用service里的方法。當(dāng)然也有自作聰明的人會修改原來的業(yè)務(wù)邏輯,在原有的action里加上了瀏覽器user-agent判斷。

重購前的代碼就像是這樣:

class UserController{
    
    function login(){
        $name = $this->request()->get("name");
        $password = $this->request()->get("passoword");
        $user = new User();
        $success = $user->where("name",$name)->where('password',$password)->find();
        if($success){
            return redirect("home");
        }else{
            return redirect('login','login fail');
        }
    }
}

這樣的代碼似乎并沒有什么問題,但是當(dāng)業(yè)務(wù)邏輯比較復(fù)雜的時候,對于名字為login的action責(zé)任就太大了,而且我在新的接口里用到登錄的邏輯時,就必須要復(fù)制代碼:

class UserController{
    
    function login(){
        $name = $this->request()->get("name");
        $password = $this->request()->get("passoword");
        $user = new User();
        $success = $user->where("name",$name)->where('password',$password)->find();
        if($success){
            return redirect("home");
        }else{
            return redirect('login','login fail');
        }
    }

    function login_mobile(){
        $name = $this->request()->get("name");
        $password = $this->request()->get("passoword");
        $user = new User();
        $success = $user->where("name",$name)->where('password',$password)->find();
        return json_encode(array(
            'success'   => $success
        ));
    }
}

所以現(xiàn)在我們作了以下的重構(gòu):

class UserController{
    function __construct()
    {
        $this->service = new Service();
    }

    function login(){
        $name = $this->request()->get("name");
        $password = $this->request()->get("passoword");
        if($this->service->has($name,$password)){
            return redirect("home");
        }else{
            return redirect('login','login fail');
        }
    }

    function login_mobile(){
        $name = $this->request()->get("name");
        $password = $this->request()->get("passoword");
        $success = $this->service->has($name,$password);
        return json_encode(array(
            'success'   => $success
        ));
    }
}

我們把可能非常冗繁的數(shù)據(jù)庫操作邏輯轉(zhuǎn)移到了service類里面。這樣,controller只是負(fù)責(zé)轉(zhuǎn)發(fā)數(shù)據(jù),并不負(fù)責(zé)任何業(yè)務(wù)邏輯,實際上,它的職責(zé)只該包括:

  1. 過濾(驗證)數(shù)據(jù)。
  2. 傳遞數(shù)據(jù)。
    要注意的是,傳遞的數(shù)據(jù)應(yīng)該包括request,session和cookie中的數(shù)據(jù),不要在service里去操作request,session和cookie。因為永遠(yuǎn)都不知道這個職能單一的service還會被誰調(diào)用,也許是命令行(CLI)模式下調(diào)用也不一定。

基于MVC思想開發(fā)的框架很多,如laravel、CI、Yii Framework,thinkphp(TP)等。許多時候開發(fā)者糾纏于使用哪一個框架能更好的開發(fā),業(yè)務(wù)邏輯能更加清晰,其實哪一個框架都可以,對代碼的控制才是關(guān)鍵。

在一些時候,框架的業(yè)務(wù)邏輯是在model里,有時是在service里。封裝具體的業(yè)務(wù)邏輯的類名并不真的重要,思想才最重要。

就像Yii Framework官網(wǎng)所說的:

In a well-designed MVC application, controllers are often very thin, containing probably only a few dozen lines of code; while models are very fat, containing most of the code responsible for representing and manipulating the data.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容