- 依赖注入是将组件注入到需要其行为的组件中。
- 面向方面的编程是关于将横切关注点应用于代码(实际上是关于坚持开放/封闭原则)。
使用 DI 时,AOP 会变得更加自然。您可以使用代理来做到这一点,但我个人的偏好是通过应用好的旧装饰器来做到这一点。
它看起来像 AOP,闻起来像 AOP,但很难与成熟的 AOP 框架相提并论。
我完全不同意这篇声明的作者。根据我的经验,PostSharp 之类的工具可以让您解决应用程序中的设计缺陷。在处理遗留应用程序或无法更改的设计(例如处理INotityPropertyChanged
接口)时,这可以使这些工具非常强大。然而,虽然这些工具允许您在不修复设计的情况下添加 AOP 功能,但这些设计缺陷仍然会在项目的整个生命周期中困扰您。
一个简单的例子是可测试性。像这样的工具并没有解决应用程序的可测试性问题,而依赖注入模式确实解决了这个问题。由于这些工具在编译时编织切面,这使得在没有切面的情况下测试代码非常困难(这是您在进行单元测试时需要做的事情,有时甚至在集成测试时也是如此)。您将不得不使用编译器指令做一些巧妙的技巧,但这只能解决部分问题,因为您仍然想测试这些方面,但只是孤立地测试,就像您想孤立地测试每段代码一样(这就是单元测试是关于)。即使你能解决它,你的代码仍然很难维护。无法维护的代码是由设计缺陷引起的。
文章的作者说:
第一个问题是动态代理仅允许您将方面添加到服务的显式边界,您选择公开为接口的那些。即使您愿意,也不能向私有或静态方法添加方面。
他对此完全正确,但是如果您想为私有或静态方法添加方面,那么您的设计就有问题:修复设计!
第二个问题更具戏剧性。当您沉迷于 AOP 的一些好处时,即使您不需要依赖注入,您也开始使用动态代理,仅仅因为动态代理的要求而改变代码的体系结构。这是错误的。AOP 不需要您更改代码的体系结构。
再一次,作者是对的:使用 PostSharp 时,您不需要更改 AOP 的体系结构。但是如果设计不正确,应用方面仍然要困难得多,即使使用 PostSharp 之类的工具也是如此。并且不要忘记使用 PostSharp 的无属性 AOP 只有在使用商业版本时才有可能。使用属性应用 AOP 仍然会导致高耦合和维护问题。所有 DI 工具(至少对于 .NET)都可以免费使用,并且默认使用无属性。
好的设计根本没有其他选择,当拥有像 PostSharp 这样的正确设计工具在大多数情况下变得多余时。它们在某些边缘情况下仍然是有益的(并且在这些情况下可能非常有益),但根据我的经验,当您的设计是SOLID时,这些情况很少见。
现在问题显然变成了:什么是好的 SOLID 设计?根本没有现成的、始终有效的设计可以应用于所有应用程序。我设计的每个应用程序都是不同的,尽管在过去几年中我看到了某些可能对您也有益的重复模式。我过去在这里、这里和这里都写过这个。这些文章中描述的模式已经成为我帮助设计和构建的许多应用程序的基本构建块。这些模式的关键成分是 SOLID。