Re: [請益] 很多層迴圈和if 怎麼寫比較好整理

看板Soft_Job作者 (null)時間13年前 (2011/07/16 18:56), 編輯推噓13(13019)
留言32則, 14人參與, 最新討論串10/16 (看更多)
好擔心回文會不會因為不是高手而被拒絕 >"< 不過至少俺有被高手前輩訓練過 (抖) 基本上 if/else 多層是比較困擾的, 因為它實在是不好用『眼睛』輕易的追蹤。 一來這是件傷眼的事, 另外它會考驗寫code到腦袋混沌時的邏輯判斷。 某大濕說過: 好的 code 看完它能開始討論它想達到什麼目的! 不好的 code 看完它只能開始討論 code 在寫些什麼。 寫出來的程式易不易懂與『鋪陳』的方式有關。 而 if/else 邏輯判斷的為了閱讀舒適感而重新安排是可以重構階段再做。 接下來在正式進入 if/else 代換的經驗之前, 實作者可以思考的不同方式是: 是不是有其它的實作方式,能避免這些條件判斷呢? 像使用不用的公式、演算法程式碼的複雜度就會有所改變。 有些情況是較易理解,易實的的公式用程式寫起來很囉囌。 而公式沒那麼好算,但幾個式字就能算出來的,可能程式會變少,但不那麼好懂。 一種是花時間在註解程式(因為解法並不漂亮只好苦命地打字), 一種是花時間說明公式的由來。 要把 if/else 排得好看, 容易處理的情況是裝載這些條件判斷的 scope 不會太大。 這樣就可以使用 early break/return 的方式 也就是版友 ronnywang 建議的部分。 void func1() { if(a) { if(b) { if(c) { // do something } } else { // do something } } } 能改寫成: void func1() { if(!a) return ; if(b) { if(c) { // do something } } else { // do something } } 能改寫成: void func1() { if(!a) return ; if(b && c) { // do something } else { // do something } } 能改寫成: void func1() { if(!a) return ; if(b && c) { // do something return ; } // do something } 使用 || 也是差不多的: void func1() { if(a || b) { if(c) { // do something } else { // do something } } } 加個 ! 讓它有『變號的效果』 => || 變成 && void func1() { if(!a && !b) return ; if(c) { // do something } else { // do something } } 又能改成: void func1() { if(!a && !b) return ; if(c) { // do something return ; } // do something } 這簡單的代換、變號技巧是曾經帶領過我的前輩交的, 但他強調這構結的變化,只去去掉了 {} 的層數, 本身的語意遠比這結構的等價交換重要許多。 當我們建立一個 function/method 表示我們替程式加了一個功能, 最好他代表著被呼叫一次精確地達成一個目標(有時沒有明確切割語意它會有多個目標) 而要滿足一個特別的目標的基本結構是: 1. 確認是否有能力執行這個任務 2. 執行任務內容 3. 檢查執行後的狀態是否在控制之中 轉成換 fucntion/method 就是 1. check precondition 2. do something 3. check postcondition 因此我們會養成這樣的寫作習慣: void target() { if(!precondition1) return ; if(!precondition2) return ; if(!precondition ...) return ; // do something // do something // do something if(!postcondition1) throw ... if(!postcondition2) throw ... ... return ; } 如果發現,連 do something 內也有許多 condition 得判斷, 這有可能是: 1. problem space 真的他馬的複雜,接受它的。 2. 這個 function/method 承受太多責任了 思考後,若是 case 2 最好考慮重構。 而重構這項活動指的是整理程式碼,讓它變得好維護。 得提醒自己: 不要成為『去 condition』偏執狂。 該用的時候就大贍寫吧。 這並不是一方面要求大家要針對它重構, 又一方面要求大家容忍它的存在。 重構的目標不是去 condition,而是安排 condition 的位置。 我個人的心得是,將程式進入點安排主要流程的部分減少條件判斷, 將判斷埋在細節實作。 這樣一開始讀主流程的原始碼較不易被許多條件混淆了思緒。 而在實作部分,就能利用 condition 平坦化的小技巧, 讓 {} 不要太多層,愛護您的眼,珍惜您的腦袋 :D -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.231.54.26

