自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

提高代碼質(zhì)量:如何編寫函數(shù)

開發(fā) 后端 前端
本文從函數(shù)命名,函數(shù)參數(shù)和函數(shù)的代碼編寫三個(gè)方面談了關(guān)于如何編寫好一個(gè)函數(shù)的感受和想法。文中提到了很多具體的情況,當(dāng)然日常編碼中肯定會(huì)遇到更多復(fù)雜的情況可能我暫時(shí)沒(méi)有想到。

函數(shù)是實(shí)現(xiàn)程序功能的最基本單位,每一個(gè)程序都是由一個(gè)個(gè)最基本的函數(shù)構(gòu)成的。寫好一個(gè)函數(shù)是提高程序代碼質(zhì)量最關(guān)鍵的一步。本文就函數(shù)的編寫,從函數(shù)命名,代碼分布,技巧等方面入手,談?wù)勅绾螌懞靡粋€(gè)可讀性高、易維護(hù),易測(cè)試的函數(shù)。

[[163037]]

命名

首先從命名說(shuō)起,命名是提高可讀性的***步。如何為變量和函數(shù)命名一直是開發(fā)者心中的痛點(diǎn)之一,對(duì)于母語(yǔ)非英語(yǔ)的我們來(lái)說(shuō),更是難上加難。下面我來(lái)說(shuō)說(shuō)如何為函數(shù)命名的一些想法和感受:

采用統(tǒng)一的命名規(guī)則

在談及如何為函數(shù)取一個(gè)準(zhǔn)確而優(yōu)雅的名字之前,首先最重要的是要有統(tǒng)一的命名規(guī)則。這是提高代碼可讀性的最基礎(chǔ)的準(zhǔn)則。
帕斯卡命名法和駝峰命名法是目前比較流行的兩種規(guī)則,不同語(yǔ)言采用的規(guī)則可能不一樣,但是要記住一點(diǎn):保持團(tuán)隊(duì)和個(gè)人風(fēng)格一致。

1、帕斯卡命名法

帕斯卡命名法簡(jiǎn)單地說(shuō)就是:多個(gè)單詞組成一個(gè)名稱時(shí),每個(gè)單詞的首字母大寫。比如:

  1. public void SendMessage (); 
  2. public void CalculatePrice (); 

在C#中,這種命名法常用于類、屬性,函數(shù)等等,在JS中,構(gòu)造函數(shù)也推薦采用這種方式命名。

2、駝峰命名法

駝峰命名法和帕斯卡命名法很類似,多個(gè)單詞組成一個(gè)名稱時(shí),***個(gè)單詞全部小寫,后面單詞首字母大寫。比如:

  1. var sendMessage = unction () {}; 
  2. var calculatePrice = function () {}; 

駝峰命名法一般用于字段、局部變量、函數(shù)參數(shù)等等。,在JS中,函數(shù)也常用此方法命名。

采用哪種命名規(guī)則并不絕對(duì),最重要的是要遵守團(tuán)隊(duì)約定,語(yǔ)言規(guī)范。

盡可能完整地描述函數(shù)所做的所有事情

有的開發(fā)者可能覺(jué)得相較于長(zhǎng)函數(shù)名來(lái)說(shuō),短函數(shù)名看起來(lái)可能更簡(jiǎn)潔,看起來(lái)也更舒服。但是通常來(lái)說(shuō),函數(shù)名稱越短其描述的意思越抽象。函數(shù)使用者對(duì) 函數(shù)的***印象就是函數(shù)名稱,進(jìn)而了解函數(shù)的功能,我們應(yīng)該盡可能地描述到函數(shù)所做的所有事情,防止使用者不知道或誤解造成潛在的錯(cuò)誤。

舉個(gè)例子,假設(shè)我們做一個(gè)添加評(píng)論的功能,添加完畢后并返回評(píng)論總數(shù)量,如何命名比較合適呢?

  1. // 描述不夠完整的函數(shù)名 
  2. var count = function addComment() {} 
  3. // 描述完整的函數(shù)名 
  4. var count = function addCommentAndReturnCount() {}; 

