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

為什么Swift中應該避免使用guard語句

移動開發(fā)
Guard語句很便于用來減少結構體和函數(shù)的嵌套,但是問題不是guard本身,而是它的使用。Guard語句會促使你寫出能做好幾件事、有多層抽象層次的大函數(shù)。只要保證所寫的函數(shù)小而明確,你根本無需guard語句。

自從guard語句在Swift中出現(xiàn)以來,就引起了大量的討論。講真,guard確實簡化了代碼,且提高了代碼的可讀性,但它就是靈丹妙藥了嗎?

小函數(shù)

關于函數(shù)的大小,人們也討論了很多。很明顯,函數(shù)體應該是短小的,而且是越短越好。沒有人想去讀、理解或者重構大函數(shù)。但是,函數(shù)應該多大才是正確的呢?

函數(shù)的首要準則是--短。次要準則是--更短。 ---羅伯特`C`馬丁

更具體點說,馬丁認為函數(shù)的長度應該小于六行,絕對不能大于十行。

規(guī)則雖簡,療效顯著,你可以看到代碼立刻就變得易懂多了。以前,你需要記住一個有著30行代碼,若干縮進層次,若干中間變量的函數(shù)。而現(xiàn)在只需要記住十個名字一目了然的函數(shù)。

單一職責

單一職責這件事也被說了很久。這條規(guī)則不僅適用于對象,也同樣適用于函數(shù)。很顯然,每一個函數(shù)應該只做一件事情,但是人們一次兩次地違反此規(guī)則,似乎大部分是因為函數(shù)的大小。如果將一個30行的函數(shù)重構為十個3行的函數(shù),那么在函數(shù)層次自然而然地遵循單一職責規(guī)則了。

單層抽象

人們對函數(shù)的單層抽象討論得并不多.它是一個有助于寫出單一職責函數(shù)的工具。

什么是單層抽象? 簡單地說,就是高抽象層次的代碼,例如控制進程的代碼中不應該混雜著小的細節(jié),例如變量自增或者布爾值檢驗。舉個栗子。

