我目前正在考虑升级中型到大型Java代码库中的日志记录机制。消息当前使用Debug
类上的静态方法记录,我建议从此切换到SLF4J或commons-logging。
应用程序架构师更喜欢我将依赖性封装在SLF4J上(可能将其包装在前面提到的Debug
类中)。这样可以更容易在将来更改日志记录实现。
这对我来说似乎有些过分,因为SLF4J已经在抽象具体的日志记录实现。
是否值得在另一个自制的抽象中包装像SLF4J这样的第三方日志记录抽象?
答案 0 :(得分:22)
我完全同意你的观点:包装纸包装纸包装失控。我怀疑架构师没有意识到SLF4J如何能够轻松地包装任何其他日志记录系统,因此“改变实现”是完全可行的,没有另一层包装。
答案 1 :(得分:10)
我认为架构师希望包装包装器(即SLF4J)的动机是将应用程序与SLF4J隔离开来。显然,从应用程序中调用SLF4J API会对SLF4J产生依赖关系。但是,如下所述,想要反复应用隔离原理同样合法。它让我想起理查德道金斯的问题:如果上帝创造了宇宙,那么谁创造了上帝呢?
实际上,您还可以在包装SLF4J的包装器上应用隔离原理。如果SLF4J包装器在某种程度上不如SLF4J,那么隔离的原因就会受到影响。虽然可能,但是包装材料相当于或超过原件是很少见的。 SWT可以作为一个值得注意的反例。但是,SWT是一个规模相当大的项目,成本很高。更重要的是,SLF4J-wrapper的定义取决于SLF4J。它必然具有相同的通用API。如果将来会出现一个新的,显着不同的日志记录API,那么使用包装器的代码将同样难以作为直接使用SLF4J的代码迁移到新API。因此,包装器不太可能在未来证明您的代码,但通过添加额外的间接使其更重。
简而言之,即使您没有更好的事情要做,也不应该浪费时间包装SLF4J,因为保证包装的附加值保证接近于零。
该主题也在SLF4J FAQ entry中进行了讨论。
答案 2 :(得分:8)
我更愿意把它包起来,但不是出于上述原因。如果担心是换出另一个框架的能力,请使用java.util.logging或SLF(java.util.logging不像包装器那样容易使用,但它非常可行),并且交换掉。使用(又一个)包装器的原因是在代码中编写适当的日志记录方法。通常,应用程序需要一个子集,例如所有系统错误都带有异常,或者具有关于何时使用标准日志记录级别的特定指导。这些决策可以封装在一些方法中,在大型代码库中创建更一致的日志记录决策。
但是,如果只是为了使交换实现成为可能,那么就不要重新发明轮子。 SLF非常适合这项工作,只需使用它即可。
这有一个例外。如果您的代码无意中被部署到许多可能的应用服务器中,那么您必须确保您的日志记录选择不会冒与框架正在使用的可能较旧或较新版本冲突的风险。
答案 3 :(得分:4)
向你的Architecture Astronaut解释slf4j已经可以作为其他日志实现的包装器,比如log4j。因此,如果您将来需要使用其他记录器并且没有适用于slf4j的适配器,您可以在需要时编写它,但它只是适配器,而不是编写一个完整的日志框架,它将只包装其他一些日志框架,您需要为此设计框架并编写自己的适配器。
答案 4 :(得分:4)
每个包装器的问题在于决定如何实际包装以及您将提供哪些功能:
我不知道你当前的Debug类,但我想这很基本。
你可能没有像
这样的功能如果您的Debug类 非常基本,这实际上非常适合您:)
这意味着您可能可以通过执行全局搜索来切换到SLF4J& destr ...错误...替换。
进行备份,但......;)
另请参阅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,非常请)
答案 5 :(得分:0)
如果您考虑将来切换日志框架,可能需要在可以切换记录器的位置添加额外的图层。否则,如果他们提供了你可能需要的一切(当然是使用你的水晶球),那么对该框架的依赖可能是好的。
如果您当前的设置允许灵活更改,则不需要包装器。