這只是簡(jiǎn)單的一個(gè)例子,實(shí)際開發(fā)中可能會(huì)遇到得更多復(fù)雜的情況,單一職責(zé)原則是我們開發(fā)函數(shù)要遵守的準(zhǔn)則,但是有時(shí)候無(wú)法做到函數(shù)單一職責(zé)時(shí),請(qǐng)記 得函數(shù)名應(yīng)該盡可能地描述所有事情。當(dāng)你無(wú)法命名一個(gè)函數(shù)時(shí),應(yīng)該分析一下,這個(gè)函數(shù)的編寫是否科學(xué),有什么辦法可以去優(yōu)化它。

采用準(zhǔn)確的描述動(dòng)詞

這一點(diǎn)對(duì)母語(yǔ)非英語(yǔ)的開發(fā)者來(lái)說(shuō)應(yīng)該是比較難的一點(diǎn),想要提高這方面的能力,最主要的還是要提高詞匯量,多閱讀優(yōu)秀代碼積累經(jīng)驗(yàn)。

這里簡(jiǎn)單說(shuō)說(shuō)我自己的一些感想和看法:

1、不要采用太抽象廣泛的單詞

很多開發(fā)人員會(huì)采用一個(gè)比較寬泛的動(dòng)詞來(lái)為函數(shù)命名,最典型的一個(gè)例子就是get這個(gè)單詞。我們平時(shí)開發(fā)中經(jīng)常會(huì)通過(guò)各種不同的方式拿到數(shù)據(jù),但是每一種方式都用get就有點(diǎn)太抽象了。具體如何命名,要具體分析:

(1)簡(jiǎn)單的返回?cái)?shù)據(jù)

  1. Person.prototype.getFullName = function() { 
  2. return this.firstName = this.lastName; 

(2)從遠(yuǎn)程獲取數(shù)據(jù)

  1. var fetchPersons = function () { 
  2.  ... 
  3.     $.ajax({ 
  4.  }) 

(3)從本地存儲(chǔ)加載數(shù)據(jù)

  1. var loadPersons = function () {}; 

(4)通過(guò)計(jì)算獲取數(shù)據(jù)

  1. var calculateTotal = function () {}; 

(5)從數(shù)組中查找數(shù)據(jù)

  1. var findSth = function (arr) {}; 

(6)從一些數(shù)據(jù)生成或得到

  1. var createSth = function (data) {}; 
  2. var buildSth = function (data) {}; 
  3. var parseSth = function(data) {}; 

這是一個(gè)簡(jiǎn)單的例子,我們平時(shí)開發(fā)中遇到的情況肯定會(huì)復(fù)雜得多,關(guān)鍵還是靠單詞的積累,多閱讀優(yōu)秀源碼

下面是整理的一些常用的對(duì)仗詞,大家可以參考使用

  1. add/remove        increment/decrement       open/close 
  2. begin/end            insert/delete                      show/hide 
  3. create/destory    lock/unlock                        source/target 
  4. first/last              min/max                             star/stop 
  5. get/put                next/previous                     up/down     
  6. get/set                old/new 

根據(jù)不同項(xiàng)目和需求制定好命名規(guī)則

這一點(diǎn)也是很重要的,尤其是在團(tuán)隊(duì)合作中,不同的項(xiàng)目和需求可能導(dǎo)致的不同的命名規(guī)則。
比如我們通常采用的命名規(guī)則是動(dòng)賓結(jié)構(gòu),也就是動(dòng)詞在前,名詞災(zāi)后。但是有一些項(xiàng)目,比如數(shù)據(jù)接口等項(xiàng)目中,有的團(tuán)隊(duì)會(huì)采用名字在前,動(dòng)詞在后的形式,例如:

  1. public static Product[] ProductsGet(){}; 
  2. public static Product[] ProductsDel(){}; 
  3. public static Customer[] CustomerDel(){}; 
  4. public static Customer[] CustomerDel(){}; 

這種的好處是看到前面的名詞,比如ProductsGet,就能很快的知道這是產(chǎn)品相關(guān)的數(shù)據(jù)接口。
當(dāng)然這個(gè)并不是絕對(duì)的,關(guān)鍵還是要團(tuán)隊(duì)共同制定和遵守同一套命名規(guī)則。

函數(shù)參數(shù)

函數(shù)使用者在調(diào)用函數(shù)時(shí),必須嚴(yán)格遵守函數(shù)定義的參數(shù),這對(duì)函數(shù)的易用性,可測(cè)試性等方面都是至關(guān)重要的。下面我從幾個(gè)方面來(lái)談?wù)勱P(guān)于如何優(yōu)化好函數(shù)參數(shù)的一些想法。

參數(shù)數(shù)量

毫無(wú)疑問(wèn),函數(shù)參數(shù)越多,函數(shù)的易用性就越差,因?yàn)槭褂谜咝枰獓?yán)格眼中參數(shù)列表依次輸入?yún)?shù),如果某個(gè)參數(shù)輸錯(cuò),將導(dǎo)致不可意料的結(jié)果。

