Logging, Aspect Oriented Programming, and Dependency Injection - Trying to make sense of it all
我知道日志记录是AOP的主要用例。另外,当您想要使用DI时,日志包装器也被举例说明为案例,这样类就不会与特定的日志实现耦合。但是,有些人认为日志包装器是反模式的。主要是,这种视图是因为在大多数情况下,包装器趋向于简单化,并删除了日志框架的许多特定功能。如果您实现了这些特定的特性,为什么不直接使用框架呢?
我知道常见的.logging外观,它试图为您抽象log4net、entlib和nlog的大量特性。然而,即使在这里,我们仍然对common.logging有某种依赖性。不是以代码/单元测试的方式来测试接口等,但是如果项目死了(自上一个版本以来已经超过一年了),或者您希望后一个版本切换到不受支持的记录器,这可能会导致问题。
也就是说,如果日志是通过AOP实现的,那么是否有必要使用DI作为日志依赖项(即,为什么不直接引用,比如说nlog)?是的,代码的AOP部分将紧密耦合,但希望进行单元测试的类的逻辑没有日志记录依赖性(至少在编织发生之前)。现在我有点迷路了(我还没试过AOP)。编织之后,如果没有将DI用于AOP代码,会不会导致单元测试被测方法出现问题?或者一个单元可以在不编织AOP代码的情况下进行测试吗?
除非日志记录是软件用户的一项要求,否则我不确定测试Mocks中发生的日志记录有多有用。我认为被测试方法的业务逻辑是最感兴趣的测试。最后,如果您想要使用TDD/BDD,那么您不需要使用DI来记录AOP代码中的依赖项吗?或者你只是不试驾AOP方面的东西?
正如您所看到的,我试图了解开发应用程序的最实用方法是什么,它将AOP用于横切问题,将DI用于设计/测试。由于AOP是相对较新的,日志记录是最常见的例子,那么推荐的方法是什么?
伐木不是一种服务,而是一种跨领域的关注。因此,最好用一个修饰器来实现。然而,添加大量的装饰器只是为了能够记录各种不同的服务,这往往会违反dry,在这种情况下,您可以进一步将这些装饰器演化为一个拦截器。
虽然可以使用IL编织来实现AOP,但更好的选择是使用支持动态拦截的DI容器,因为它是一个更轻量的解决方案。
这使您能够将具体的服务与日志完全分离。在这种情况下,我会说没有理由包装任何特定的日志框架,因为如果您想要更改日志框架,您可以只更改单个拦截器。
下面是一个例子,讨论了仪表的修饰器和拦截器(非常类似于日志记录)。
如果你想了解更多关于AOP和DI的信息,你可以在线查看我在Goto哥本哈根2010年的演讲。