【轉】PHP 雜談《重構-改善既有代碼的設計》之一 重新組織你的函數

来源:http://www.cnblogs.com/aiweixiao/archive/2016/10/17/5971461.html
-Advertisement-
Play Games

原文地址: PHP 雜談《重構-改善既有代碼的設計》之一 重新組織你的函數 思維導圖 點擊下圖,可以看大圖。 原文地址: PHP 雜談《重構-改善既有代碼的設計》之一 重新組織你的函數 思維導圖 點擊下圖,可以看大圖。 介紹 我把我比較喜歡的和比較關註的地方寫下來和大家分享。上次我寫了篇《php 跟 ...


原文地址: PHP 雜談《重構-改善既有代碼的設計》之一 重新組織你的函數 思維導圖   點擊下圖,可以看大圖。

   介紹   我把我比較喜歡的和比較關註的地方寫下來和大家分享。上次我寫了篇《php 跟老大的對話》。還是有很多疑問,這書幫了我不少的忙。   如果你比較繁忙,或者懶得看文字,建議你直接看截圖,也會有很大的收穫的。你可以通過比較截圖中的代碼就能知道孰優孰劣了。   代碼部分我為什麼用圖呢?因為我經常用手機看代碼,博客園的代碼在手機里亂七八糟的,還是看圖比較舒服。    專業術語   我們畢竟是用英文字母編碼,所以用一些英語單詞,更能顯示出我們的專業性。以下的英文單詞,你如果掌握了,與其他coder交流的時候會更直接,更專業。——臭顯擺一下吧,呵呵。 “*”表示文中經常提到的   inline:內聯 function:函數 *method:方法 finely grained:細粒度的 rename:重命名 query:查詢 temp:臨時(temporary)——一般指臨時變數 *extract:提取——我個人更喜歡翻譯成“提煉” *duplicate:複製 split:剖解 variable:變數 factor:因素,因數    重構原則   一、何謂重構?      名詞形式:對軟體內部結構的一種調整,目的是在不改變軟體之可察行為前提下,提高其可理解型性,降低其修改成本。   動詞形式:使用一系列重構準則,在不改變軟體之可察行為前提下,調整其結構。    二、為何重構 ?   1、經常重構可以讓代碼維持該有的形態。   2、讓代碼找到合適的位置。   3、讓軟體更易理解。   4、可以找到bug。   5、提高我們的編碼速度。

 三、重構的難題   1、修改介面命名     如果你的類中的方法是public,那麼你在rename的時候,冒著很大的風險,你不知道到底有哪些模塊在調用你的這個方法(我們經常的做法是在整個項目下做grep操作,然後逐一看各個模塊的調用和邏輯)。——所以我們在編寫類的時候不管是屬性還是方法儘量做到private,避免介面開放。     2、何時不該重構     (1)重寫所有代碼,而且現有代碼實在太混亂,重構還不如重寫。     (2)項目臨近結束的時候,應該避免重構。我們可以把重構放到二期去解決。 

 

 代碼的壞味道   一、Duplicate Code   1、同一個類,兩個方法含有相同表達式。     解決方法:你可以Extract Method提煉重覆代碼,然後讓這兩個方法都調用這個Extract Method。        2、兩個類,有相似的方法。      解決方法:(1)把兩個類的方法提出來,共同構造一個父類。              (2)把其中一個類的方法刪除,調用另一個類的方法。  二、Long Method   1、短函數:代碼閱讀費點力氣,因為我們必須經常轉換上下文去看看子程式做了什麼。但是讓small method容易理解的真正關鍵在於一個好的名字。讀者可以通過名字瞭解函數的作用,根本不必去看其中寫了些什麼。——早期的編程語言中,調用方法需要額外開銷,這使得coder不願意使用small method。但是現代的OO語言幾乎已經完全免除了process內的額外開銷(函數調用)。     2、註釋地方提煉信號:每當感覺需要以註釋來說明點什麼的時候,我們就把需要說明的東西寫進一個獨立函數中,並以其用途命名。可以對一組或甚至短短一行代碼做這件事。——只要函數名稱能夠解釋其用戶,我們也該毫不猶豫地那麼做。   "函數"理解為”做什麼“或”如何做“     3、條件式和迴圈常常也是提煉信號。     4、《代碼整潔之道》的一個例子。我們可以想想!

  三、Large Class     1、Class內數個屬性變數有相同首碼或者字尾,可使用Extract Class。     2、Class內並非大多數變數使用屬性變數,可使用Extract Class。      3、有太多代碼,可Extract Class。   四、Long Parameter   做成Introduce Parameter Object。——這個我不太贊同,因為我在使用別人方法的時候,我很少去看代碼實踐,更不要說去看裡面都用到了對象的那些屬性或者方法,取我想要的數據了。   五、Switch Statements   1、少用switch語句。——問題在於duplication。添加新case的時候,你必須找到所有case並修改它們。      2、用多態來替換它。做法:1.將switch進行Extract Method;2.MoveMethod把case里的實踐代碼放到多態性的class里。   六、 Comments   試試用Extract Method,如果還不行,那你試試Rename Method。   當你感覺需要撰寫註釋,請先嘗試重構,試著讓所有註釋變得多餘。     註釋一般用於將來的打算,還可以用於你並無十足把握的區域(為什麼做某事)。  
 重新組織你的函數     Long Method往往包含太多信息,這些信息又被錯綜複雜的邏輯掩蓋,不易鑒別。   一、Extract Method 狀況:我看見一個過長的函數或者需要一段註釋才能讓人理解用途的代碼,那麼將這段代碼放進一個獨立函數中,並讓函數名稱解釋改函數的用途。

 

