Java 当吻和干碰撞时
我是一个执迷于法律和原则的追随者,但上周我遇到了一个案例,两者似乎相互矛盾: 对于我正在做的一个应用程序,我必须实现一个循环For times,它执行以下操作:Java 当吻和干碰撞时,java,dry,Java,Dry,我是一个执迷于法律和原则的追随者,但上周我遇到了一个案例,两者似乎相互矛盾: 对于我正在做的一个应用程序,我必须实现一个循环For times,它执行以下操作: 迭代类型a列表的元素 将类型A的元素转换为类型B,并将其插入类型B的列表中 下面是一个例子: for (A a : listOfA) { listOfB.add(BFactory.convertFromAToB(a)); } 在代码中,我必须这样做大约4次,将一个类型(如D、e等)转换为另一个类型。我可能无法更改我要转换的类型
for (A a : listOfA) {
listOfB.add(BFactory.convertFromAToB(a));
}
在代码中,我必须这样做大约4次,将一个类型(如D、e等)转换为另一个类型。我可能无法更改我要转换的类型,因为它们是我们必须在out应用程序中使用的第三方类型
因此,我们:
for (A a : listOfA) {
listOfB.add(BFactory.convertFromAToB(a));
}
for (C a : listOfC) {
listOfB.add(DFactory.convertFromCToD(c));
}
...
因此,为了不违反dry,我提出了一个通用解决方案:
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));
}
}
专用接口函数{
不适用;;
}
public void convertAndCopy(列表src、列表dst、函数f){
适用于(S:src){
dst.添加(f.应用);
}
}
一个电话看起来像这样:
convertAndCopy(listOfA, listOfB, new Function<A, B>() {
A apply(B b) {
return CFactory.convertFromBToC(b);
}
});
convertAndCopy(listOfA,listOfB,new函数),因为这种解决方案比复制for循环更难理解
那么,这是干吻还是吻?在这种情况下,哪一个更受欢迎
编辑
需要明确的是,我所说的类是一个适配器,它将对遗留系统的调用委托给我们自己的实现,并将遗留转换为我们自己的类型。我无法更改遗留类型,也不能更改我们的类型(由XML模式生成).干燥和亲吻等一般原则永远不会奏效
在我看来,答案是忘记教条(至少在这个问题上是这样),想想什么能给你提供最好/最具可读性的解决方案
如果复制的x 4代码更容易理解,并且不是维护负担(即,您不需要对其进行太多更改),那么它就是正确的解决方案
(Thilo的答案也是正确的……IMO)如果在整个应用程序中只需执行4次,并且转换与示例一样简单,那么我会选择在通用解决方案中随时编写4 for循环
使用这种通用解决方案会使可读性受到很大影响,而实际上您并没有从中获得任何好处。两者都可以
对于循环,您并不是在真正地重复自己,因为唯一重复的部分是“语法混乱”(在您的例子中不是太多),您并不是在重复/复制“应用程序逻辑”代码
如果您喜欢“函数”样式,可以使用Guava库(它有函数接口和许多在集合中使用它们的助手方法)。这是干巴巴的(因为您不重复自己,并且重复使用已经存在的代码),并且仍然可以使用KISS(因为这些是很好理解的模式).我认为并不是KISS和DRY互相矛盾。我宁愿说Java不允许您在不重复自己的同时表达简单性
首先,如果您引入正确命名的方法,从List
转换为List
等等,而不是一直重复循环,那么它将是干燥的,同时仍然保持亲吻
但我的建议是,看看其他语言,让你在推广亲吻的同时充分利用DRY,例如Scala:
val listOfB = listOfA map convertAtoB
val listOfC = listOfB map convertBtoC
val listOfD = listOfC map convertCtoD
其中,convertAtoB
是一个函数,它接受类型为a的项并返回B:
def convertAtoB(a: A): B = //...
或者您甚至可以链接这些map
调用。您可以将转换函数移到CFactory中:
convertAndCopy(listOfA, listOfB, CFactory.getConverterFromAToB());
通过这种方式,代码非常可读/简单,并且可以促进代码重用(以后可能需要在另一个上下文中使用converter对象)
实施:
public <S, T> void convertAndCopy(List<A> listofA, List<B> listOfB, Function<A, B> f) {
listOfB.addAll(Collections2.transform(listOfA,f));
}
关键词:爪哇干吻-爱死它了!什么是“干”的意思?啊,答案是这样的,我想你不要重复了。@Angel,sry我稍后会添加引用:-)。@helpermethod-无需。Angel应该阅读标签wiki中的标签;e、 在它上面盘旋。+1次,完全忘记番石榴!在这种情况下,您不会从DRY中获得太多好处:您没有主要的代码分解;你可能不会因为重复自己的话而导致语无伦次的行为。您仍然需要重复自己的操作,因为您必须始终编写“新函数{X apply(Y){return CFactory.convertFromYToX(Y);}}”。这次我要接吻了。+1这真是个好主意:-)。
listOfB.addAll(Collections2.transform(listOfA,CFactory.getConverterFromAToB()));