讓我們試着去理解爲什麼DRY是很重要的,然後我們就可以明白的地方打破規則是合理的:
DRY應該用來避免在兩段代碼在概念上做一些同樣的工作的情況,所以無論何時您在一個地方更改代碼,您都必須在其他地方更改代碼。如果相同的邏輯在兩個不同的地方,那麼你必須始終記住要在兩個地方改變邏輯,這很容易出錯。這可以適用於任何規模。它可以是被複制的整個應用程序,也可以是單個常量值。也可能根本沒有任何重複的代碼,它可能只是一個重複的原則。你必須問:「如果我要在一個地方做出改變,我是否需要在其他地方做出相應的改變?」。如果答案是「是」,那麼代碼違反了DRY。
試想一下,你有這樣的線在你的程序:
cost = price + price*0.10 // account for sales tax
在你的程序
和其他地方,你有類似的一行:
x = base_price*1.1; // account for sales tax
如果銷售稅的變化,你將需要改變這兩條線。這裏幾乎沒有重複代碼,但事實是,如果您在一個地方進行更改,則需要在另一個地方進行更改,這會導致代碼不幹。更重要的是,你可能很難意識到你必須在兩個地方做出改變。也許你的單元測試會抓住它,但也許不是,所以擺脫重複是很重要的。也許你會因素的營業稅變成一個獨立的恆定值,它可以在多個地方使用:
cost = price + price*sales_tax;
x = base_price*(1.0+sales_tax);
或可能創建一個函數來抽象甚至更多:
cost = costWithTax(price);
x = costWithTax(base_price);
無論哪種方式,這很可能是值得的麻煩。
或者,你可能有一些代碼看起來非常相似,但沒有違反DRY:
x = base_price * 1.1; // add 10% markup for premium service
如果你的方式來改變銷售稅的計算,你不會想要改變該行的代碼,所以它實際上並不重複任何邏輯。
也有不得不在多個地方進行相同更改的情況。例如,您可能有這樣的代碼:
a0 = f(0);
a1 = f(1);
此代碼在幾個方面不是乾的。例如,如果您要更改功能f
的名稱,則必須更改兩個位置。你也許可以通過創建一個小循環並將a
變成一個數組來讓代碼更幹。但是,這種特殊的重複並不是什麼大問題。首先,這兩個變化非常接近,所以在不改變另一個的情況下意外改變它是不太可能的。其次,如果你使用的是編譯語言,那麼編譯器很可能會發現問題。如果你不是編譯語言,那麼希望你的單元測試能夠抓住它。
有很多很好的理由讓你的代碼幹,但也有很多不好的理由。
這可能更適合程序員.se –