但是,函數(shù)參數(shù)就一定越少越好嗎?我們來(lái)看看下面的例子:

  1. var count = 0
  2. var unitPrice = 1.5
  3. .... 
  4. ... 
  5. var calculatePrice = function () { 
  6.     return count * unitPrice; 

在這個(gè)例子中,我們通過(guò)calculatePrice這個(gè)函數(shù)來(lái)計(jì)算價(jià)格,函數(shù)不接收任何參數(shù),直接通過(guò)兩個(gè)全局變量unitPrice和 count進(jìn)行計(jì)算。這種函數(shù)的定義對(duì)使用者來(lái)說(shuō)非常方便,直接調(diào)用即可,不用輸入任何參數(shù)。但是這里可能會(huì)有潛在的bug:全局變量可能在其他地方被修 改成其他值了,難以進(jìn)行單元測(cè)試等等問(wèn)題。所以,這個(gè)函數(shù)可以傳入數(shù)量和價(jià)格信息:

  1. var calculatePrice = function(count, unitPrice) { 
  2.     return count * unitPrice; 

這種方式下,函數(shù)使用者在使用時(shí),要傳入?yún)?shù)進(jìn)行調(diào)用,避免了全局變量可能存在的問(wèn)題。另外也降低了耦合,提高了可測(cè)試性,在測(cè)試的時(shí)候就不必依賴于全局變量。

當(dāng)然,在保證函數(shù)不依賴于全局變量和測(cè)試性的情況下,函數(shù)參數(shù)還是越少越好?!洞a大全》中提出將函數(shù)的參數(shù)限制在7個(gè)以內(nèi),這個(gè)可以作為我們的參考。
有的時(shí)候,我們不可避免地要使用超過(guò)10個(gè)以上函數(shù),在這中情況下,我們可以考慮將類似的參數(shù)構(gòu)造成一個(gè)類,我們來(lái)看看一個(gè)典型的例子。

我相信大家平時(shí)一定做過(guò)這樣的功能,列表篩選,其中涉及到各種條件的篩選,排序,分頁(yè)等等功能,如果將參數(shù)一個(gè)一個(gè)地列出來(lái)必定會(huì)很長(zhǎng),例如:

  1. var filterHotel = function (city, checkIn, checkOut, price, star, position, wifi, meal, sort, pageIndex) {} 

這是一個(gè)篩選酒店的函數(shù),其中的參數(shù)分別是城市,入住和退房時(shí)間,價(jià)格,***,位置,是否有wifi,是否有早餐,排序,頁(yè)碼等等,實(shí)際的情況可能會(huì)更多。在這種參數(shù)特別多的情況下,我們可以考慮將一些相似的參數(shù)提取成類出來(lái):

  1. function DatePlace (city, checkIn, checkOut){ 
  2.     this.city = city; 
  3.     this.checkIn = checkIn; 
  4.      this.checkOut = checkOut 
  5. function HotelFeature (price, star, position, wifi, meal){ 
  6.     this.price = price; 
  7.     this.star = star; 
  8.      this.position = position; 
  9.     this.wifi = wifi; 
  10.     this.meal = meal; 
  11.  } 
  12.  var filterHotel = function (datePlce, hotelFeature, sort, pageIndex) {}; 

將多個(gè)參數(shù)提取成對(duì)象了,雖然對(duì)象數(shù)量增多了,但是函數(shù)參數(shù)更清晰了,調(diào)用起來(lái)也更方便了。

盡量不要使用bool類型作為參數(shù)

有的時(shí)候,我們會(huì)寫出使用bool作為參數(shù)的情況,比如:

  1. var getProduct = function(finished) { 
  2.    if(finished){ 
  3.    } 
  4.   else
  5.    } 
  6.  } 
  7. // 調(diào)用 
  8. getProduct(true); 

