我需要某种方式登录应用程序中的几乎每个类。
再想一想。如果您认为需要登录几乎每个类,那么您的设计就有问题。这个Stackoverflow答案讨论了你的设计可能存在的问题。它在.NET的上下文中得到了答案,但答案也适用于Java。
这个答案主要讨论异常日志记录,对于非异常日志记录,我会说:防止在太多地方记录太多信息。对于要记录的每个信息或警告,请询问这是否首先不应该是异常。例如,不要记录诸如“我们不应该在这个分支中”之类的事情,而是抛出一个异常!
即使您想记录调试信息,是否有人会阅读此内容?您最终会得到包含成千上万行的日志文件,没有人会阅读。如果他们阅读它,他们必须遍历所有这些文本行,并通过它进行复杂的正则表达式搜索,以获得他们正在寻找的信息。
我看到开发人员这样做的另一个原因是掩盖他们的糟糕代码。就像注释以这种方式使用一样。我看到开发人员记录了诸如“我们已经执行了此块”或“如果跳过分支,则为”之类的内容。通过这种方式,他们可以跟踪代码和大方法。
但是,我们现在都知道方法应该很小,而不是编写大方法。不,甚至更小。此外,如果您对代码进行彻底的单元测试,则没有太多理由调试代码,并且您已经验证了它是否执行了它应该执行的操作。
再一次,好的设计可以在这方面有所帮助。使用 Stackoverflow 答案中所述的设计(使用命令处理程序)时,可以再次创建单个修饰器,该修饰器可以序列化任何任意命令消息,并在执行开始之前将其记录到磁盘。这为您提供了非常准确的日志。只需向日志中添加一些上下文信息(例如执行时间和用户名),您就有了一个审计跟踪,甚至可以在调试甚至负载测试期间重播命令。
我使用这种类型的应用程序设计已经有几年了,从那时起,我几乎没有任何理由在业务逻辑中进行额外的日志记录。时不时需要它,但这些情况非常罕见。
但这感觉就像将日志记录问题真正添加到每个类中并污染了我的构造函数
确实如此,您最终会得到参数过多的构造函数。但不要责怪伐木者,责怪你的代码。您违反了此处的单一责任原则。您可以通过静态外观调用此依赖项来“隐藏”此依赖项,但这不会降低类的依赖项数量和整体复杂性。
在我要调用日志的方法中使用全局服务定位器。呃,但所有DI粉丝都会讨厌我这样做
最后,你会为此而讨厌自己,因为每个类仍然有一个额外的依赖关系(在这种情况下是一个很好的隐藏的依赖关系)。这使得每个类都更加复杂,并且将迫使您拥有更多代码:要测试的代码更多,要有错误的代码更多,要维护的代码更多。