您是否应该将您采用的第三方库包装到项目中?

fly*_*ire 44 refactoring

我今天和同事讨论过.

他声称每当你使用第三方库时,你应该总是为它写一个包装器.因此,您可以随时更改内容并根据具体用途调整内容.

总是不同意这个词,关于log4j的讨论已经出现了,我声称log4j经过了很好的测试和经过时间验证的API和实现,所有可以想象的都可以后验配置,你不应该包装.即使你想要包装,也有经过验证的包装器,如commons-logging和log5j.

我们讨论的另一个例子是Hibernate.我声称它有一个非常大的API被包装.此外,它还有一个分层API,可让您根据需要调整其内部.我的朋友声称他仍然相信它应该被包装但是他没有这样做因为API的大小(这个同事在我们当前的项目中比我更老练).

我声称这个,并且应该在特定情况下进行包装:

  • 您不确定图书馆如何满足您的需求
  • 您将只使用一小部分库(在这种情况下,您可能只暴露其API的一部分).
  • 您不确定库的API或实现的质量.

我还坚持认为,有时你可以包装代码而不是库.例如,将与数据库相关的代码放在DAO层中,而不是抢先包装所有的hibernate.

嗯,最后这不是一个真正的问题,但您的见解,经验和意见都受到高度赞赏.

Mic*_*rdt 63

这是YAGNI的完美典范:

  • 这是更多的工作
  • 它会给你的项目带来膨胀
  • 它可能会使您的设计复杂化
  • 它没有直接的好处
  • 你写的它可能永远不会显现出来
  • 当它发生时,你的包装器很可能需要完全重写,因为它与你正在使用的具体库绑得太紧,新的API与你的API不匹配.

  • @Michael:不,使用包装器的关键是你保持相同的API,使用它的代码根本不需要改变.包装器只应在内部更改. (10认同)
  • 最后一个要点上的+100 (9认同)
  • +1这绝对是最好的理由.为什么你会设计,实现,然后维护代码可能发生的可能性?浪费时间和精力. (3认同)
  • 完全重写包装器比完全重写应用程序要少*少*工作.尽管如此,我同意YAGNI的原则,并且会在你第一次*需要它之前推迟写一个包装器. (3认同)
  • 如果完全重写包装器,您还必须使用它更改所有代码 - 几乎与引入新抽象层的工作量相同. (2认同)
  • 是的,这就是理论.问题是,正如我所写,包装器的API可能与新库的工作方式不匹配 - 因此您也必须更改API. (2认同)

Sat*_*ppy 10

嗯,明显的好处是切换技术.如果你有一个不推荐使用的库,并且你想要切换,你可能最终会重写大量的代码以适应这种变化,而如果它被包装,你可以更轻松地为新的lib编写一个新的包装器. ,而不是改变你的所有代码.

另一方面,这意味着你必须为你包含的每个普通库编写一个包装器,这可能是一个不可接受的开销量.

我的行业是关于速度的,所以我唯一能够证明编写包装器的理由是,它是围绕一些可能会定期发生巨大变化的关键库.或者,更常见的是,如果我需要使用一个新的库并将其塞进旧代码中,这是一个不幸的现实.

这绝对不是一个"永远"的情况.这是可取的.但是时间并不总是存在,最后,如果编写一个包装器需要几个小时,而且长期代码库的更改将会很少,而且很简单...为什么要这么麻烦?


irr*_*ble 6

不。Java 架构师/想要的蜜蜂正忙于针对想象中的变化进行设计。

使用现代 IDE,当您确实需要更改时,这是小菜一碟。在那之前,保持简单。

  • +1 表示“忙于针对想象中的变化进行设计” (2认同)

Fin*_*las 6

我同意几乎所说的一切.

包装第三方代码唯一有用的方法(违反YAGNI)是单元测试.

模拟静态等等要求你包装代码,这是为第三方代码编写包装器的正当理由.

在记录代码的情况下,它不需要.


bma*_*ies 5

这里的问题部分是"包装"一词,部分是错误的二分法,部分是JDK与其他一切之间的错误区别.

'包装'一词

如你所说,包装所有Hibernate是一个完全不切实际的企业.

另一方面,将Hibernate依赖性限制为已识别的,受控制的源文件集可能是实用的并且实现相同的结果.

错误的二分法

错误的二分法是未能认识到第三种选择:标准.如果您使用JPA注释,则可以将Hibernate替换为其他内容.如果您正在编写Web服务并使用JAX-WS注释和JAX-B,则可以在JDK,CXF,Glassfish或其他任何内容之间进行交换.

虚假的区别

当然,JDK变化缓慢,不太可能死亡.但主要的开源软件包也变化缓慢,不太可能死亡.数以千计的开发人员和项目使用Hibernate.实际上,与Java本身相比,Hibernate没有更多的风险消失或进行根本不兼容的API更改.


Uri*_*Uri 5

如果您计划包装的库在其来自同一域中的其他产品的"访问原则,隐喻和习惯用法"中是唯一的,那么您的包装器几乎与该库类似,如果不对您有任何好处,你有一天会切换到另一个库,因为你需要一个新的包装器.

如果以与其他库类似的方式访问库并且相同的包装器可以应用于这些库,则它们可能基于某些现有标准编写,并且存在一些已经存在的公共层来访问它们.

如果我确定我必须在生产中支持多个不同的库,我只会选择包装器.