如果沒(méi)有注釋,使用者看到這樣的代碼:getProduct(true),他肯定搞不清楚true是代表什么意思,還要去查看函數(shù)定義才能明白這個(gè)函數(shù)是如何使用的。這就意味著這個(gè)函數(shù)不夠清晰,就應(yīng)該考慮去優(yōu)化它。通常有兩種方式去優(yōu)化它:

(1)將函數(shù)一分為二,分成兩個(gè)函數(shù)getFinishedProduct和getUnFinishedProduct
(2)將bool轉(zhuǎn)換成有意義的枚舉getProduct(ProductStatus)

不要修改輸入?yún)?shù)

如果輸入?yún)?shù)在函數(shù)內(nèi)被修改了,很有可能造成潛在的bug,而且使用者不知道調(diào)用函數(shù)后居然會(huì)修改函數(shù)參數(shù)。
正確使用輸入?yún)?shù)的做法應(yīng)該是只傳入?yún)?shù)用于函數(shù)調(diào)用。

如果不可避免地要修改,一定要在注釋中說(shuō)明。

盡量不要使用輸出參數(shù)

使用輸出參數(shù)說(shuō)明這個(gè)函數(shù)不只做了一件事情,而且使用者使用的時(shí)候可能還會(huì)感到困惑。正確的方式應(yīng)該是分解函數(shù),讓函數(shù)只做一件事。

編寫函數(shù)體

函數(shù)體就是實(shí)現(xiàn)函數(shù)功能的整個(gè)邏輯,是一個(gè)函數(shù)最關(guān)鍵的地方。下面我談?wù)勱P(guān)于函數(shù)代碼編寫的一些個(gè)人想法。

相關(guān)操作放在一起

有的時(shí)候,我們會(huì)在一個(gè)函數(shù)內(nèi)進(jìn)行一系列的操作來(lái)完成一個(gè)功能,比如:

  1. var calculateTotalPrice = function()  { 
  2.    var roomCount = getRoomCount(); 
  3.    var mealCount = getMealCount(); 
  4.     var roomPrice = getRoomPrice(roomCount); 
  5.    var mealPrice = getMealPrice(mealCount); 
  6.    return roomPrice + mealPrice; 

這段代碼計(jì)算了房間價(jià)格和早餐價(jià)格,然后將兩者相加返回總價(jià)格。

這段代碼乍一看,沒(méi)有什么問(wèn)題,但是我們分析代碼,我們先是分別獲取了房間數(shù)量和早餐數(shù)量,然后再通過(guò)房間數(shù)量和早餐數(shù)量分別計(jì)算兩者的價(jià)格。這種 情況下,房間數(shù)量和計(jì)算房間價(jià)格的代碼分散在了兩個(gè)位置,早餐價(jià)格的計(jì)算也是分散到了兩個(gè)位置。也就是兩部分相關(guān)的代碼分散在了各處,這樣閱讀起代碼來(lái)邏 輯會(huì)略顯不通,代碼組織不夠好。我們應(yīng)該讓相關(guān)的語(yǔ)句和操作放在一起,也有利于重構(gòu)代碼。我們修改如下:

  1. var calculateTotalPrice = function()  { 
  2.    var roomCount = getRoomCount(); 
  3.    var roomPrice = getRoomPrice(roomCount); 
  4.    var mealCount = getMealCount(); 
  5.   var mealPrice = getMealPrice(mealCount); 
  6.   return roomPrice + mealPrice; 

我們將相關(guān)的操作放在一起,這樣代碼看起來(lái)更清晰了,而且也更容易重構(gòu)了。

盡量減少代碼嵌套

我們平時(shí)寫if,switch或for語(yǔ)句是常有的事兒,也一定寫過(guò)多層if或for語(yǔ)句嵌套的情況,如果代碼里的嵌套超過(guò)3層,閱讀起來(lái)就會(huì)非常困難了。我們應(yīng)該盡量避免代碼嵌套多層,***不要超過(guò)2層。下面我來(lái)說(shuō)說(shuō)我平時(shí)一些減少嵌套的技巧或方法。

if語(yǔ)句嵌套的問(wèn)題

多層if語(yǔ)句嵌套是常有的事情,有什么好的方法可以減少嵌套呢?

1、盡早終止函數(shù)或返回?cái)?shù)據(jù)

