首頁 php教程 php手册 【轉】PHP 雜談《重建-改善既有程式碼的設計》之一 重新組織你的函數

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

Oct 18, 2016 am 08:42 AM

原文位址: 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應該有不同的觀點,我自己也是,有的很贊同,有的我也是不太贊同的。所以要「則其善之而從之,其不善之而改之」。
 
歡迎大家發表下自己的看法。

 

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1655
14
CakePHP 教程
1413
52
Laravel 教程
1306
25
PHP教程
1252
29
C# 教程
1226
24