【重構學習】09 函數調用的重構

来源:http://www.cnblogs.com/vvjiang/archive/2016/01/10/5117677.html
-Advertisement-
Play Games

之前寫了個函數的重構,這裡寫的是函數的調用的重構,不同哦,是為了寫出讓別人好調用的函數(或介面)。1、函數改名修改點:函數的名稱未能提示函數的用途。做法:修改函數的名稱如果你想給函數寫上一句什麼註釋,那麼你就把這個註釋想辦法作為名稱寫上好了。Martin原話:你可能無法第一次就取一個好名字,這個時候...


之前寫了個函數的重構,這裡寫的是函數的調用的重構,不同哦,是為了寫出讓別人好調用的函數(或介面)。

1、函數改名

修改點:函數的名稱未能提示函數的用途。

做法:修改函數的名稱

如果你想給函數寫上一句什麼註釋,那麼你就把這個註釋想辦法作為名稱寫上好了。

Martin原話:

你可能無法第一次就取一個好名字,這個時候你就會想,就這麼將就著吧,畢竟這隻是一個名稱。

當心,這是惡魔的召喚,是通向混亂之路,千萬不要被它誘惑。

我就無數次被誘惑,然後取了很多渣名,因為想一個好名字真是太難了,除非我把函數名寫很長

2、添加參數

修改點:某個函數需要從調用端得到更多信息

做法:為此函數添加一個對象參數,讓該對象帶進函數所有信息。