07/16 19:05, , 1F
把if (b) {if (c)} 改寫成 if (b && c)時好像有點問題
07/16 19:05, 1F

07/16 19:05, , 2F
07/16 19:05, 2F

07/16 19:06, , 3F
原本b=true,c=false會不做事 但改之後會做b=false的事
07/16 19:06, 3F

07/16 19:08, , 4F
嗯,確實。不過這是單純結構上來換。能不能換要視實際判斷
07/16 19:08, 4F

07/16 19:08, , 5F
感謝 asilzheng 提醒我不夠嚴謹的部分。
07/16 19:08, 5F

07/16 19:09, , 6F
我剛看了一輪竟然沒掃到一樓講的 XD 真是看得太偷懶了
07/16 19:09, 6F

07/16 19:09, , 7F
不過還是推一個 這樣會讓程式好讀很多
07/16 19:09, 7F

07/16 19:10, , 8F
我曾寫過你說的情況的 bug XD
07/16 19:10, 8F

07/16 19:11, , 9F
只是不是因為去 {},是渾然天成地寫了出來 (羞)
07/16 19:11, 9F

07/16 20:00, , 10F
推這篇 :d
07/16 20:00, 10F

07/16 20:40, , 11F
我懷疑過VC++編輯器是不是有BUG 一樓你意思是這樣???
07/16 20:40, 11F

07/16 20:42, , 12F
一樓說的是這兩個判斷在那個範例裡並不是等價
07/16 20:42, 12F

07/16 21:28, , 13F
我比較好奇的是,是condition直鋪後用很多括號好讀,還
07/16 21:28, 13F

07/16 21:28, , 14F
是如這篇所說邏輯變號將行數簡化好讀?
07/16 21:28, 14F

07/16 21:30, , 15F
我是覺得如果頭腦不是時常保持清醒,後者似乎出錯(特別
07/16 21:30, 15F

07/16 21:30, , 16F
是logic error)的機率似乎高些?
07/16 21:30, 16F

07/16 21:32, , 17F
能在腦袋清醒時寫最好,不過一天八小時裡總有不清醒的時候。
07/16 21:32, 17F

07/16 21:34, , 18F
我是覺得八小時保持清醒還可以,但是通常總時間遠遠超過
07/16 21:34, 18F

07/16 21:34, , 19F
八小時...XD
07/16 21:34, 19F

07/16 21:36, , 20F
我能有4小時是清醒的就謝天謝地了(逃)
07/16 21:36, 20F

07/16 21:56, , 21F
推一個, 又學到一項觀念了
07/16 21:56, 21F

07/17 02:25, , 22F
給推
07/17 02:25, 22F

07/17 02:45, , 23F
其實還有另一個問題,不過可能對大多數程式沒差
07/17 02:45, 23F

07/17 02:45, , 24F
就是改寫成 if (b && c) 後,worst case下應該是比
07/17 02:45, 24F

07/17 02:46, , 25F
if (b) {if (c)} 多花一滴滴時間
07/17 02:46, 25F

07/17 02:46, , 26F
在某些需求下這個時間累積起來會很顯著
07/17 02:46, 26F

07/17 04:37, , 27F
看完好像真的獲得一些東西 謝謝~~
07/17 04:37, 27F

07/17 11:45, , 28F
沒繳學費不好意思 XD
07/17 11:45, 28F

07/17 14:55, , 29F
我也是用這招 這招在C C++ Java C#都通吃
07/17 14:55, 29F

07/17 16:41, , 30F
我也常用,只是沒系統化整理,憑洞察跟直覺就改成這樣了
07/17 16:41, 30F

07/17 23:02, , 31F
07/17 23:02, 31F

07/17 23:43, , 32F
有看有推
07/17 23:43, 32F
文章代碼(AID): #1E8Mvs0e (Soft_Job)
討論串 (同標題文章)
以下文章回應了本文 (最舊先):
完整討論串 (本文為第 10 之 16 篇):
文章代碼(AID): #1E8Mvs0e (Soft_Job)