代碼整潔筆記——整潔類的書寫準則

1.0整潔類的書寫準則

1.1 合理地分布類中的代碼

一般情況下抹竹,我們遵循變量列表在前,函數(shù)在后的原則盏档。

類應該從一組變量列表開始。若有公有靜態(tài)常量燥爷,應該最先出現(xiàn)蜈亩,然后是私有靜態(tài)變量,以及公有變量前翎,私有變量稚配。盡可能少的出現(xiàn)公有變量。

公共函數(shù)應該出現(xiàn)在變量列表之后港华。我們喜歡把由某個公共函數(shù)調(diào)用的私有工具函數(shù)緊跟在公共函數(shù)后面道川。

這樣是符合自定向下的原則,讓程序讀起來像一篇報紙文章立宜。

1.2 盡可能保持類的封裝

我們喜歡保持變量和工具函數(shù)的私有性冒萄,但不執(zhí)著于此。有時橙数,我們需要用到protected變量或者工具尊流,比如讓測試可以訪問到。然而灯帮,我們會盡可能使函數(shù)或變量保持私有崖技,不對外暴露太多細節(jié)。放松封裝钟哥,總是下策迎献。

1.3 類應該短小

正如之前關于函數(shù)書寫的論調(diào)。類的一條規(guī)則是短小瞪醋,第二條規(guī)則還是要短小忿晕。

和函數(shù)一樣,馬上有個問題要出現(xiàn)银受,那就是践盼,多小合適呢鸦采?
對于函數(shù),我們通過計算代碼行數(shù)來衡量大小咕幻,對于類渔伯,我們采用不同的衡量方法,那就是權責(responsibility)肄程。

1.3.1 單一權責原則

單一權責(Single Responsibility Principle锣吼,SRP)認為,類或模塊應有且只有一條加以修改的理由蓝厌。

舉個栗子玄叠,下面這個類足夠短小了嗎?

public class SuperDashboard extends JFrameimplements MetaDataUser
{
    public Component getLastFocusedComponent()
    public void setLastFocused(Component lastFocused)
    public int getMajorVersionNumber()
    public int getMinorVersionNumber()
    public int getBuildNumber()
}

答案是否定的拓提,這個類不夠“短小”读恃。5個方法不算多,但是這個類雖方法少代态,但還是擁有太多權責寺惫。這個貌似很小的SuperDashboard類,卻有兩條關聯(lián)度并不大的加以修改的理由:

第一蹦疑, 它跟蹤會隨著軟件每次發(fā)布而更新的版本信息(含有getMajorVersionNumber等方法)西雀。
第二,它還在管理組件(含有getLastFocusedComponent方法)歉摧。

其實艇肴,鑒別權責(修改的理由)常常幫助我們在代碼中認識到并創(chuàng)建出更好的抽象。

我們可以輕易地將SuperDashboard拆解成名為Version的類中判莉,而這個名為Version的類豆挽,極可能在其他應用程序中得到復用:

public class Version
{
    public int getMajorVersionNumber()
    public int getMinorVersionNumber()
    public int getBuildNumber()
}

這樣育谬,這個類就大致做到了單一權責券盅。

1.4 合理提高類的內(nèi)聚性

我們希望類的內(nèi)聚性保持在較高的水平。

何為類的內(nèi)聚性膛檀?類的內(nèi)聚性就是類中變量與方法之間的依賴關系锰镀。類中方法操作的變量越多,就越黏聚到類上咖刃,就代表類的內(nèi)聚性高泳炉。

類應該只有少量的實體變量,類中的每個方法都應該操作一個或者多個這種變量嚎杨。通常而言花鹅,如果一個類中的每個變量都被每個方法所使用,則該類具有最大的內(nèi)聚性枫浙。一般來說刨肃,創(chuàng)建這種極大化的內(nèi)聚類不可取古拴,也不可能。

我們只希望內(nèi)聚性保持在較高的水平真友。內(nèi)聚性高黄痪,表示類中方法和變量相互依賴,相互結(jié)合成一個邏輯整體盔然。

舉個高內(nèi)聚的例子:

public class Stack 
{
    private int topOfStack = 0;
    List<Integer> elements = new LinkedList<Integer>();
 
    public int size() 
    {
        return topOfStack;
    }
 
    public void push(int element)
    {
        topOfStack++;
        elements.add(element);
    }
 
    public int pop() throws PoppedWhenEmpty 
    {
        if (topOfStack == 0)
            throw new PoppedWhenEmpty();
        int element = elements.get(--topOfStack);
        elements.remove(topOfStack);
            return element;
    }
}

這個類非常內(nèi)聚桅打,在三個方法中,僅有size()方法沒有使用所有的兩個變量愈案。

注意挺尾,保持函數(shù)和參數(shù)短小的策略,有時候會導致為一組子集方法所用的實體變量增加站绪。我們應該嘗試將這些方法拆分到兩個或者多個類中潦嘶,讓新的類更為內(nèi)聚。

1.5 有效地隔離修改

需求會改變崇众,所以代碼也會改變掂僵。在面向?qū)ο笕腴T知識中我們學習到,具體類包含實現(xiàn)細節(jié)(代碼)顷歌,而抽象類則呈現(xiàn)概念锰蓬。依賴于具體細節(jié)的客戶類,當細節(jié)改變時眯漩,就會有風險芹扭。我們可以借助接口和抽象類來隔離這些細節(jié)帶來的影響。