動機:

簡短而有良好命名的函數:——finely grained

  1、復用機會大。

  2、函數讀起來像讀一系列comments。

  3、函數覆寫容易。

重點:函數長度關鍵在於函數名稱和函數本體之間的語義距離。如果提煉動作可以強化代碼的清晰度,那麼就去做。

作法:

  1、創建新函數,根據函數的意圖命名——以它“做什麼”命名,而不是以它“怎樣做”命名。

    =》 即使Extract Function 非常簡單,例如只是消息或函數調用,只要新Function能夠以更好方式昭示代碼意圖,你也應該提煉它。但如果你想不出更有意義的名稱,就別動它。

  2、將Extract的代碼從Source Function 中Move到New Function中。

二、Inline Method

  Method Body與Method Name一樣清晰易懂的時候,請Inline Method。

 

三、Inline Temp

一個臨時變數,只被一個簡單表達式賦值一次,而且賦值完也只使用了一次。——請Inline Temp

 

四、Replace Temp with Query

如果一個Temp變數,保存一個表達式,將這個表達式Extract Method。——這就是所謂的查詢式,query

 

動機:

  1、局部變數會使代碼難以提煉。

  2、臨時變數會驅使你寫出更長的代碼。如果改成query method,那麼class下的method,都可以獲得這份信息。——將編寫出更清晰的代碼。

  3、Replace Temp with Query往往是你運用Extract Method之前必不可少的步驟。

作法:

  1、找出只被賦值一次的臨時變數。

    =>  如果臨時變數賦值超過一次,考慮使用Split Temporary Variable將它分割成多個變數。

  2、對Temp Variable賦值的右側部分,Extract到一個獨立函數中。

           =>  將Method聲明為private,日後如果有其他class用的時候再放開它(public或protected)。

  

如果代碼組織良好,那麼你往往能發現更有效的優化方案。————如果性能真的很糟糕,那麼放回去也很容易。   五、Introduce Explaining Variable   將複雜表達式中(或其中一部分)的結果放進一個臨時變數,以此變數名稱來解釋表達式用途。  

  動機:   表達式複雜而且難以閱讀。在這種情況下,臨時變數可以幫助你將表達式分解為比較容易管理的形式。     六、Split Temporator Variable    某個臨時變數被賦值超過一次,它既不是迴圈變數,也不是集合變數。那麼針對每次賦值,創造一個獨立的,對應的臨時變數。

 

 

動機:

  1、如果臨時變數承擔多個責任,它就應該被替換為多個臨時變數。每個變數只承擔一個責任。

  2、同一個臨時變數承擔兩件不同的事情,會令review變得糊塗。

六、Remove Assignments To Parameters 如果你的代碼對參數進行賦值,那麼以一個臨時變數取代該參數的位置。  

 

七、Replace Method with Method Object

大型函數對局部變數的使用無法採用Extract Method。那麼將這個Method放進一個單獨對象中,如此一來,讓局部變數成為對象的filed,然後在同一個對象中將大型函數分解為數個小型Method。

 

 

動機:

  1、將相對獨立的代碼從大型Method中Extract出來,就可以大大提高代碼的可讀性。

  2、一個Method中,局部變數泛濫成災,分解這個函數將會非常困難。

  3、Replace Method with Method Object 會將所有局部變數變成對象的值域。然後對這個新對象進行Extract Method了。

八、Substitute Algorithm   如果你想把某個演算法替換為另一個更清晰的演算法,那麼將Method Body替換為另一個演算法。——就是直接修改原來的Method Body。   動機:隨著對問題有了更多的瞭解,你發現一件事可以有更清晰的方式,就應該以較清晰的方式取代複雜方式。    總結   這隻是本書的一部分內容,我知道會有很多的coder應該有不同的觀點,我自己也是,有的很贊同,有的我也是不太贊同的。所以要“則其善之而從之,其不善之而改之”。   歡迎大家發表下自己的看法。

 


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

-Advertisement-
Play Games
更多相關文章
  • 1,打開window->Preferences,彈出Preferences面板。搜索Text Editors。找到background color,去掉system default。如圖: 重點:色調85,飽和度123,亮度205 2,自動生成特定代碼 :window->preferences->j ...
  • python官網:python-2.7.12.amd64.msihttps://pypi.python.org/pypi/setuptools:setuptools-28.6.0.zipsetuptools-28.6.0>python setup.py installhttps://pypi.pyt ...
  • "視頻轉字元動畫 Python 60行代碼" , 轉載請註明出處。 昨晚一朋友跟我說在網上看到了別人做的字元視頻,覺得很厲害,我於是也打算玩玩。今天中午花時間實現了這樣一個小玩意。 順便把過程記錄在這裡。 步驟 1. 把視頻的幀保存為圖片 2. 把圖片轉化為字元圖片 3. 按順序播放圖片 模塊 這個 ...
  • 聲明:參考了羅某某的RPG教程 PS:由於博客園不支持VB的代碼,所以可行的地方暫用VB.net代替。 一、設置透明色 1.在VB新建一個工程,在窗體Form1的屬性面板中設置其名稱為main,AutoRedraw(自動重畫)為true(真),scalemode(縮放模式)為3-pixel(像素). ...
  • 利用 Spring IOC 技術實現用戶登錄的驗證機制,對用戶進行登錄驗證。 首先利用 Spring 的自動裝配模式將 User 對象註入到控制器中,然後將用戶輸入的用戶名和密碼與系統中限定的合法用戶的用戶名和密碼進行匹配。 當用戶名與密碼匹配成功時,跳轉到登錄成功頁面;當用戶名與密碼不匹配時,跳轉 ...
  • 一、預備知識—程式的記憶體分配 一個由C/C++編譯的程式占用的記憶體分為以下幾個部分 : 1、棧區(stack)— 由編譯器自動分配釋放 ,存放函數的參數值,局部變數的值等。其 操作方式類似於數據結構中的棧。 2、堆區(heap) — 一般由程式員分配釋放, 若程式員不釋放,程式結束時可能由OS回 收 ...
  • 我扮演的角色是駕駛員 一、結對伙伴 領航員:趙峻 作業地址見我的博客。 二、代碼地址 https://coding.net/u/k2048/p/huangjindian/git/blob/master/main.c 三、總結 1、個人總結 本次作業我扮演駕駛員,趙峻扮演領航員,我負責演算法實現以及代碼 ...
  • 【Python練習題 023】 有5個人坐在一起,問第五個人多少歲?他說比第4個人大2歲。問第4個人歲數,他說比第3個人大2歲。問第三個人,又說比第2人大兩歲。問第2個人,說比第一個人大兩歲。最後 問第一個人,他說是10歲。請問第五個人多大? 這題真是……用心算就能算出來好嗎?好吧,應該又是要訓練遞 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...