在每個類別中,應該只會有少量的實體變數,而內部的方法則操縱一個至多個該類型的變數。一般來說,一個類別中的方法所操作的變數越多,則該類別的凝聚性越高,如果有一個類別中的每個方法,都會影響到該類別中的所有變數,那麼這個類別就是具備最大凝聚性的類別。
但通常來說,具備這樣凝聚性的類別並不太可能做到,也不會被建議去達成,然而,我們仍然期待類別具有較高的凝聚性。當類別內部的方法與變數彼此依賴時,他們在邏輯上會更被明確為一個整體。
在過去幾天,我們曾提到說函式要簡短及保持參數串列夠小,而當這兩項策略再加上維持類別的凝聚性時,我們將會神奇地將一個大型類別,分割得到許多小型類別。
這是什麼意思呢?
為了使函式簡短,我們將一個大型函式的部分抽離出來,成為另一個不同的函式。然而,當這個新函式使用了原函式內部所宣告的四個變數時,我們是否會將這四個變數都作為參數傳遞到新函式中呢?
不!我們不會。為了盡量保持函式沒有參數或極少參數的狀態,我們會將這四個變數抽取出來,升等為類別中的實體變數。於是,我們能輕鬆地完成將一個大函式變為數個小函式的過程。而隨著我們持續地讓函式保持簡短,該類別中的實體變數也將不可避免的增加。但這些實體變數卻只被少數幾個方法所共用,於是這個類別漸漸喪失了凝聚性。
這時我們應該有感受到那股衝動!當某些實體變數僅被少數幾個方法所共同使用時,不就正代表著這些變數與方法,應當獨立出來成為一個新的類別嗎?是的,當類別喪失凝聚性時,我們就應當將它們拆分開來,讓每個類別都擁有夠高的凝聚性。
也就是說,當我們將一個大型函式拆解成許多小函式時,往往會驅動我們去將類別分割,使我們的程式擁有更好、更明確的結構。
為了避免篇幅過長,我這裡不放上程式碼,但大家可以想像一下,當我們遵循上述的流程,將一個類別內部的大型函式分割,使之成為具有描述力的許多小函式,程式碼將會發生什麼事?它將會暴增到比原本的程式碼多的多。為什麼呢?
回想我們過去半個月所學習的,首先,我們會使用更長、更具備說明性的變數名稱;再來,重構後的程式,我們將會讓它擁有註解效果的函式名稱及變數宣告;最後,我們運用編排技巧,使程式碼具備可讀性。於是,我們所會、所擁有的技巧將串聯在一起,彼此貫通成為撰寫整潔程式碼中的要素。
當我們成功地將各類別拆分開來,使之遵循單一職責原則,擁有恰當的凝聚姓,在往後需要對程式進行維護時,便可極大程度上避免因修改系統功能,而改變、破壞到不相關的程式碼。而要能夠善加運用我們所學的技巧及策略,將程式重構成整潔的樣貌,測試程式便體現出自身的重要性了。
有趣的是,作者並沒有提倡我們積極地去重構程式。
然而,系統需要改變自己才是該採取行動的主要誘因。......類別被視為邏輯已完備,那麼我們就不需要去擔心職責拆解的有關問題。......不過,一旦我們發現自己打開了一個類別,我們就應該考慮修補我們的設計。
也就是說,當我們遇到程式需要修改而系統設計有所缺陷時,才是驅動我們去對程式進行重構的主要動力。
因為自己實務上往往並沒有太多時間與精力,去審視程式並為之修整,是以我通常是在需要維護時,才去慢慢調整過去所積累下來的缺陷。但這樣的行為,我一直認為那是自己不得已的妥協,卻沒想到作者其實也並沒有認為,我們需要主動大刀闊斧地去修改,不禁小小地感到安慰。