簡體   English   中英

什么放在IF塊中以及放入ELSE塊中的內容?

[英]What to put in the IF block and what to put in the ELSE block?

這是一個次要的樣式問題,但是您添加到代碼中的每一點可讀性都很重要。

所以,如果你有:

if (condition) then
{
   // do stuff
}
else
{
   // do other stuff
}

你如何決定它是否更好,或者像這樣:

   if (!condition) then
   {
     // do other stuff
   {
   else
   {
     // do stuff
   }

我的啟發式是:

  1. 保持病情積極(閱讀時心理計算較少)
  2. 將最常見的路徑放入第一個塊

我更喜歡把最常見的路徑放在第一位,而且我堅信減少嵌套,所以我會盡可能地打破,繼續或返回,而不是精益求精。 我通常更傾向於測試正面條件,或者將[和名稱]負面條件反轉為正面。

if (condition)
    return;

DoSomething();

我發現通過大幅減少else的使用,我的代碼更具可讀性和可維護性,當我必須使用else時,它幾乎總是一個更好的候選者,用於更結構化的switch語句。

兩個(矛盾的)教科書引用:

將if / else的最短子句置於頂部

--Allen Holub,“足夠的繩索射擊自己的腳”,第52頁

將正常情況放在if之后而不是在else之后

--Steve McConnell,“Code Complete,2nd ed。”,第356頁

我更喜歡第一個。 條件應該盡可能簡單,它應該是相當明顯的,更簡單的條件和條件

這取決於你的流量。 對於許多函數,我將使用前提條件:

bool MyFunc(variable) {
    if (variable != something_i_want)
        return false;

    // a large block of code
    // ...
    return true;
}

如果我需要一些事情每一種情況下,我將使用一個if (positive_clause) {} else {}格式。

如果代碼是檢查錯誤條件,我更喜歡先放置代碼,然后將“成功”代碼放在第二位; 從概念上講,這將函數調用及其錯誤檢查代碼保持在一起,這對我來說是有意義的,因為它們是相關的。 例如:

  if (!some_function_that_could_fail())
  {
     // Error handling code
  }
  else
  {
     // Success code
  }

我同意Oli在可能的情況下使用積極的if條款。

請永遠不要這樣做:

if (somePositiveCondition)
else {
    //stuff
}

我曾經在我工作的一個地方經常看到這個,並常常想知道其中一個程序員是否不理解如何不工作......

當我在查看數據驗證時,我會嘗試將我的條件設為“白名單” - 也就是說,我會測試我接受的內容:

if DataIsGood() then
   DoMyNormalStuff
else
   TakeEvasiveAction

而不是相反,往往退化為:

if SomeErrorTest then
  TakeSomeEvasiveAction
else if SomeOtherErrorCondition then
  CorrectMoreStupidUserProblems
else if YetAnotherErrorThatNoOneThoughtOf then
  DoMoreErrorHandling
else
  DoMyNormalStuff

我知道這不是你正在尋找的,但是......很多開發人員使用“保護條款”,即一個消極的“if”語句,盡快打破方法。 那時,真的沒有“別的”。

例:

if (blah == false)
{
    return; // perhaps with a message
}

// do rest of code here...

有一些硬核c / c ++ /匯編人員會告訴你,你正在摧毀你的CPU! (在許多情況下,處理器偏愛“真實”語句並試圖“預取”下一件事......所以理論上任何“假”條件都會刷新管道並且會慢幾微秒)。

在我看來,我們正處於“更好”(更易理解)的代碼勝過超過幾秒的CPU時間。

我認為對於單個變量,not運算符非常簡單,命名問題開始變得更加相關。

永遠不要將變量not_X命名,如果需要使用同義詞並找到相反的變量。 我見過很多糟糕的代碼

if (not_dead) {
} else {
}

而不是顯而易見的

if (alive) {
} else {
}

然后你可以理智地使用(非常易讀,無需反轉代碼塊)

if (!alive) {
} else {
}

如果我們談論更多變量,我認為最好的規則是簡化條件。 過了一段時間項目往往會得到如下條件:

if (dead || (!dead && sleeping)) {
} else {
}

這轉化為

if (dead || sleeping) {
} else {
}

始終注意什么樣的條件以及如何簡化它們。

軟件是知識捕獲。 你正在編碼某人對如何做某事的知識。

該軟件應該適合問題的“自然”。 如有疑問,請詢問其他人並查看人們的實際說法和行為。

那些“普通”案件無所作為的情況怎么樣? 然后怎樣呢

if( common ) {
    // pass
}
else {
    // great big block of exception-handling folderol
}

或者你這樣做?

if( ! common ) {
    // great big block of except-handling folderol
}

“永遠積極”的規則並不是你想要的。 您想要查看更像以下規則。

  1. 永遠自然 - 它應該像英語(或任何組織中的通用語言)。
  2. 在可能的情況下,首先是常見案例
  3. 盡可能使用正邏輯; 負邏輯可用於通常以這種方式表達的地方,或者常見情況是什么都不做的地方。

如果兩條路徑中的一條非常短(1到10行左右)而另一條路徑更長,我遵循這里提到Holub規則並將更短的代碼放在if中。 這使得在查看代碼時更容易在一個屏幕上看到if / else流。

如果那是不可能的,那么我構造使條件盡可能簡單。

對我來說,這取決於條件,例如:

if (!PreserveData.Checked)
{  resetfields();}

我傾向於用我想要的邏輯與自己交談,並將其編碼為我腦子里的小聲音。

您通常可以在不切換if / else塊的情況下使條件為正。

更改

   if (!widget.enabled()) {
     // more common 
   } else {
     // less common 
   }

   if (widget.disabled()) {
     // more common 
   } else {
     // less common
   }

英特爾奔騰分支預測預取“if”情況的指令。 如果它跟在“else”分支之后:它具有刷新指令管道,導致停頓。

如果你非常關心表現:把最可能的結果放在'if'條款中。

我個人把它寫成

if (expected)
{
   //expected path
}
else
{
   //fallback other odd case
} 

如果您同時擁有真假條件,那么我會選擇積極的條件 - 這可以減少混淆,一般來說,我相信會讓您的代碼更容易閱讀。

另一方面,如果您使用的是Perl之類的語言,特別是如果您的錯誤條件是錯誤條件或最常見的條件,您可以使用'unless'結構,它執行代碼塊,除非條件是真的(即if的反面):

unless ($foo) {
    $bar;
}

首先,讓我們暫時擱置最好避免首先使用“其他”的情況(我希望每個人都同意這種情況確實存在並且確定這種情況可能應該是一個單獨的主題)。

所以,我們假設必須有一個“else”子句。

我認為可讀性/可理解性至少強加了三個關鍵要求或規則,不幸的是它們經常相互競爭:

  1. 第一個塊(“if”塊)越短,就越容易掌握整個“if-else”結構。 當“if”塊足夠長時,很容易忽略“else”塊的存在。

  2. 當“if”和“else”路徑在邏輯上不對稱時(例如“正常處理”與“錯誤處理”),在獨立的 “if-else”構造中,哪個路徑首先是哪個路徑並且哪個路徑是第二個並不重要。 但是,當有多個 “if-else”構造彼此接近時(包括嵌套),並且當所有那些“if-else”構造具有相同類型的不對稱時 - 那就是排列那些非對稱路徑非常重要的時候一致。

    同樣,對於所有人來說,它可以是“如果...正常路徑......其他......異常路徑”,或者“如果...異常路徑......其他......正常路徑”,但它不應該是這兩種變體的混合體。

    在所有其他條件相同的情況下,將正常路徑放在第一位對於大多數人來說可能更自然(我認為它更多地是關於心理學而不是美學:-)。

  3. 以否定開頭的表達式通常比不具有否定性的表達式更不易讀/可理解。

因此,我們有這三個相互競爭的要求/規則,真正的問題是:哪一個比其他更重要。 對於Allen Holub來說,規則#1可能是最重要的規則。 史蒂夫麥康奈爾 - 這是規則#2。 但我認為你不能真正選擇其中一條作為單一的准則。

我打賭你已經在這里猜到了我的個人優先事項(從我訂購上述規則的方式:-)。

我的理由很簡單:

  • 規則#1是無條件的,不可能規避。 如果其中一個塊太長而無法在屏幕上運行 - 它必須成為“其他”塊。 (不,機械地創建函數/方法只是為了減少“if”或“else”塊中的行數並不是一個好主意!我假設每個塊已經具有邏輯上合理的最小行數。 )

  • 規則#2涉及很多條件:多個“if-else”構造,都具有相同類型的不對稱性等等。因此它在許多情況下不適用。

    此外,我經常觀察到以下有趣的現象:當規則#2適用時以及正確使用時,它實際上與規則#1不沖突! 例如,每當我有一堆“if-else”語句具有“正常與異常”不對稱時,所有“異常”路徑都比“正常”路徑短(反之亦然)。 我無法解釋這種現象,但我認為這只是良好代碼組織的標志。 換句話說,每當我看到規則#1和#2發生沖突的情況時,我就開始尋找“代碼味道”,而且我經常會找到一些; 重構后 - tada! 規則#1和規則#2之間沒有更痛苦的選擇,:-)

  • 最后,規則#3具有最小的范圍,因此是最不重要的。

    此外,正如其他同事在這里所說的那樣,通常很容易“欺騙”這個規則(例如,寫“if(disabled),,,”而不是“if(!enabled)...”)。

我希望有人能對這一作品有所了解......

我通常在開始時把積極的結果(所以方法)放在一起,所以:

if(condition)
{
doSomething();
}
else
{
System.out.println("condition not true")
}

但是如果要使用的方法的條件必須為false,我會這樣做:

if(!condition)
{
doSomething();
}
else
{
System.out.println("condition true");
}

作為一般規則,如果一個明顯大於另一個,我將較大的一個作為if塊。

  1. 把共同的道路放在首位
  2. 把負面的cheking變成正面的( !full == empty

如果您必須有多個退出點,請先將它們放在一起並清除它們:

if TerminatingCondition1 then
  Exit
if TerminatingCondition2 then
  Exit

現在我們可以用通常的東西進步:

if NormalThing then
  DoNormalThing
else
  DoAbnormalThing

我總是最有可能保持第一。

在Perl中,我有一個額外的控制結構來幫助解決這個問題。 if的反轉。

unless (alive) {
     go_to_heaven;
} else {
     say "MEDIC";
}

你應該始終把最可能的案例放在第一位。 除了更具可讀性之外,它更快。 這也適用於switch語句。

關於我如何設置if語句,我很可怕。 基本上,我根據我正在尋找的東西來設置它,這導致一切都不同。

if(userinput = null){
explodeViolently();
} else {
實際做的東西;
}

或者類似的東西

if(1 + 1 = 2){
做東西;
} else {
explodeViolently();
}

if / else語句的哪一部分實際上對我有用,這是我的一個壞習慣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM