Re: [請益] 很多層迴圈和if 怎麼寫比較好整理
好擔心回文會不會因為不是高手而被拒絕 >"<
不過至少俺有被高手前輩訓練過 (抖)
基本上 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
07/16 19:05, 1F
推
07/16 19:05, , 2F
07/16 19:05, 2F
→
07/16 19:06, , 3F
07/16 19:06, 3F
→
07/16 19:08, , 4F
07/16 19:08, 4F
→
07/16 19:08, , 5F
07/16 19:08, 5F
→
07/16 19:09, , 6F
07/16 19:09, 6F
推
07/16 19:09, , 7F
07/16 19:09, 7F
→
07/16 19:10, , 8F
07/16 19:10, 8F
→
07/16 19:11, , 9F
07/16 19:11, 9F
推
07/16 20:00, , 10F
07/16 20:00, 10F
→
07/16 20:40, , 11F
07/16 20:40, 11F
→
07/16 20:42, , 12F
07/16 20:42, 12F
推
07/16 21:28, , 13F
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
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
07/16 21:34, 19F
→
07/16 21:36, , 20F
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
07/17 02:45, 24F
→
07/17 02:46, , 25F
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
07/17 11:45, 28F
→
07/17 14:55, , 29F
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
討論串 (同標題文章)
以下文章回應了本文 (最舊先):
完整討論串 (本文為第 10 之 16 篇):