2011-09-05 48 views
15

我的DRYKISS原則迷戀的追隨者,但上週我曾在那裏似乎都相互矛盾的情形:當KISS和DRY碰撞

對於一個應用程序,我在幹什麼,我不得不實施對於次的循環,其執行以下操作:

  1. 迭代過A型
  2. 的列表的元素轉換類型A的元件到類型B,並將它們插入到類型B的列表

下面是一個例子:

for (A a : listOfA) { 
    listOfB.add(BFactory.convertFromAToB(a)); 
} 

中的代碼,我必須這樣做,約4倍,轉換類型(例如, D,E等)到另一個。我可能無法更改要轉換的類型,因爲它們是我們必須在應用程序中使用的第三方類型。

因此,我們有:

for (A a : listOfA) { 
    listOfB.add(BFactory.convertFromAToB(a)); 
} 

for (C a : listOfC) { 
    listOfB.add(DFactory.convertFromCToD(c)); 
} 

... 

所以,爲了不違反乾的,我想出了一個通用的解決方案:

private interface Function<S, T> { 
    T apply(S s); 
} 

public <S, T> void convertAndCopy(List<S> src, List<T> dst, Function<S, T> f) { 
    for (S s : src) { 
     dst.add(f.apply(s)); 
    } 
} 

調用看起來是這樣的:

convertAndCopy(listOfA, listOfB, new Function<A, B>() { 
    A apply(B b) { 
     return CFactory.convertFromBToC(b); 
    } 
}); 

現在,雖然這在DRY方面更好,但我認爲它違反了KISS,因爲此解決方案難以滿足而不是重複的for循環。

那麼,這是幹還是吻?在這種情況下,哪一個贊成?

編輯

只是要清楚,我說的這個類是適配器,其代表稱遺留系統,以我們自己的實現,傳統轉換成我們自己的類型沿途。我無法更改遺留類型,也不能更改我們的類型(這是XML-Schema生成的)。

+7

關鍵字:JAVA幹吻 - 愛它! – hawkeye

+1

「幹」是什麼意思?啊,答案說,不要重複自己,我猜。 –

+0

@天使,我會在稍後添加引用:-)。 – helpermethod

回答

15

兩者都沒問題。

有了循環,你並沒有真正重複自己,因爲唯一重複的部分是「語法混亂」(在你的情況下並不太多)。您不重複/複製「應用程序邏輯」代碼。

如果您喜歡「函數」風格,也許可以使用Guava庫(具有Function接口和許多與收藏集一起使用的幫助器方法)。這是乾的(因爲你不重複自己,並重新使用已經存在的代碼),並仍然是KISS(因爲這些都是很好理解的模式)。

+0

+1 Thx,完全忘掉番石榴! – helpermethod

9

像DRY和KISS的一般原則從來沒有工作所有的時間

國際海事組織,答案是忘記教條(至少對於這個問題),並思考什麼給你最好/最可讀的解決方案。

IF的重複×4碼容易理解,而不是維護負擔(`因爲你需要改變了很多),其正確的解決方案。

(和蒂洛的答案是正確的太... IMO)

12

如果你只在你的整個應用程序做到這一點的4倍,並轉換爲真如你的例子是小事,我會選擇寫4在通用解決方案的任何時間循環。

由於使用該通用解決方案,可讀性受到很大影響,您實際上並沒有從中獲得任何收益。

+4

在這種情況下,您從DRY中獲益不多:您沒有主要的代碼因子分解;你可能不會因重複自己而引入不連貫的行爲。你仍然相當重複自己,因爲你必須一直寫「新功能 {X apply(Y y){return CFactory.convertFromYToX(y); }}」。我會吻這次。 – ysdx

4

我認爲這不是KISS和DRY相互矛盾。我寧願說Java不允許你表達簡單而不重複自己。

首先,如果您引入了正確命名的方法,將其從List<A>轉換爲List<B>等等,而不是一直重複循環,它將保持乾燥而仍然保持KISS。

但是,我建議的是看看替代語言,讓你充分利用DRY,同時還能促進KISS,例如,在斯卡拉:

val listOfB = listOfA map convertAtoB 
val listOfC = listOfB map convertBtoC 
val listOfD = listOfC map convertCtoD 

convertAtoB是一個函數取A型的項目,並返回B:

def convertAtoB(a: A): B = //... 

或者你甚至可以鏈接這些map電話。

4

你可以移動的轉換功能爲CFactory:

convertAndCopy(listOfA, listOfB, CFactory.getConverterFromAToB()); 

的代碼非常可讀/簡單這樣你促進代碼重用(也許你以後需要使用該轉換器對象在另一個上下文中)。

實現:

public <S, T> void convertAndCopy(List<A> listofA, List<B> listOfB, Function<A, B> f) { 
    listOfB.addAll(Collections2.transform(listOfA,f)); 
} 

(使用番石榴迭代)。

我什至不知道,你應該幹在這裏,你可以直接使用:

listOfB.addAll(Collections2.transform(listOfA,CFactory.getConverterFromAToB())); 
+0

+1這實際上是個好主意:-)。 – helpermethod