如果符合某個(gè)條件下可以直接終止函數(shù),則應(yīng)該將這個(gè)條件放在***位。我們來(lái)看看下面的例子。

  1.  if(condition1) { 
  2.     if(condition2){ 
  3.         if(condition3){ 
  4.         } 
  5.         else
  6.             return
  7.          }    
  8.     } 
  9.    else
  10.         return
  11.     }    
  12.  } 
  13. else { 
  14.     return
  15.  } 

這段代碼中if語(yǔ)句嵌套了3層,看起來(lái)已經(jīng)很復(fù)雜了,我們可以將***面的return提取到最前面去。

  1.  if(!condition1){ 
  2.  return
  3. if(!condition2){ 
  4.     return
  5.  if(!condition3){ 
  6.      return
  7.  } 
  8.  //doSth 

這段代碼中,我們把condition1等于false的語(yǔ)句提取到前面,直接終止函數(shù),將多層嵌套的if語(yǔ)句重構(gòu)成只有一層if語(yǔ)句,代碼也更清晰了。

注意:一般情況下,我們寫if語(yǔ)句會(huì)將條件為true的情況寫在前面,這也比較符合我們的思維習(xí)慣。如果是多層嵌套的情況,應(yīng)該優(yōu)先減少if語(yǔ)句的嵌套

2、不適用if語(yǔ)句或switch語(yǔ)句

條件語(yǔ)句一般來(lái)說(shuō)是不可避免的,有的時(shí)候,我們要判斷很多條件就會(huì)寫很多if-elseif語(yǔ)句,嵌套的話,就更加麻煩了。如果有一天增加了新需 求,我們就要去增加一個(gè)if分支語(yǔ)句,這樣不僅修改起來(lái)麻煩,而且容易出錯(cuò)。《代碼大全》提出的表驅(qū)動(dòng)法可以有效地解決if語(yǔ)句帶來(lái)的問(wèn)題。我們來(lái)看下面 這個(gè)例子:

  1. if(condition == “case1”){ 
  2.     return 1
  3.  } 
  4.  elseif(condition == “case2”){ 
  5.      return 2
  6.  } 
  7. elseif(condition == “case3”){ 
  8.      return 3
  9.  } 
  10.  elseif(condition == “case4”){ 
  11.      return 4
  12.  } 

這段代碼分別依次判斷了四種情況,如果再增加一種情況,我們就要再新增一個(gè)if分支,這樣就可能造成潛在的問(wèn)題,如何去優(yōu)化這段代碼呢?我們可以采用一個(gè)Map或Dictionary來(lái)將每一種情況和相應(yīng)值一一對(duì)應(yīng)。

  1. var map = { 
  2.   "case1":1
  3.   "case2":2
  4.   "case3":3
  5.   "case4":4 
  6. return map[condition]; 

通過(guò)map優(yōu)化后,整個(gè)代碼不僅更加簡(jiǎn)潔,修改起來(lái)也更方便而且不易出錯(cuò)了。

當(dāng)然,很多時(shí)候我們的條件判斷語(yǔ)句并不是這么簡(jiǎn)單的,可能會(huì)涉及到復(fù)雜的邏輯運(yùn)算,大家可以查看《代碼大全》第18章,其中有詳細(xì)的介紹。

3、提取內(nèi)層嵌套為一個(gè)函數(shù)進(jìn)行調(diào)用

多層嵌套的時(shí)候,我們還可以將內(nèi)層嵌套提取到一個(gè)新的函數(shù)中,然后調(diào)用該函數(shù),這樣代碼也就更清晰了。

for循環(huán)嵌套優(yōu)化

for循環(huán)嵌套相比于if嵌套來(lái)說(shuō)更加復(fù)雜,閱讀起來(lái)會(huì)更麻煩,下面說(shuō)說(shuō)幾點(diǎn)要注意的東西:

1、最多只能兩層for循環(huán)嵌套
2、提取內(nèi)層循環(huán)到新函數(shù)中
3、多層循環(huán)時(shí),不要簡(jiǎn)單地位索引變量命名為i,j,k等,容易造成混淆,要有具體的意思

提取復(fù)雜邏輯,語(yǔ)義化

有的時(shí)候,我們會(huì)寫出一些比較復(fù)雜的邏輯,閱讀代碼的人看到后可能搞不清楚要做什么,這個(gè)時(shí)候,就應(yīng)該提取出這段復(fù)雜的邏輯代碼。

  1. if (age > 18 && gender == "man") { 
  2.   //doSth 
  3.  } 

這段代碼表示當(dāng)年齡大于18并且是男性的話,可以doSth,但是還是不夠清晰,可以將其提取出來(lái)

  1.  var canDoSth = function (age, gender){ 
  2.     return age > 18 && gender == "man"
  3.  } 
  4. ... 
  5. ... 
  6. ... 
  7. if(canDoSth(age, gender)){ 
  8.     //doSth 
  9.  } 

雖說(shuō)多了一個(gè)函數(shù),但是代碼更加清晰和語(yǔ)義化了。

總結(jié)

本文從函數(shù)命名,函數(shù)參數(shù)和函數(shù)的代碼編寫三個(gè)方面談了關(guān)于如何編寫好一個(gè)函數(shù)的感受和想法。文中提到了很多具體的情況,當(dāng)然日常編碼中肯定會(huì)遇到更多復(fù)雜的情況可能我暫時(shí)沒(méi)有想到。我簡(jiǎn)單的歸納了幾點(diǎn):

1、準(zhǔn)確地對(duì)變量、函數(shù)命名
2、不要有重復(fù)邏輯的代碼
3、函數(shù)的行數(shù)不要超過(guò)20行,這里的20行只是個(gè)大概,并不一定是這個(gè)數(shù)字
4、減少嵌套

我相信大家一定會(huì)很多關(guān)于這方面的經(jīng)驗(yàn),歡迎進(jìn)行交流,共同提高代碼質(zhì)量。

 

責(zé)任編輯:王雪燕 來(lái)源: 狼狼的藍(lán)胖子
相關(guān)推薦

2016-02-24 16:03:34

代碼質(zhì)量編寫函數(shù)

2022-08-04 09:01:45

TypeScriptMicrosoft

2023-01-06 18:31:46

準(zhǔn)確命名

2012-11-07 09:48:26

2017-08-18 13:02:15

大數(shù)據(jù)數(shù)據(jù)質(zhì)量

2011-03-04 10:11:09

JavascriptAPI

2009-06-03 15:31:40

Eclipse插件提高代碼質(zhì)量

2012-04-09 15:40:31

PHP

2012-11-02 14:37:58

代碼編程語(yǔ)言

2015-05-06 09:20:34

代碼質(zhì)量代碼審查實(shí)踐

2015-08-11 09:39:25

重構(gòu)提高代碼質(zhì)量

2024-05-21 10:40:09

開發(fā)前端裝飾器

2020-02-26 12:03:36

代碼漏洞產(chǎn)品質(zhì)量

2012-07-30 13:15:18

代碼

2015-07-15 10:27:48

Android代碼質(zhì)量工具

2022-03-25 09:22:42

代碼開發(fā)

2011-04-01 09:13:19

VB程序員

2010-05-20 09:07:30

jQuery

2024-02-19 14:50:42

編碼原則軟件開發(fā)

2015-08-25 08:29:11

編寫高質(zhì)量命名
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)