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