2012-12-18 42 views
7

我前幾天正在尋找一個Ruby代碼質量工具,並且碰到了看起來很有意思的pelusa寶石。它檢查的一件事是給定的Ruby文件中使用的else語句的數量。Ruby爲什麼不鼓勵其他語句?

我的問題是,爲什麼這些不好?我明白if/else語句通常會增加很多複雜性(而且我的目標是降低代碼複雜度),但如何在不使用else的情況下編寫檢查兩個案例的方法?

總括來說,我有兩個問題:

1)難道還有比減少了代碼的複雜性,可能避免else語句以外的原因?

2)以下是我正在使用的應用程序中的示例方法,它使用else語句。你會怎樣寫這個沒有?我能想到的唯一選擇是三元語句,但這裏有足夠的邏輯,我認爲三元語句實際上會更復雜,更難以閱讀。

def deliver_email_verification_instructions 
    if Rails.env.test? || Rails.env.development? 
    deliver_email_verification_instructions! 
    else 
    delay.deliver_email_verification_instructions! 
    end 
end 

如果你寫了這個帶有三元運算符,這將是:

def deliver_email_verification_instructions 
    (Rails.env.test? || Rails.env.development?) ? deliver_email_verification_instructions! : delay.deliver_email_verification_instructions! 
end 

是嗎?如果是這樣,是不是更難以閱讀? else聲明是否有助於解決這個問題?有沒有另一種更好的方式來寫這個,我沒有想到?

我想我在這裏尋找文體考慮因素。

+1

好在'else'上寫下代碼的氣味:http://solnic.eu/2012/04/11/get-rid-of-that-c​​ode-smell-control-couple.html – michaelmichael

+0

這就是相當不錯,還有一些我在尋找的東西(雖然在我的腦海裏有點偏)。小心張貼作爲答案,詳細說明,併爲額外的業力點,重構我的例子或使用你自己的例子來說明?或者你覺得這個帖子應該作爲一個答案? – nickcoxdotme

+0

過度使用是不好的,因爲它是一個堅決要求避免。有一段時間和一個地方,並且用正確書寫的代碼,偶爾它是正確的解決方案。它可能會混淆意大利麪條代碼,所以應避免編寫代碼錯誤的代碼,其餘部分應該自行處理。 –

回答

6

讓我首先要說,確實沒有什麼錯你的代碼,通常你應該知道,任何一個代碼質量工具告訴你可能是完全荒謬的,因爲它缺乏評估你實際在做什麼的背景。

但是回到代碼。如果有一類有隻有一個方法的片段

if Rails.env.test? || Rails.env.development? 
    # Do stuff 
else 
    # Do other stuff 
end 

發生的位置,這將是完全沒問題(有總是不同的方法給定的事情,但你不必擔心,即使程序員會恨你不與他們爭論它:D)。

現在出現棘手的部分。人們很懶,因此像上面這樣的代碼片段是複製/粘貼代碼的簡單目標(這就是爲什麼人們會認爲應該首先避免它們的原因,因爲如果稍後擴展一個類,則更有可能只是複製和粘貼東西,而不是實際重構它)。

讓我們以您的代碼片段爲例。我基本上提出了和@Mik_Die一樣的東西,但是他的例子同樣容易被複制/粘貼爲你的。因此,就應該做的(IMO)是這樣的:

class Foo 
    def initialize 
    @target = (Rails.env.test? || Rails.env.development?) ? self : delay 
    end 

    def deliver_email_verification_instructions 
    @target.deliver_email_verification_instructions! 
    end 
end 

這可能並不適用於您的應用程序原樣,但我希望你的想法,那就是:不要重複自己。永遠。每當你重複自己的時候,你不僅會讓你的代碼不易維護,而且因此在未來更容易出錯,因爲你複製和粘貼的任何一個或者甚至99/100次事件都可能被改變,但是剩下的一個發生是什麼原因導致到底:)


,我已經忘記了被@RayToal(感謝:),這帶來了一個點的@disasterOfEpicProportions,如果/ else結構中經常使用與布爾輸入參數結合,產生如下結構(我必須維護一個項目的實際代碼):

class String 
    def uc(only_first=false) 
    if only_first 
     capitalize 
    else 
     upcase 
    end 
    end 
end 

讓我們忽略這裏明顯的方法命名和猴子修補問題,並重點關注if/else結構,該結構用於根據參數only_firstuc方法提供兩種不同的行爲。這樣的代碼違反了單一責任原則,因爲你的方法是做了不止一件事,這就是爲什麼你應該先寫兩種方法。

+2

這是最好的重構OP代碼的恕我直言。 'else'部分的陳述通常是不被接受的,因爲當你看到它們時,你的封閉方法**正在做超過一件事情**,這違反了SRP(儘管我絕不會認爲遵循這100%時間)。基於環境的目標初始化並不只是一件事;它正在計算正確的目標。然後交付方式很好。 +1 –

+0

@RayToal感謝您的加入:)更新了我的答案。 – fresskoma

2
def deliver_email_verification_instructions 
    subj = (Rails.env.test? || Rails.env.development?) ? self : delay 
    subj.deliver_email_verification_instructions! 
end 
+1

對我寫的方法進行了重構,我很欣賞。你可以添加任何上下文來解決我的第一個問題,你爲什麼選擇這種風格,以及這種方法客觀地用'else'語句提供了什麼?那,我可以標記正確。 – nickcoxdotme

相關問題