我知道日志记录是AOP的主要用例。此外,日志记录包装器也可以作为您希望使用DI的示例,以便类不与特定的日志记录实现相结合。但是,some consider logging wrappers an anti-pattern。首先,这样的视图是因为在大多数情况下,包装器往往是简单的并且删除了特定于日志框架的许多特征。如果您实现这些特定功能,为什么不直接使用框架。
我知道Common.Logging外观试图为您提取log4Net,EntLib,NLog的大量功能。但是,即使在这里,我们仍然依赖于Common.Logging。不是关于接口等的代码/单元测试方式,但如果项目死亡(自上次发布以来已超过一年)或者您希望后者切换到不支持的记录器,则可能会导致问题。
那就是说,如果通过AOP实现日志记录,是否需要使用DI作为日志依赖(即为什么不直接引用说NLog)?是的,AOP部分代码将紧密耦合,但是想要进行单元测试的类的逻辑缺乏记录依赖性(至少在编织发生之前)。在这一点上,我有点迷失(我还没有尝试过AOP)。编织后,没有使用DI作为AOP代码会导致单元测试被测方法的问题吗?或者可以在不编织AOP代码的情况下测试一个单元吗?
除非记录是软件用户的要求,否则我不确定测试记录是否发生了多么有用。我认为被测方法的业务逻辑是大多数人对测试感兴趣的东西。最后,如果想要使用TDD / BDD,是否必须在AOP代码中使用DI来记录日志依赖?或者只是不会试驾 AOP方面的东西?
正如您所看到的,我正在尝试了解开发一个应用程序的最实用的方法,该应用程序将AOP用于横切关注点,而DI用于设计/测试。 由于AOP相对较新,并且日志记录是最常见的示例,建议的方法是什么?
答案 0 :(得分:54)
记录不是服务,而是cross-cutting concern。因此,最好使用Decorator实现。但是,添加许多装饰器只是为了启用各种不同服务的记录,往往会违反DRY,在这种情况下,您可以进一步将这些装饰器演变为单个拦截器。
虽然可以使用IL编织来实现AOP,但更好的选择是使用支持动态拦截的DI容器,因为它是一个更轻量级的解决方案。
这使您可以将具体服务与日志记录完全分离。在那种情况下,我会说没有理由包装任何特定的日志框架,因为如果你想要更改日志框架,你可以只改变那个单一的拦截器。
Here's an example讨论用于检测的装饰器和拦截器(非常类似于记录)。
如果您想了解有关AOP和DI的更多信息,可以view online this talk I gave at GOTO Copenhagen 2010。