下面例子出自The Swift Programming Language book。

  1. struct Item { 
  2.     var price: Int 
  3.     var count: Int 
  4.   
  5. enum VendingMachineError: ErrorType { 
  6.     case InvalidSelection 
  7.     case InsufficientFunds(coinsNeeded: Int) 
  8.     case OutOfStock 
  9.   
  10. class VendingMachine { 
  11.     var inventory = [ 
  12.         "Candy Bar": Item(price: 12, count: 7), 
  13.         "Chips": Item(price: 10, count: 4), 
  14.         "Pretzels": Item(price: 7, count: 11
  15.     ] 
  16.   
  17.     var coinsDeposited = 0 
  18.   
  19.     func dispense(snack: String) { 
  20.         print("Dispensing \(snack)"
  21.     } 
  22.   
  23.     func vend(itemNamed name: String) throws { 
  24.         guard var item = inventory[name] else { 
  25.             throw VendingMachineError.InvalidSelection 
  26.         } 
  27.   
  28.         guard item.count > 0 else { 
  29.             throw VendingMachineError.OutOfStock 
  30.         } 
  31.   
  32.         guard item.price <= coinsDeposited else { 
  33.             throw VendingMachineError.InsufficientFunds(coinsNeeded: item.price - coinsDeposited) 
  34.         } 
  35.   
  36.         coinsDeposited -= item.price 
  37.         --item.count 
  38.         inventory[name] = item 
  39.         dispense(name) 
  40.     } 

當然,vend(itemNamed:)只是使用gaurd語句的一個例子,不過你經(jīng)常能在生產(chǎn)代碼中看到相似的函數(shù)。這個函數(shù)就出現(xiàn)了三個上面說到的問題:

  1. 它相當?shù)拈L,有十六行,很多部分由空行隔開。
  2. 它做了好幾件事:通過名稱拿到一件商品,驗證參數(shù)合法性,然后是出售商品的邏輯。
  3. 它有好幾個抽象層次。最高層的出售過程被隱藏在了更細層次的細節(jié)當中了,例如布爾值驗證,特殊常量的使用,數(shù)學運算等等。

這個函數(shù)重構后是什么樣呢?

  1. func vend(itemNamed name: String) throws { 
  2.     let item = try validatedItemNamed(name) 
  3.     reduceDepositedCoinsBy(item.price) 
  4.     removeFromInventory(item, name: name) 
  5.     dispense(name) 
  6.   
  7. private func validatedItemNamed(name: String) throws -> Item { 
  8.     let item = try itemNamed(name) 
  9.     try validate(item) 
  10.     return item 
  11.   
  12. private func reduceDepositedCoinsBy(price: Int) { 
  13.     coinsDeposited -= price 
  14.   
  15. private func removeFromInventory(var item: Item, name: String) { 
  16.     --item.count 
  17.     inventory[name] = item 
  18.   
  19. private func itemNamed(name: String) throws -> Item { 
  20.     if let item = inventory[name] { 
  21.         return item 
  22.     } else { 
  23.         throw VendingMachineError.InvalidSelection 
  24.     } 
  25.   
  26. private func validate(item: Item) throws { 
  27.     try validateCount(item.count) 
  28.     try validatePrice(item.price) 
  29.   
  30. private func validateCount(count: Int) throws { 
  31.     if count == 0 { 
  32.         throw VendingMachineError.OutOfStock 
  33.     } 
  34.   
  35. private func validatePrice(price: Int) throws { 
  36.     if coinsDeposited < price { 
  37.         throw VendingMachineError.InsufficientFunds(coinsNeeded: price - coinsDeposited) 
  38.     } 

雖然總行數(shù)變多了,但你應該記住,代碼行數(shù)并不是它的最終目的。

重構后的代碼相對于舊版的多了幾個優(yōu)點:

  1. 核心的出售函數(shù)變小了,而且只包含了出售一個商品的步驟的高層邏輯.如果讀者對細節(jié)不感興趣,通過快速地看這個高層函數(shù),她就明白了售賣過程。
  2. 這些函數(shù)更好地遵守了單一職責原則.其中有一些還可以進一步分解地更小,不過即使是當前的形式,它們都更易讀易懂.它們將老的一大串的代碼分解成了更小的,一目了然的代碼塊。
  3. 每個函數(shù)只負責單一層次邏輯的抽象。讀者可以根據(jù)需要在不同層次間移動。那出售的過程是什么樣的呢?根據(jù)名稱確定商品是否有效,然后減少顧客的余額,再將商品從存貨清單中移除,最后顯示此商品已賣出?怎么知道商品是否有效呢?通過檢查數(shù)量和價格,那怎么知道確切的數(shù)量呢?通過和0做比較。如果讀者對細節(jié)毫無興趣,他完全可以忽略這部分內(nèi)容。

結論

Guard語句很便于用來減少結構體和函數(shù)的嵌套,但是問題不是guard本身,而是它的使用。Guard語句會促使你寫出能做好幾件事、有多層抽象層次的大函數(shù)。只要保證所寫的函數(shù)小而明確,你根本無需guard語句。

相關閱讀

責任編輯:倪明 來源: cocoachina
相關推薦

2022-12-26 00:25:06

2018-06-08 15:27:59

云計算企業(yè)存儲

2022-05-16 09:27:37

UbuntuUbuntu LTS

2024-03-01 19:47:27

SQL數(shù)據(jù)庫

2023-02-10 10:14:59

普通索引唯一索引

2013-07-29 14:50:43

API

2022-09-09 08:48:13

ITCIO流程

2022-01-23 13:51:30

Arch LinuxLinux

2020-06-05 14:09:42

Kubernetes容器應用程序

2018-07-30 08:20:39

編程語言Python集合

2015-10-20 15:59:57

注釋代碼程序

2015-10-26 09:38:52

避免注釋代碼

2019-01-10 13:17:15

微服務容器微服務架構

2024-03-25 10:00:00

C++編程else

2012-09-20 15:45:09

2020-07-10 13:59:52

Kaggle代碼數(shù)據(jù)

2022-01-03 08:06:15

函數(shù)Go數(shù)據(jù)

2020-06-21 21:25:14

物聯(lián)網(wǎng)WiFiIOT

2018-07-09 14:05:16

編程語言PythonPipenv

2021-05-08 14:00:58

FedoraLinux
點贊
收藏

51CTO技術棧公眾號