成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

iOS代碼里邏輯分支的處理

移動開發
我們大致上可以將代碼按執行方式分解為三類:Sequence,Selection,Iteration。Selection即為條件模式,說的簡單一點就是平常我們寫代碼時所用的 if else,switch。這是我們代碼的邏輯產生分支的地方,也是這篇文章的主題。

我們大致上可以將代碼按執行方式分解為三類:Sequence,Selection,Iteration。

Sequence

Sequence即為按前后順序依次執行,從第一行按序一直執行到第 n 行。比如:

 

  1. NSString *name = @"default"; //definition 
  2. name = @"peak"; //assignment 
  3. NSLog(@"name is %@"name); //send message 

3 行代碼包含 Definition,Assignment,Send Message 不同類型的指令,但他們被運行的時候作為一個整體是依照 Sequence 模式依次執行。

Selection

Selection即為條件模式,說的簡單一點就是平常我們寫代碼時所用的 if else,switch。這是我們代碼的邏輯產生分支的地方,也是這篇文章的主題。記得之前讀到過一句話,大意說是當我們想要重構代碼的時候,if else 總會是個好的著手點,或者說 if else 是我們代碼最容易出錯的地方。

按我個人理解,邏輯分支之所以容易出錯在于兩點。

其一是所依賴的條件不確定,或者不穩定。比如:

 

  1. if ([users objectAtIndex:0] == currentUser) { 
  2.     ... 

看似簡單的條件代碼 [users objectAtIndex:0] == currentUser 會在各種情況下出錯,比如 users 當中沒有任何元素會發生越界,比如 users 已被釋放導致內存訪問異常,同樣的情況也會發生在 currentUser 身上,一個條件語句所包含的狀態越多,出錯的可能性也就越大。

其二是遺漏某個條件分支。比如:

 

  1. typedef enum : NSUInteger { 
  2.   EUserLoginStatusLoggedIn, 
  3.   EUserLoginStatusLoggedOut, 
  4.   EUserLoginStatusKickedOut, 
  5. } EUserLoginStatus; 
  6.  
  7. EUserLoginStatus userStatus; 
  8. ... 
  9. if (userStatus == EUserLoginStatusLoggedIn) { 
  10.     ... 
  11. else if (userStatus == EUserLoginStatusLoggedOut) { 
  12.     ... 

比如上面代碼忘記處理 EUserLoginStatusKickedOut, 當然如果代碼是同一個人所寫,一般不會遺漏。但如果代碼交由后面的人維護,EUserLoginStatus 新增了 status,而 if else 的處理有散落的工程的各個角落,忘記處理新的分支就很容易發生了。

Iteration

Iteration發生在我們需要循環或多次處理某些數據的時候,比如我們常見的 while,for 循環。iteration 有時也會依賴某些數據或者某些條件語句,在處理的時候也會存在 Selection 語句容易遇到的狀態不穩定問題。

Sequence,Selection,Iteration 可以概括我們所寫的全部代碼。其中 Selection 是最容易出錯的地方,也是我個人平時 review 代碼的重點。

Selection 第一個所依賴狀態不穩定的問題,多注意數據或者對象的生命周期,不可變性,多線程安全即可。

分支遺留

第二個分支遺漏的問題,出現的概率比大多數人想象的要高,尤其是隨著項目代碼的膨脹,工程師的更替。所以從代碼層面做一些限制可以有效的避免這一問題出現。

一種常見的做法是針對多分支的邏輯處理,盡量使用 switch 而非 if else,比如工程師 A 先寫了如下代碼:

 

  1. // File A 
  2. typedef enum : NSUInteger { 
  3.   EUserLoginStatusLoggedIn, 
  4.   EUserLoginStatusLoggedOut, 
  5. } EUserLoginStatus; 
  6.  
  7. // File B 
  8. EUserLoginStatus userStatus; 
  9. ... 
  10. switch (userStatus) { 
  11.   case EUserLoginStatusLoggedIn: 
  12.   { 
  13.  
  14.   } 
  15.   break; 
  16.   case EUserLoginStatusLoggedOut: 
  17.   { 
  18.  
  19.   } 
  20.   break; 

之后工程師 B 在 File A 中又加了一種 enum 值 EUserLoginStatusKickedOut,那么此時編譯器會以警告的方式,幫助我們檢查遺漏的類型,這里的關鍵在于寫 switch 時不要寫 default case,否則編譯器會認為新增的 enum 值有默認的處理邏輯了。

如果沒寫 default case,Xcode 會給出如下警告:

iOS代碼里邏輯分支的處理

這幾乎可以看做是 iOS 下處理邏輯分支的 best practice 了。

Match

除此之外,我們還有另一種更“激進”的方式來避免這類問題,match pattern。過去一年看到越來越多的代碼采用這種方式。使用 match pattern 代碼如下:

 

  1. // File A 
  2. typedef enum : NSUInteger { 
  3.   EUserLoginStatusLoggedIn, 
  4.   EUserLoginStatusLoggedOut, 
  5. } EUserLoginStatus; 
  6.  
  7. // File B 
  8. typedef void (^UserLoggedInBlock)(void); 
  9. typedef void (^UserLoggedoutBlock)(void); 
  10.  
  11. - (void)someMatchUserStatusLogic 
  12.   [self matchUserStatusLoggedIn:^{ 
  13.     //... 
  14.   } loggedOut:^{ 
  15.     //... 
  16.   }]; 
  17.  
  18. - (void)matchUserStatusLoggedIn:(UserLoggedInBlock)loggedInBlock loggedOut:(UserLoggedoutBlock)loggedoutBlock 
  19.   EUserLoginStatus userStatus = EUserLoginStatusLoggedIn; 
  20.   switch (userStatus) { 
  21.     case EUserLoginStatusLoggedIn: 
  22.     { 
  23.       loggedInBlock(); 
  24.     } 
  25.       break; 
  26.     case EUserLoginStatusLoggedOut: 
  27.     { 
  28.       loggedoutBlock(); 
  29.     } 
  30.       break; 
  31.   } 

這種方式在 switch 的基礎之上再封裝了一層函數調用,將分支的處理寫進函數簽名里面,好處很明顯,當你新增 EUserLoginStatusKickedOut case 的時候,只要更改 matchUserStatusLoggedIn 函數,新增一個參數:

 

  1. // File B 
  2. typedef void (^UserLoggedInBlock)(void); 
  3. typedef void (^UserLoggedoutBlock)(void); 
  4. typedef void (^UserKickedoutBlock)(void); 
  5.  
  6. - (void)matchUserStatusLoggedIn:(UserLoggedInBlock)loggedInBlock loggedOut:(UserLoggedoutBlock)loggedoutBlock kickedOut:(UserKickedoutBlock)kickedoutBlock; 

那么所有被影響的代碼只要一編譯都會報錯,改起來相當方便,相比較于 warning,compile error 顯然更能借助編譯器來避免我們代碼上的分支遺漏。即使代碼被第二個人接手,改動起來也一目了然。

這種寫法如果不明白目的所在,第一眼看上去顯得笨重且多余。我個人感覺,有時候如果多寫的代碼模式固定且簡單容易理解,同時這種多出來的代碼可以讓邏輯更健壯,那么這些多余的代碼就并不多余。尤其是當項目代碼量過于龐大且參與人數眾多的情況下,優質的代碼書寫避免代碼產生意料之外的降級。

責任編輯:未麗燕 來源: MrPeak技術分享
相關推薦

2017-07-25 09:55:10

iOS橫豎屏旋轉

2015-05-20 10:11:11

微軟漢拿山Office 365

2011-03-30 10:50:55

GitLinux 版本控制

2019-08-15 10:25:02

代碼開發工具

2010-08-25 10:27:35

代碼

2010-08-25 11:29:07

代碼

2012-01-10 09:32:12

iOS 5.1設備四核處理器

2011-11-03 15:44:10

程序員

2010-07-19 10:55:07

SQL Server

2024-08-20 08:19:43

2017-11-16 15:21:06

代碼taste方法

2022-02-15 08:38:04

錯誤邏輯異常編程程序

2021-05-13 10:40:16

ThreadLocal代碼Java

2025-04-28 10:13:03

JavaScript數組代碼

2022-05-25 16:51:41

Git 分支重命名開發者

2021-05-31 18:56:56

代碼編碼開發

2011-08-08 13:26:48

iOS開發 Twitter

2021-03-25 07:30:24

代碼開發數據

2013-03-28 11:00:40

服務器數據虛擬化

2013-06-08 10:40:49

代碼規則命名規則代碼命名
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品久久久久久久 | 国产精品一区二区欧美黑人喷潮水 | 日本一区二区三区免费观看 | 精品电影 | 91久久精品国产91久久性色tv | 亚洲播放| 亚洲精品无 | 亚洲国产精品久久久久 | 欧美日韩中文字幕在线 | 久久精品国产一区 | 日韩精品视频在线免费观看 | 91av在线免费 | 国产一区二区中文字幕 | 人妖一区 | 亚洲精品乱码久久久久久久久久 | 日批免费观看 | 精品无码久久久久国产 | 欧美成人在线网站 | 91视频国产一区 | 国产午夜精品视频 | 夜夜爽99久久国产综合精品女不卡 | www.日日夜夜 | 99久久精品国产麻豆演员表 | 国产乱肥老妇国产一区二 | 美女黄色在线观看 | 天天躁日日躁aaaa视频 | 亚洲不卡| 最新国产精品精品视频 | 成人免费观看男女羞羞视频 | 日本高清精品 | 欧美在线小视频 | 美女视频一区二区三区 | 欧美视频 | 免费观看黄 | 91影库| 日本高清视频在线播放 | 一级黄色片毛片 | 999精品在线观看 | 日韩成人 | 九一精品 | 午夜久久久久久久久久一区二区 |