当亲吻和干燥碰撞[关闭]

2022-09-02 23:18:03

我是DRYKISS原则的痴迷追随者,但上周我有一个案例,两者似乎相互矛盾:

对于我正在做的应用程序,我必须多次实现一个循环,该循环执行以下操作:

  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 架构生成的)。


答案 1

两者都很好。

对于循环,你并没有真正重复自己,因为唯一重复的部分是“语法混乱”(在你的情况下不会太多)。您没有重复/复制“应用程序逻辑”代码。

如果你喜欢“函数”风格,也许可以使用番石榴库(它具有函数接口和许多在集合上使用它们的帮助器方法)。这是DRY(因为你不会重复自己,而是重用已经存在的代码),仍然是KISS(因为这些是很好理解的模式)。


答案 2

如果你只需要在整个应用程序中这样做4次,并且转换实际上和你的示例一样微不足道,我会选择在通用解决方案上随时编写4个for循环。

使用这种通用解决方案会给可读性带来很大损失,而且您实际上并没有从中获得任何东西。


推荐