记录和依赖注入 [英] Logging and Dependency Injection

查看:192
本文介绍了记录和依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



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



现在我想出了在应用程序期间记录一些信息的问题。我不介绍一般的日志记录方法调用等等。我知道 AOP 并且我可以像这样的方法调用跟踪等。



我要寻找的是手动记录。我需要一些登录我的应用程序几乎每个类的方法。所以我想到了两个选项:


  1. 通过使用Guice注入框架获取记录器,通过构造函数(或setter或private ...),但是感觉像在每个类中真正地添加日志记录,并且在我想要调用日志的方法中使用全局服务定位器来污染我的构造函数

  2. 。呃但是所有的DI粉丝都会讨厌我这样做。

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

解决方案


我需要一些登录我的应用程序中几乎每个类的方法。


再想一想。如果您认为您几乎每个课程都需要登录,您的设计会出现问题。 此Stackoverflow答案将介绍您的设计可能出错。它在.NET的上下文中得到回答,但答案也适用于Java。



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



即使你想要记录调试信息,有没有人会读这个?你会得到日志文件,数千和数千行,没有人会读。如果他们阅读它们,他们必须通过所有这些文本行,并通过它们进行复杂的正则表达式搜索,以获取他们正在寻找的信息。



另一个原因我看到开发者这样做是为了掩盖他们的坏代码。就像这样用意见一样。我看到开发人员记录了我们已经执行了这个程序块,或者如果分支跳过了。这样他们可以跟踪代码和大方法。



但是,我们现在都知道,方法应该很小。不,甚至更小。此外,如果您单独对代码进行单元测试,调试代码就没有太多的理由,而且您已经验证了它是否应该做的。



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



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


但是感觉就像将日志记录关注到
每个类并且污染我的构造函数


这样做,你最终会得到参数太多的构造函数。但不要责怪记录器,责怪你的代码。您在这里违反单一责任原则。您可以通过静态外观来隐藏此依赖关系,但并不会降低依赖关系的数量和类的整体复杂性。


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


最后,你会讨厌自己,因为每一个班级还是有一个额外的依赖(在这种情况下很好的隐藏依赖)。这使得每个类更复杂,并将强制你有更多的代码:更多的代码来测试,更多的代码有bug,更多的维护代码。


I try to build and application based on Java.

For dependency injection I use Google Guice.

Now I came up with the problem of logging some information during the application. I do not talk about general logging in a way of method calls etc. I know about AOP and that I can do like method call tracing etc. with that.

What I look for is manual logging. I need some way of logging in nearly each class in my application. So I thought about two options:

  1. getting the logger by using the Guice injection framework doing this for me through the constructor (or setter or private ...) but it feels like adding the logging concern really to each class and pollutes my constructor
  2. using a global service locator in the method where I want to call the log. Uhh but all DI fans will hate me for doing that

So what is the best way from a practical point of view?

解决方案

I need some way of logging in nearly each class in my application.

Think again. If you think you need logging in nearly every class, there is something wrong with your design. This Stackoverflow answer talks about what might be wrong with your design. It's answered in the context of .NET, but the answer is applicable to Java as well.

That answer mainly talks about exception logging, for non-exception logging I would say: Prevent logging too much information at too many places. For each info or warning that you want to log, question whether this shouldn't have been an exception in the first place. For instance, don't log things like "we shouldn't be in this branch", but throw an exception!

And even when you want to log debug information, does anyone ever going to read this? You'll end up with log files with thousands and thousands of lines that nobody will read. And if they read it, they have to wade through all those lines of text and do complicated regex searches through it to get the information they were looking for.

Another reason I see developers do this is to cover up for their bad code. Just as comments are used in this way. I see developers log things like "we have executed this block" or "this if branch skipped". This way they can trace through the code and big methods.

However, instead of writing big methods, we all know by now that methods should be small. No, even smaller. Besides, if you unit test your code thoroughly, there is not much reason to debug the code and you have verified that it does what it is supposed to do.

And again good design can help here. When you use a design as described in that Stackoverflow answer (with command handlers), you can again create a single decorator that can serialize any arbitrary command message and log it to disk before the execution starts. This gives you an amazingly accurate log. Just add some context information (such as execution time and user name) to the log and you have an audit trail that could even be used to replay commands during debugging or even load testing.

I use this type of application design for a couple of years now, and since then, I hardly ever have any reason to do extra logging within the business logic. It is needed now and then, but those cases are pretty rare.

but it feels like adding the logging concern really to each class and pollutes my constructor

It does, and you'll end up with constructors with too many parameters. But don't blame the logger, blame your code. You are violating the Single Responsibility Principle here. You can 'hide' this dependency by calling it through a static facade, but that doesn't lower the number of dependencies and overall complexity of a class.

using a global service locator in the method where I want to call the log. Uhh but all DI fans will hate me for doing that

In the end, you will hate yourself for that, because every class is still has an extra dependency (a well hidden dependency in this case). This makes each class more complicated, and will force you to have more code: more code to test, more code to have bugs, more code to maintain.

这篇关于记录和依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