舉個栗子赦抖,在一個設計場景下舱卡,我們以其設計直接依賴于TokyoStockExchange的Protfolio類,不如創(chuàng)建StockExchange接口队萤,里面只聲明一個方法:

public interface StockExchange
{
    MoneycurrentPrice(String symbol);
}

接著設計TokyoStockExchange類來實現(xiàn)這個接口:

public class TokyoStockExchange extends StockExchange
{
       //…
}

我們還要確保Portfolio的構造器接受作為參數(shù)StickExchange引用:

public Portfolio
{
    private StockExchange exchange;
    public Portfolio(StockExchange exchange)
    {
        this.exchange = exchange;
    }
    // ...
}

那么現(xiàn)在就可以為StockExchange接口創(chuàng)建可以測試的實現(xiàn)了轮锥,例如返回固定的股票現(xiàn)值。比如測試購買5股微軟股票要尔,我們下面的實現(xiàn)代碼返回100美元的現(xiàn)值舍杜,然后再實現(xiàn)一個總投資價值為500美元的測試,那么大概代碼則是:

public class PortfolioTest
{
    privateFixedStockExchangeStub exchange;
    privatePortfolio portfolio;
 
    @Before
    protected void setUp() throws Exception
    {
        exchange = new FixedStockExchangeStub();
        exchange.fix("MSFT", 100);
        portfolio = new Portfolio(exchange);
    }
 
    @Test
    public void GivenFiveMSFTTotalShouldBe500() throws Exception
    {
        portfolio.add(5, "MSFT");
        Assert.assertEquals(500,portfolio.value());
    }
}

如果系統(tǒng)解耦到足以這樣測試的程度赵辕,也就更加靈活既绩,更加可復用。部件之間的解耦代表著系統(tǒng)中的元素相互隔離得很好还惠。隔離也讓對系統(tǒng)每個元素的理解變得更加容易饲握。

我們的Portfolio類不再是依賴于TokyoStockExchange類的實現(xiàn)細節(jié),而是依賴于StockExchange接口這個抽象的概念,這樣就隔離了特定的細節(jié)救欧。而其實我們的類就遵循了另一條類的設計原則歪今,依賴倒置原則(Dependency Inversion Principle , DIP),因為依賴倒置原則的本質(zhì)颜矿,實際上就是認為類應該依賴于抽象寄猩,而不是依賴于具體細節(jié)。

2.0總結(jié)

  • 合理地分布類中的代碼: 類中代碼的分布順序大致是:
    <1> 公有靜態(tài)常量
    <2> 私有靜態(tài)變量
    <3> 公有普通變量
    <4> 私有普通變量
    <5> 公共函數(shù)
    <6> 私有函數(shù)
  • 盡可能地保持類的封裝: 盡可能使函數(shù)或變量保持私有骑疆,不對外暴露太多細節(jié)田篇。
  • 類應該短小,盡量保持單一權責原則: 類或模塊應有且只有一條加以修改的理由箍铭。
  • 合理提高類的內(nèi)聚性: 我們希望類的內(nèi)聚性保持在較高的水平泊柬。內(nèi)聚性高,表示類中方法和變量相互依賴诈火,相互結(jié)合成一個邏輯整體兽赁。
  • 有效地隔離修改: 類應該依賴于抽象,而不是依賴于具體細節(jié)冷守。盡量對設計解耦刀崖,做好系統(tǒng)中的元素的相互隔離,做到更加靈活與可復用拍摇。
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末亮钦,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子充活,更是在濱河造成了極大的恐慌蜂莉,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件混卵,死亡現(xiàn)場離奇詭異映穗,居然都是意外死亡,警方通過查閱死者的電腦和手機幕随,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門蚁滋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人合陵,你說我怎么就攤上這事枢赔。” “怎么了拥知?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長碎赢。 經(jīng)常有香客問我低剔,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任襟齿,我火速辦了婚禮姻锁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘猜欺。我一直安慰自己位隶,他們只是感情好,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布开皿。 她就那樣靜靜地躺著涧黄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪赋荆。 梳的紋絲不亂的頭發(fā)上笋妥,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機與錄音窄潭,去河邊找鬼春宣。 笑死,一個胖子當著我的面吹牛嫉你,可吹牛的內(nèi)容都是我干的月帝。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼幽污,長吁一口氣:“原來是場噩夢啊……” “哼嫁赏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起油挥,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤潦蝇,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后深寥,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體攘乒,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年惋鹅,在試婚紗的時候發(fā)現(xiàn)自己被綠了则酝。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡闰集,死狀恐怖沽讹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情武鲁,我是刑警寧澤爽雄,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站沐鼠,受9級特大地震影響挚瘟,放射性物質(zhì)發(fā)生泄漏叹谁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一乘盖、第九天 我趴在偏房一處隱蔽的房頂上張望焰檩。 院中可真熱鬧,春花似錦订框、人聲如沸析苫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽衩侥。三九已至,卻和暖如春纵揍,著一層夾襖步出監(jiān)牢的瞬間顿乒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工泽谨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留璧榄,地道東北人。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓吧雹,卻偏偏與公主長得像骨杂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子雄卷,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容