日志记录和依赖注入

问题描述

我需要某种方式登录应用程序中的几乎每个类。

再想一想。如果您认为几乎每个类都需要登录,则您的设计有问题。这个Stackoverflow答案讨论您的设计可能出什么问题。它是在.NET上下文中回答的,但答案也适用于Java。

该答案主要是关于异常日志记录的,对于非异常日志记录,我会说:防止在太多地方记录太多信息。对于您要记录的每个信息或警告,首先要问这是否应该不是例外。例如,不要记录“我们不应该在此分支中”之类的日志,而要抛出异常!

甚至当您要记录调试信息时,有没有人会阅读此信息?您最终将获得包含成千上万行的日志文件,没人会读取。而且,如果他们阅读了该文本,则必须遍历所有这些文本行,并对其进行复杂的正则表达式搜索,以获取所需的信息。

我看到开发人员这样做的另一个原因是掩盖他们的错误代码。就像以这种方式使用注释一样。我看到开发人员记录了诸如“我们已经执行了此块”或“如果跳过了分支这一点”之类的事情。这样,他们就可以遍历代码和大型方法

但是,我们现在都知道写方法应该很小,而不是编写大方法。不,甚至更小。此外,如果您对代码进行彻底的单元测试,则没有太多理由调试代码,并且您已验证它可以执行预期的工作。

好的设计可以再次为您提供帮助。当您使用该Stackoverflow答案(带有命令处理程序)中所述的设计时,您可以再次创建一个装饰器,该装饰器可以序列化任意命令消息并将其记录在执行开始之前的磁盘上。这为您提供了非常准确的日志。只需在日志中添加一些上下文信息(例如执行时间和用户名),您就会拥有一个审计跟踪,甚至可以在调试甚至负载测试期间重播命令。

我使用这种类型的应用程序设计已有两年了,从那时起,我几乎没有理由在业务逻辑中进行额外的日志记录。有时需要它,但是这些情况很少见。

但是感觉就像真的在每个类中增加了日志记录关注,并且污染了我的构造函数

确实如此,您最终将获得带有太多参数的构造函数。但是不要怪记录器,也不要怪您的代码。您在这里违反了“单一责任原则”。您可以通过静态外观调用此依赖项,以“隐藏”此依赖项,但这不会降低依赖项的数量和类的整体复杂性。

在我要调用日志的方法中使用全局服务定位器。嗯,但是所有DI粉丝都会讨厌我这样做

最后,您会为此而讨厌自己,因为每个类仍然有一个额外的依赖项(在这种情况下,这是一个隐蔽的依赖项)。这会使每个类变得更加复杂,并且将迫使您拥有更多的代码:要测试的代码更多,要有错误代码更多,要维护的代码更多。

解决方法

我尝试构建基于Java的应用程序。

对于依赖项注入,我使用Google Guice。

现在我想到了在应用程序中记录一些信息的问题。我不是在谈论方法调用等方式的常规日志记录。我对AOP有所了解,并且我可以像这样进行方法调用跟踪。

我要寻找的是手动记录。我需要某种方式登录应用程序中的几乎每个类。所以我考虑了两个选择:

  1. 通过使用Guice注入框架通过构造函数(或setter或private …)为我做到这一点,从而获得记录器,但是感觉就像真的将日志记录问题添加到每个类并污染了我的构造器
  2. 在我要调用日志的方法中使用全局服务定位器。嗯,但是所有DI粉丝都会讨厌我这样做

那么从实际角度来看最好的方法是什么?