【问题标题】:Is it worth wrapping a logging framework in an additional layer?是否值得将日志框架包装在附加层中?
【发布时间】:2010-11-01 23:53:45
【问题描述】:

我目前正在考虑升级中型到大型 Java 代码库中的日志记录机制。当前使用 Debug 类上的静态方法记录消息,我建议从该类切换到 SLF4J 或 commons-logging 之类的东西。

应用程序架构师更喜欢我封装对 SLF4J 的依赖项(可能通过将其包装在前面提到的 Debug 类中)。这将使将来更改日志记录实现变得更加容易。

这对我来说似乎有点过头了,因为 SLF4J 已经在抽象具体的日志记录实现了。

是否值得在另一个自主开发的抽象中包装像 SLF4J 这样的第 3 方日志抽象?

【问题讨论】:

  • 架构师还没搞懂什么是slf4j。

标签: java logging encapsulation slf4j apache-commons-logging


【解决方案1】:

我完全同意你的观点:包装器的包装器正在失控。我怀疑架构师没有意识到特别是 SLF4J 可以轻松包装任何其他日志系统,因此“更改实现”在没有另一层包装的情况下是完全可行的。

【讨论】:

  • 确实如此。我只能预见到我们需要从 SLF4J 切换的两个可能原因:要么 SLF4J 完全灭绝,要么有人发明了一种全新的日志记录方式,与现在每个人的方式完全不同。两者似乎都不太可能:)
  • +1 @harto 的评论,因为它是一个完美的声音字节!-)
  • 我猜架构师并没有真正尝试过 slf4j,也没有意识到它是 API,而不是实现。
【解决方案2】:

我猜架构师希望包装包装器(即 SLF4J)背后的动机是将您的应用程序与 SLF4J 隔离开来。显然,从应用程序中调用 SLF4J API 会创建对 SLF4J 的依赖。然而,想要重复应用隔离原则同样合理,如下所述。这让我想起了理查德·道金斯的问题:如果上帝创造了宇宙,那么谁创造了上帝?

确实,您还可以在包装 SLF4J 的包装器上应用隔离原则。如果 SLF4J 包装器在某种程度上不如 SLF4J,那么隔离的原因将无法发挥作用。尽管有可能,但包装器很少能达到或超过原始包装器。 SWT 可以作为一个值得注意的反例来引用。然而,SWT 是一个相当大的项目,成本很高。更重要的是,根据定义,SLF4J 包装器依赖于 SLF4J。它必然具有相同的通用 API。如果将来出现一个新的和显着不同的日志 API,那么使用包装器的代码将与直接使用 SLF4J 的代码一样难以迁移到新的 API。因此,包装器不太可能对您的代码进行未来验证,而是通过添加额外的间接来使其更重。

简而言之,即使您没有更好的事情可做,也不应该浪费时间包装 SLF4J,因为您的包装器的附加值保证接近于零。

SLF4J FAQ entry 中也提出了该主题。

【讨论】:

    【解决方案3】:

    我更愿意包装它,但不是出于所述原因。如果担心换出另一个框架的能力,请使用 java.util.logging 或 SLF(java.util.logging 不像包装器那样容易使用,但它是非常可行的),然后换掉。使用(又一个)包装器的原因是在代码中编写适当的日志记录方式。通常,应用程序需要一个子集,例如所有系统错误都带有异常,或者有关于何时使用标准日志记录级别的特定指导。这些决策可以封装在一些方法中,从而在大型代码库上创建更一致的日志记录决策。

    但是,如果动机只是为了让替换实现成为可能,请不要重新发明轮子。 SLF 非常适合这项工作,只需使用它。

    这有一个例外。如果您的代码旨在无缝地部署到许多可能的应用服务器中,则您必须确保您的日志记录选择不会与框架使用的任何旧版本或新版本发生冲突。

    【讨论】:

    • 关于适当的日志记录方式的要点。确保以一致的方式完成日志记录当然很重要。关于部署考虑,核心库不仅作为我们 Web 应用程序的一部分部署,而且还部署到桌面。但是,我们通常只使用 Tomcat 6,所以我认为这不是问题。
    • 添加专有的日志包装器可能会破坏日志后端的调用定位功能。除此之外,它是您必须支持的另一个模块(调试、错误修复),而充分使用的第三方模块大部分(以相对方式;))已经没有错误。
    • 大部分是相对的?嘿,不要吓到我们的用户! :-)
    • SLF4J 非常认真地努力保持兼容性。实际上,最近在 SLF4J 中遇到的所有的兼容性问题都与负责兼容性管理的代码有关。请记住,您可能自己编写的任何包装器也会有问题。
    • 包装器不会与您碰巧部署的框架发生冲突,因此您可以将框架更换为不冲突的框架,并且只会影响包装器。关于呼叫定位功能,这取决于您如何实现它以及所涉及的框架。我们能够使用 log4j 毫无问题地做到这一点。
    【解决方案4】:

    向您的Architecture Astronaut 解释说 slf4j 已经可以充当其他日志记录实现的包装器,例如 log4j。所以如果你将来需要使用其他一些记录器并且没有slf4j的适配器,你可以在需要时编写它,但它只是适配器,而不是编写一个只会包装一些其他的整个日志记录框架日志框架,您需要为此设计框架并编写自己的适配器。

    【讨论】:

      【解决方案5】:

      每个包装器的问题在于您将决定如何实际包装以及您将提供哪些功能:

      • commons.logging 提供了一组最小的日志记录功能,隐藏了底层框架可能提供的附加功能。您不会获得参数化日志记录或 MDC 等高级功能。
      • SLF4J 以相反的方式工作。它通过在没有本地实现它们的框架之上实现它们来处理参数化日志记录等高级功能。这是更好的方法,恕我直言。

      我不知道你当前的 Debug 类,但我想它很基础。

      你可能不会有类似的功能

      • 日志消息的位置,即源文件的名称 + 行号
      • 不同的日志记录级别
      • 能够有选择地设置不同记录器的级别,即每个类没有一个记录器,能够将该记录器设置为某个感兴趣的级别,例如信息,警告。这非常关键。

      如果您的 Debug 类非常基本,这对您来说实际上非常好:)

      这意味着您很可能可以通过执行全局搜索和销毁... err... 替换来切换到 SLF4J。

      进行备份,不过... ;)

      另请参阅Should new projects use logback instead of log4j?、What’s Up with Logging in Java?、Which log4j facade to choose?、Find a way in the java logging frameworks scene. 和 Do you find java.util.logging sufficient?。 (剧透:你不应该使用 java.util.logging,拜托了)

      【讨论】:

        【解决方案6】:

        如果您打算在未来切换 Logging 框架,可能值得添加一个额外的层来切换记录器。否则,如果他们提供了你可能需要的一切(当然是使用你的水晶球),那么对那个框架有一个硬依赖可能是可以的。

        如果您当前的设置允许灵活更改,则不需要包装器。

        【讨论】:

        • 重点是,SLF4J已经被设计用来包装“任何可能的日志系统”(他们是雄心勃勃的,但也相当熟练......) ,并且已经提供了几个包装器以及本机实现。
        • SLF4J 旨在包装当前流行的(现有)日志框架。 SLF4J 不会也不能对未来的日志框架做出声明。
        猜你喜欢
        • 2015-03-11
        • 2013-08-28
        • 1970-01-01
        • 2019-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-18
        相关资源
        最近更新 更多