Time of Update: 2018-12-07
你有一個複雜的條件陳述式。從if、then、else三個段落中分別提煉出獨立函數。動機:程式之中,複雜的條件邏輯是最常導致複雜度上升的地點之一。你必須編寫代碼來檢查不同的條件分支、根據不同的分支做不同的事,然後,你很快就會得到一個相當長的函數。大型函數自身就會使代碼的可讀性下降,而條件邏輯則會使代碼更難閱讀。在帶有複雜條件邏輯的函數中,代碼(包括檢查條件分支的代碼和真正實現功能的代碼)會告訴你發生的事,當常常讓你弄不清為什麼會發生這樣的事,這就說明代碼的可讀性的確大大降低了。
Time of Update: 2018-12-07
函數本體不再需要某個函數。將該參數去除。動機:程式員可能檢查添加參數,卻往往不願意去掉它們。他們打的如意算盤是:無論如何,多餘的參數不會引起任何問題,而且以後還可能用上它。 參數代表著函數所需的資訊,不同的參數值有不同的意義。函數調用者必須為每一個參數操心該傳什麼東西進去。如果你不去掉多餘參數,就是讓你的每一位使用者多費一份心。是很不划算的,更何況“去除參數”是非常簡單的一項重構。
Time of Update: 2018-12-07
函數對某個類的興趣高過對自己所處的類,通常的焦點就是資料,某個函數為了計算某個值,從另一個對象那兒調用幾乎半打的存取子。這時一個運用 Move Method (搬移函數)把它移到自己該去的地方。有時候函數中只有一部分受這種依戀之苦,這時候使用Extract Method (提煉函數)把這部分提煉到獨立函數中,再使用Move Method (搬移函數)帶它去它的夢中家園。
Time of Update: 2018-12-07
你的程式中,某個欄位被其所駐類之外的另一個類更多的用到。在目標類建立一個新欄位,修改源欄位的所有使用者,令它們改用新欄位。 動機:在類之間移動狀態和行為,是重構過程中必不可少的措施。隨著系統發展,你會發現自己需要新的類,並需要將現有的工作責任拖到新的類中。在這個星期看似合理而正確的設計決策,到了下個星期可能不再正確。這沒問題,如果你從來沒遇到這種情況,那才有問題。
Time of Update: 2018-12-07
對象技術的新手通常不願意在小任務上運用小對象—像是結合數值和幣種的money類,由一個起始值和結束值組成的range類等。你可以使用 Replace Data Value with Object (以對象取代資料值)將原本單獨存在的資料值替換為對象。如果想要替換的資料值是類型碼,而它並不影響行為,則可以運用 Replace Type Code with Class (以類取代類型碼)將它替換掉。如果你有與類型碼相關的條件運算式,可運用 Replace Type Code with
Time of Update: 2018-12-07
面對一個調用者可以預先檢查的條件,你拋出一個異常。修改調用者,使它在調用函數之前先做檢查。動機:異常的出現是程式語言的一大進步。但是,就像許多好東西一樣,異常會被濫用,從而變得不再讓人愉快。“異常”只應該被用於異常的、罕見的行為,也就是那些產生意料之外的錯誤的行為,而不應該成為條件檢查的替代品。如果你可以合理期望調用者在調用函數之前檢查某個條件,那麼就應該提供一個測試,而調用者應該使用它。
Time of Update: 2018-12-07
客戶通過一個委託類在調用另一個對象。在服務類上建立客戶所需的所有函數,用以隱藏委託關係。動機:“封裝”即使不是對象的關鍵特徵,也是關鍵特徵之一。“封裝”意味每個對象都有應該儘可能少瞭解系統的其他部分。如此一來,一旦發生變化,需要瞭解這一變化的對象就會比較少,這會使變化較容易進行。 如果某個客戶先通過服務物件的欄位得到另一個對象,然後調用後者的函數,那麼客戶就必須知曉這一層委託關係。萬一委託關係發生變化,客戶也得相應變化。你可以在服務物件上放置一個簡單的委託函數,將委託關係隱藏起來,
Time of Update: 2018-12-07
你有一系列條件測試,都得到相同結果。將這些測試合并為一個條件運算式,並將這個條件運算式提煉為一個獨立函數。動機:有時你會發現這樣一串條件檢查:檢查條件各不相同,最終行為卻一致。如果發現這種情況,就應該使用“邏輯或”和“邏輯與”將它們合并為一個條件運算式。
Time of Update: 2018-12-07
你有一個字面數值,帶有特別含義。建立一個常量,根據其意義為它命名,並將上述的字面數值替換為這個常量。動機:在計算科學中,魔法數是曆史悠久的不良現象之一。所謂魔法數是指擁有特殊意義,卻又不能明確表現出這種意義的數字。如果你需要在不同的地點引用同一個邏輯數,魔法數會讓你煩惱不已,因為一旦這些數發生變化,你就必須在程式中找到所有魔法數,並將它們全部修改一遍。就算你不需要修改,要準確指出每個魔法數的用途,也會讓你頗費腦筋。
Time of Update: 2018-12-07
某個函數既返回對象狀態值,又修改對象狀態。建立2個不同的函數,其中一個負責查詢,另一個負責修改。動機:如果某個函數只是向你提供一個值,沒有任何看得到的副作用,那麼這是個很有價值的東西。你可以任意調用這個函數,也可能把調用動作搬到函數的其他地方。明確表現出”有副作用”與“無副作用”2種函數之間的差異,是個很好的想法。任何有傳回值的函數,都不應該有看得到的副作用。有些程式員甚至將此作為一條必須遵守的規則。
Time of Update: 2018-12-07
你想要把某個演算法替換為另一個更清晰地演算法。將函數本體替換為另一個演算法。 string FoundPerson(string[] people) { for (int i = 0; i < people.Length; i++) { if (people[i].Equals("don")) { return "don";
Time of Update: 2018-12-07
2個類都需要使用對方特性,但其間只有1條單向串連。添加1個反向指標,並使修改函數能夠同時更新2條串連。動機:開發初期,你可能會在2個類之間建立1條單向串連,使其中一個類可以使用另一個類。隨著時間推移,你可能發現被引用類需要得到其引用者以便進行某些處理。也就是說它需要一個反向指標。但指標是一種單向串連,你不可能反向操作它。通常你可以繞道而行,雖然會耗費一些計算時間,成本還算合理,然後你可以在被引用類中建立一個函數專門負責此行為。但是,有時候想繞過這個問題並不容易,此時就需要建立雙向參考關聯性,或
Time of Update: 2018-12-07
某個類做了過多的簡單委託動作。讓客戶直接調用受託類。動機:在Hide Delegate (隱藏委託關係)的“動機”中,談到了“封裝委派物件”的好處。但是這層封裝也是要付出代價的,它的代價是:每當客戶要使用受託類的新特性時,你就必須在服務端添加一個簡單委託函數。隨著委託類的特性(功能)越來越多,這一過程讓你痛苦不已。服務類完全變成了“中間人”,此時你就應該讓客戶直接調用受託類。 很難說什麼程度的隱藏才是合適的。還好,有了Hide Delegate (隱藏委託關係)和Remove
Time of Update: 2018-12-07
常常可以在很多地方看到相同的3、4項資料:2個類中相同的欄位、許多函數簽名中相同的參數。這些總是綁在一起出現的資料真應該擁有屬於它們自己的對象。首先找出這些資料以欄位形式出現的地方,運用Extract Class (提煉類)將它們提煉到一個獨立對象中。然後將注意力轉移到函數簽名上,運用Introduce Parameter Object (引入參數對象)或Preserve Whole Object
Time of Update: 2018-12-07
你需要為提供服務的類增加一個函數,但你無法修改這個類。在客戶類中建立一個函數,並以第一參數形式傳入一個服務類執行個體。 動機:這種事情發生了太多次了,你正在使用一個類,它真的很好,為你提供了需要的所有服務。而後,你又需要一項新服務,這個類卻無法供應。於是你開始咒罵“為什麼不能做這件事?”如果可以修改源碼,你便可以自行添加一個新函數;如果不能,你就得在用戶端編碼,補足你要的那個函數。
Time of Update: 2018-12-07
某個類沒有做太多事情。將這個類的所有特性搬移到另一個類中,然後移除原類。動機:Inline Class (將類內聯化)正好於Extract Class (提煉類)相反。如果一個類不再承擔足夠責任、不再有單獨存在的理由(這通常是因為此前的重構動作移走了這個類的責任),就挑選這個“萎縮類”的最頻繁的使用者(也是個類),以Inline Class
Time of Update: 2018-12-07
Silverlight中的資源一、使用相同組件中的資源檔1、xaml檔案和資源檔目錄同級 用image樣本 <Image x:Name="Image1" Source="Images/xxx.png" /> Images檔案夾和MainPage.xaml檔案在同級目錄中 2、xaml檔案和資源檔夾不同級 <Image x:Name="Image1" Source="../Images/xxx.png"
Time of Update: 2018-12-07
在條件運算式的每個分支上有著相同的一段代碼。將這段重複代碼移到條件運算式之外。動機:一組條件運算式的所有分支都執行了相同的某段代碼。你應該將這段代碼搬移到運算式外面。這樣,代碼才能更清楚地表明哪些東西隨條件變化而變化、哪些東西保持不變。做法:1、鑒別出“執行方式不隨變化而變化”的代碼。 2、如果這些共通代碼位於條件運算式起始處,就將它移到條件運算式之前。 3、如果這些共通代碼位於條件運算式的尾端,就它移到條件運算式之後。
Time of Update: 2018-12-07
某個子類只使用超類介面中的一部分,或是根本不需要繼承而來的資料。在子類中建立一個欄位用以儲存超類;調整子類函數,令它改而委託超類;然後去掉2者之間的繼承關係。動機:繼承是個好東西,但有時候它並不是你要的。你常常會遇到這樣的情況:一開始繼承了一個類,隨後發現超類中的許多操作並不真正適用於子類。這種情況下,你所擁有的介面並未真正反映出子類的功能。或者,你可能發現你從超類中繼承了一大堆子類並不需要的資料,抑或你可能發現超類中的某些protected函數對子類並沒有什麼意義。
Time of Update: 2018-12-07
若干函數做了類似的工作,但在函數本體中卻包含了不同的值。建立一個單一函數,以參數表達那些不同的值。動機:你可能會發現這樣的2個函數:它們做著類似的工作,但因少數幾個值致使行為略為不同。這種情況下,你可以將這些各自分離的函數統一起來,並通過參數來處理那些變化,用以簡化問題。這樣的修改可以去除重複代碼,並提高靈活性,因為你可以用這個參數處理更多的變化情況。做法:1、建立一個帶有參數的函數,使它可以替換先前所有的重複性函數。 2、編譯。 3、將調用舊函數的代碼改為調用新函數。