搬磚方法論:Single Responsibility Principle(單一職責(zé)原則、SRP原則)

差異的源頭

前言:語(yǔ)言本身是一件非常不穩(wěn)定的表達(dá)工具,這也是為什么我們?cè)跍贤ㄖ行枰^察對(duì)方的表情、肢體動(dòng)作、給予的隱喻、提供的圖像來(lái)進(jìn)一步確定對(duì)方想表達(dá)的意思,加之語(yǔ)言的使用者和接收者因文化、職業(yè)、經(jīng)歷等不確定因素的影響,又會(huì)造成相同的語(yǔ)句表達(dá)出不同含義,這讓語(yǔ)言的精確性再次下降。

只有這些?

當(dāng)我們用搜索引擎搜索 SRP原則或單一職責(zé)原則關(guān)鍵字,定義中使用頻率最多的一句話就是:一個(gè)類(lèi)應(yīng)該只有一個(gè)發(fā)生變化的原因。

這不僅讓讀者陷入思索,其中所描述的原因到底是什么?是否可量化?

以量取勝

為了進(jìn)一步解釋這個(gè)"原因",我們對(duì)其定義豐富一下:

  • 一個(gè)類(lèi)應(yīng)該只有一個(gè)發(fā)生變化的原因。
  • 每一個(gè)類(lèi)都應(yīng)該對(duì)程序功能的一個(gè)部分負(fù)責(zé),此時(shí)它應(yīng)該封裝。該模塊、類(lèi)或函數(shù)的所有服務(wù)都應(yīng)該與該職責(zé)緊密結(jié)合。
  • 將因相同原因而發(fā)生變化的事物聚集在一起。分開(kāi)由于不同原因而改變的事物。

以上的三條定義說(shuō)的都是一件事:?jiǎn)我宦氊?zé)原則。
這也能看出,這個(gè)發(fā)生變化的"原因"是基于一個(gè)集合。如果每個(gè)函數(shù)只做一件事是一個(gè)機(jī)器的零件,那單一職責(zé)中的"職責(zé)"也就是所說(shuō)的“原因”就是這些零件組合起來(lái)的功能。

確定單一

既然我們已經(jīng)從概念上統(tǒng)一了職責(zé)到底是什么,那么下一步就是從量化的角度確定如何保證職責(zé)單一。

分為如下三步

  • 建模
  • 編碼對(duì)應(yīng)的類(lèi)(筆者開(kāi)始階段常用偽代碼代替)
  • 將對(duì)應(yīng)的類(lèi)拆分為多個(gè)類(lèi)直到不能拆分

建模:可以理解為對(duì)應(yīng)需求的梳理和拆分,最終抽象(總結(jié))出這個(gè)職責(zé)核心是做什么的,要依賴(lài)于哪些其他的職責(zé)。

應(yīng)用

我們可以舉個(gè)例子來(lái)說(shuō)明,我們要做一個(gè)菜單界面功能,一般我們會(huì)這么寫(xiě)

public class MenuPanel
{
    public MenuPanel()
    {
        var menuData = GetMenuData();
        SetMenuDataAndUpdate(menuData);
    }

    public string GetMenuData()
    {
        // do something...
        return default;
    }

    public void SetMenuDataAndUpdate(string temp)
    {
        // do something...
    }
}

在這個(gè)MenuPanel類(lèi)中負(fù)責(zé)顯示Menu這個(gè)菜單界面,但是這個(gè)MenuPanel真的是僅僅負(fù)責(zé)顯示嗎?答案是否定的。

當(dāng)?shù)玫讲邉澬枨蟮臅r(shí)候,可按照【確定單一】里面所說(shuō)的3步驟進(jìn)行如下操作

建模

  • 根據(jù)數(shù)據(jù)庫(kù)的數(shù)據(jù)顯示對(duì)應(yīng)的菜單。
  • 數(shù)據(jù)方面需要:請(qǐng)求-驗(yàn)證-解析-整合-篩選等操作。相當(dāng)于上述代碼GetMenuData()函數(shù)。
  • UI方面需要:接收數(shù)據(jù)-數(shù)據(jù)分類(lèi)填充-適配布局-注冊(cè)響應(yīng)事件等操作。相當(dāng)于上述代碼SetMenuDataAndUpdate()函數(shù)。
  • 將上面數(shù)據(jù)與UI進(jìn)行銜接操作。相當(dāng)于上述代碼MenuPanel()。

拆分對(duì)應(yīng)的類(lèi)直到不能再拆分

  • 數(shù)據(jù)處理一個(gè)類(lèi)
  • UI顯示一個(gè)類(lèi)
  • 數(shù)據(jù)與UI銜接一個(gè)類(lèi)

經(jīng)過(guò)拆分后的代碼

public class ServerData
{
    public string GetNeedData()
    {
        /*
         * 請(qǐng)求 函數(shù)
         * 驗(yàn)證 函數(shù)
         * 解析 函數(shù)
         * 整合 函數(shù)
         * 篩選 函數(shù)
         */
        return default;
    }

}

public class MenuPanel
{
    private string m_NeedData;
    public MenuPanel(string needData)
    {
        m_NeedData = needData;
    }

    public void UpdateMenu()
    {
        // do something...
    }
}

public class EnterMenuPanelCommand
{
    public void Excute()
    {
        var serverData = new ServerData();
        var needData = serverData.GetNeedData();
        //TODO:正常情況下不應(yīng)該直接傳入基本類(lèi)型,應(yīng)該傳入對(duì)應(yīng)的自定義類(lèi),為了示例簡(jiǎn)單暫且代替
        var menuPanel = new MenuPanel(needData);
        menuPanel.UpdateMenu();
    }
}

經(jīng)過(guò)一系列的操作我們得到三個(gè)職責(zé):數(shù)據(jù)處理、UI刷新、數(shù)據(jù)與UI銜接三個(gè)職責(zé)。這樣每一個(gè)類(lèi)當(dāng)職責(zé)變化,即只有一個(gè)發(fā)生變化原因時(shí),我們才需要更改對(duì)應(yīng)的類(lèi)。

總結(jié)

SRP原則并不是徹底消滅腐朽代碼的銀彈,它只是降低出現(xiàn)代碼壞的味道的幾率,提高代碼整潔的系數(shù)。SRP原則是一個(gè)指導(dǎo)性建議,并非強(qiáng)制要求,也切勿生搬硬套。


更多文章詳見(jiàn)主頁(yè):www.aihailan.com

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

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

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