3、移除參數(好吧,相比第二點,很多人可能會嫌麻煩不去搞這個,惡魔的誘惑哦

修改點:函數本體不再需要某個參數

做法:將該參數去除

4、將查詢函數和修改函數分離所以直接用屬性就好了啊

修改點:某個函數既返回對象狀態值,又修改對象狀態

做法:建立兩個不同的函數,其中一個負責查詢,又負責修改

存在例外哦,就是併發場景下同時查詢與修改的操作,那麼你仍應該分離,但是單獨寫一個函數去同時進行這兩個事情。

5、令函數攜帶參數

修改點:若幹函數做了類似工作,但在函數本體中卻包含不同的值

做法:建立單一函數,以參數表達那些不同的值

簡單來說,就是兩個函數有很多相同部分,就幾個值不同,你把這幾個值作為函數參數,那麼就可以把兩個函數合二為一

6、以明確函數替代參數(與5相反哦

修改點:你有一個函數,其中完全取決於參數值而採用不同行為(看好是完全

做法:針對該參數的每一個可能值,建立一個獨立函數

意思就是說你根據參數的判斷而採取不同的行為,那麼你完全可以分成幾個函數來實現。

而如果影響並不是很大,用5就好了,如果確實需要條件判斷,那麼可以考慮使用多態來消除條件判斷

7、保持對象完整

修改點:你從某個對象中去除若幹值,將它們作為某一次函數調用時的參數

做法:改為傳遞整個對象

動機:萬一將來函數需要新的數據項,你就必須查找並修改對此函數的所有調用。而且這樣也能提高整個代碼的可讀性。

但是也有例外:如果你穿的是數值,那麼函數就僅僅依賴於數值,但是如果是對象,那麼依賴的就是整個對象,這有可能會造成你的結構惡化,所以你得具體情況具體分析。

不過如果一個函數使用了另外一個對象很多的值,那麼你可能需要考慮是不是需要把這個函數放在那個對象所屬的類裡面了。

 8、以函數取代參數

修改點:對象調用某個函數,並將所有結果作為參數,傳遞給另外一個函數

做法:讓參數接受者去除該項參數,並直接調用前一個函數

動機:如果函數可以通過其它途徑獲取參數值,那麼它就不應該通過參數取得該值。過長的參數列會增加程式員的理解難度,因此應該儘可能縮短參數列的長度。

9、引入參數對象

修改點:某些參數總是很自然地同時出現

做法:以一個對象取代這些參數

之前在何處重構里已經講過了,其它的章節貌似也涉及到了。這種類其實也有其他的好處,比如你建立了這樣一個類,說不定有些函數就可以放到這個類里,讓代碼結構更清晰。

10、移除設置函數

修改點:類中的某個欄位應該在對象創建時被設值,然後就不再改變

做法:去掉該欄位的所有設置函數

意思就是說如果初始化的時候就不需要改變某個欄位,那麼你就不要去添加設置函數,這樣會讓意圖不明確。

11、隱藏函數

修改點:有一個函數,從來沒有被其他任何類用到

做法:將這個函數修改為private

還是這個意思,讓調用者看到他們應該看到的,和想看到的,不要暴露給他們過多的信息,越簡單越好,他們用起來越方便,也有利於安全性。

12、以工廠函數替代構造函數

修改點:你希望在創建對象時不僅僅是做簡單的建構工作。

做法:將構造函數替換為工廠函數

很簡單,在數據的重構里第14點我的例子就是這樣的。

    public class Room
    {
        public Room() { 
        
        }
        public static Room CreateRoom()
        {
            return new Room();
        }

    }

這個東西用來多態去除類型碼,去除過多的條件表達式特別有效

也就是在CreateRoom里用來判斷Room類型來創建Room的不同子類,當然在類型較少的情況下,你也可以加多個工廠函數,分別創建不同的子類

13、封裝向下轉型

修改點:某個函數返回的對象,需要由函數調用者執行向下轉型。

做法:將向下轉型動作移到函數中

簡單例子:

    public class Room
    {
        public Room() { 
        
        }
        public Object GetRandRoom() {
            return RoomList.GetRandRoom(new Random().Next());
        }

    }

應該轉為

     public class Room
    {
        public Room() { 
        
        }
        public Room GetRandRoom() {
            return (Room)RoomList.GetRandRoom(new Random().Next());
        }

    }

也就是說有些系統函數或者別人寫的函數經過處理後返回一個object對象,但是你知道這個object對象是Room類型,那麼請把它轉化為Room類型,也就是說儘量在更底層就轉型,而不是在調用端轉型,這個增加調用者的理解難度。

這種情況可能會在返回迭代器或者集合的函數身上發生

不過貌似我們.NET幾乎不會出現這種情況,起碼我遇到的代碼就沒見過,是我見過的代碼太少呢,還是說大家都很厲害的樣子,避開了這個坑。

14、以異常取代錯誤碼

修改點:某個函數返回一個特定的代碼,用以表示某種錯誤情況

做法:改為拋異常

好吧這個應該不用我來說了吧,不過很多人(包括我)都習慣返回錯誤碼,因為簡單,大家共勉,以圖改進吧。

順便提一點,對.NET的錯誤機制,也就是try catch finally throw這幾個東西用到時候要小心點,這個東西存在很多的爭議,就是你拋出的異常應該是可控的異常,而不應該是不知道是什麼鬼的異常,如果是不知道是什麼鬼的異常就應該立馬解決了,而不是吞掉。

15、以條件判斷取代異常

修改點:面對一個調用者可以預先檢查的條件,你拋出一個異常

做法:修改調用者,使它在調用函數之前先做檢查。

好吧,這個東西也就是消除異常,也就是說比如這個異常你可以提前預料到,你就應該去直接用個某種手段去檢查,檢查不通過就返回你catch後執行的操作,而不是不去檢查,直接try catch。坦白說,其實try catch里的代碼越少越好,因為找到異常後定位異常也需要資源。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 首先還是先感謝github,感謝github上提供此段源碼的作者。跟昨晚的來比今天的靜態文件伺服器有點點複雜些,可以學到很多新的東西。仔細會發現這次的代碼多了一個fs.stat函數和ReadStream對象的pipe函數,stat這個函數是用來獲取文件信息。第一個參數是傳入文件路徑,第二個則是回調函...
  • 目錄結構參數介紹/*** * Created by laixiangran on 2015/12/22. * karma單元測試配置文件 */module.exports = function(config) { config.set({ /*** * 基礎路徑,...
  • 昨天在解決了盒模型的問題之後又出現了新的知識模糊點:浮動和絕對定位?今天先解決浮動相關的問題,首先列舉出想要解決的問題:1.浮動到底是怎麼樣的?2.浮動對元素的影響有什麼?3.浮動主要用來乾什麼?第一個問題:浮動到底是怎麼樣的?W3CSCHOOL對浮動屬性的解釋:浮動的框可以向左或向右移動,直到它的...
  • DOM1級主要定義了文檔的底層結構,並提供了基本的查詢操作的API,總體而言這些API已經比較完善,我們可以通過這些API完成大部分的DOM操作。然而,為了擴展DOM API的功能,同時進一步提高DOM操作的效率,DOM擴展也不斷被提出和採納。對DOM的擴展主要有兩部分:Selectors API和...
  • 一、引言 很久沒有寫過博客了,但是最近這段時間都沒有閑著,接觸了很多方面。比如一些前端框架和組件、還有移動開發React-Native、以及對.NET框架設計的一些重新認識。這些內容在接下來的時間都會一一和大家分享的。我為什麼放置了這麼久又重新寫博客呢?因為在這段時間裡面,我雖然接觸了這麼多東西,....
  • 在iOS中,apple提供了AVFoundation 用來處理音視頻,基本能滿足一些常用的音視頻處理需求,而且能調用的硬體編解碼介面,能提高不少效率,這是其它庫所不能達到的。最近做過的Recnow SDK中已經集成了這些功能,像一些視頻長度剪輯、視頻插入、視頻轉場、添加配音、添加動畫效果等,還有一些...
  • 設想有一個游戲,游戲中有各種鴨子,它們可以飛,也可以呱呱叫。這樣一個游戲該怎樣設計呢?一、使用繼承:鴨子雖然有不同的種類,但是也有一定的相同之處,所以我們可以從鴨子中提取一個父類Duck,讓不同種類的鴨子類繼承自父類,將所有鴨子共有的屬性和行為放到父類中。這樣做看似沒有錯誤,但實際上存在以下兩個方面...
  • 在使用Excel編寫VBA程式時,用到ListBox,然後研究了下它的所有屬性。其實這個控制項功能很不好用,太老了,最重要的是還不支持滑鼠滾輪,很不好操作,但是考慮到相容性,還是使用它。 其實讀取、寫入數據用ListBox.List已經足夠了,而BoundColumn和TextColumn主...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...