Nate Kohari 发布了针对.NET 的依赖注入容器 Ninject 的 1.0 版本。依赖注入如今已经广为人所知,而这个新鲜出炉的工具 Ninject 正是为了更好地利用这项技术。
Ninject 为.NET 应用程序提供快速、轻型的依赖注入器而著称。它有助于开发人员将应用程序拆分为松耦合、高内聚的功能片断的集合,然后以灵活的方式将它们粘连在一起。从软件架构层面上使用 Ninject,可以使得你的代码更易于编写、重用、测试和修改。
Ninject 网站对 Ninject 的描述如下:
- 专注。目前太多的依赖注入项目牺牲了可用性,换来的却是不太常用的功能特性。在每一次,我们将一个特性加入到 Ninject 时,都会对其带来的益处与复杂性进行权衡。我们的目的是守好入口——这是使用 Ninject 所要求的最基本底线。Ninject 有很多高级特性,相对于基本特性而言,理解它们不是必须的。
- 雅致。框架膨胀是一些项目面临的最大问题,鉴于此,Ninject 的所有核心功能都是一个单独的程序集,与.NET 基本类库没有任何依赖。在编译发布时,单独的程序集容量大约为 110KB。
- 快速。不同于依赖于反射调用的其他框架,Ninject 利用了 CLR 2.0 版本的轻量级代码生成特性。在多种场景下,性能都得到了显著(8-50 倍)的提升。
- 严谨。Ninject 有效地避免了开发人员在首次使用的时候犯错。它没有依赖 XML 映射文件以及字符串识别符来组成组件,而是提供了健壮的领域特定语言。这就意味着 Ninject 充分地利用了语言(例如类型安全)和 IDE(例如智能感知和代码完成)的特长。
- 敏捷。Ninject 的设计基于组件架构,允许定制化与系统的演进。系统的许多方面都可以增强或修改,以适应每个项目的需求。
- 隐藏。尽管使用了.NET 特性,但 Ninject 并不会影响你的代码。你可以很容易地将 Ninject 的依赖隔离到项目中的一个单独程序集中。
- 强大。Ninject 涵盖了众多高级特性。例如,Ninject 是第一个支持上下文绑定的依赖注入容器,可以根据服务请求的上下文为服务注入不同的具体实现。
InfoQ 有幸对该框架的作者 Nate 进行访谈,对 Ninject 的内容与原理进行了介绍,以飨读者。
Robert Bazinet(以下缩写为 RB):能否做一下自我介绍?
Nate Kohari(以下缩写为 NK):我来自于俄亥俄州亚克朗市,今年 25 岁,是一名软件架构师。我就职于 Commercial Timesharing 公司(CTI),这是一家咨询公司,为客户开发软件和商务智能解决方案。在 CTI,我的角色是为.NET 项目提供架构指导,但是我仍然会参与开发——毫无疑问,我仍然是一名“战斗在前线”的架构师。在我的大学时代和早期职业生涯中,我做过 C、C++、PHP 以及在 Linux 下 Perl 的开发,这正是我坚定支持开源的一大主因。
RB:Ninject 是什么呢?
NK:Ninject 是一个依赖注入框架,如果你愿意,也可以说是“控制反转容器”。我们已经对工厂模式有所耳闻,而 Ninject 就类似于某种“超级工厂 ”,它知道如何根据你提供的提示,创建所有类型的对象。从根本上讲,如果你将应用程序视为是“拼图游戏”,一旦你告知 Ninject 需要使用哪些“拼图 ”,Ninject 就会将它们拼凑在一起。而且,如果你在未来希望修改拼图的方式,你只需修改你的绑定,Ninject 会为你完成余下的工作。
RB:依赖注入为何如此重要?
NK:正如一句格言所云:“唯一的约束就是变化”,在软件领域中,此言可谓“放之四海而皆准”。Fred Brooks 写到软件没有银弹——既然软件“易于”变化(相对而言),因此人们总会找到理由提出变化。项目的发展与范围的界定总是举步维艰,在倾瞬之间,你创建的小规模的应用程序原型会成为企业系统的关键任务。控制反转——实际上总是使用依赖注入来实现——将有助于你从一开始就能够设计出在灵活性上符合要求的软件。当变化不可避免的发生时,软件却能够随需而变。这种灵活性使得你能够更加容易地进行单元测试,因为在测试期间,你可以将真实组件替换为 Mock 对象。
RB:为什么要开发一个新的依赖注入容器?
NK:传统上的依赖注入框架依赖于 XML 去定义元数据,从而为你的应用程序组成组件。XML 不仅写起来麻烦,而且不容易扩展:随着应用程序的增长,定义了元数据的 XML 文件就会迅速膨胀。Ninject 采用了 Google Guice 的方式,这是在 Java 世界中相对较新的依赖注入框架,通过提供接口用于连接软件的各个小块。Ninject 的目标是无论项目规模大小,都能够灵活地进行依赖注入,即使项目增长,对元数据的管理依然能够轻而易举。我希望能够降低依赖注入的入门难度。最终的目的是要创建一个轻便快速,易于使用的依赖注入框架。
RB:为何要使用 Ninject,而不是选择其它产品,例如 StructureMap,Unity,Windsor 以及其它?
NK:不要误解我的意思,这些都是伟大的项目。但是,它们却受制于我所顾虑的“XML 优先”的思想。由于 Ninject 允许你使用代码来建立你的组件,因而可以利用语言和 IDE 的特性——例如类型安全和代码完成——这些在编写 C#和 VB.NET 中经常用到的特性,但在编写 XML 时却无法使用。某些框架建立在“ 连贯接口(fluent interfaces)”上,以弥补 XML 配置的缺陷,但在 API 中,这些却属于二等公民。
Ninject 能够帮助你在设计应用程序时提供依赖注入特性。使用 Ninject 时,你可以声明一个或多个“模块”,每个模块都是应用程序的组成部分。由于这些模块都是类,因而对它们的构建就特别简单和智能化。例如,你可以读取命令行参数,扫描程序集获得准确的类型,或者甚至在数据库之外读取配置,而这些却是 XML 力不能及的。Ninject 还具有一项非常强大的高级特性,称为“上下文绑定”,可以用于为某个特定类型声明多个绑定。同时,Ninject 会根据正在创建的对象所属的上下文去判断应该使用哪一个绑定。最后,Ninject 非常易于扩展。Ninject 对此给与了极大的关注,以确保框架的每个单独的功能块都能够被定制,同时能与不同的库集成。
RB:这样设计的 Ninject 能否应用在现有项目上?如果能,那么通常而言,不管是对代码进行重构,还是编写新代码,开发人员应该如何使用 Ninject 才能有效地促进开发向前发展。
NK:控制反转仅仅是一种思想,各种依赖注入(无论有无框架)都取决你设计的软件是否抱有控制反转的目的。遗留软件通常受制于糟糕的强依赖(关注的拙劣分离)以及“控制的问题”,即对象负责创建自己的依赖。软件具有的控制反转反模式越多,那么使用 Ninject 对代码进行优化就越困难——应该说任何一种依赖注入技术对于这种情况都难以应对。虽然困难,但仍然是可行的。Ninject 可以使依赖变得极为简单,一旦你在软件中使用 Ninject,则纠正这些反模式就会变得更加简单。首先,需要找到和创建组件之间的合适的分离,并使用 Ninject 将它们组合。之后,就可以通过将组件修改为与接口交互从而引入灵活性。最开始应该从应用程序的小块片断开始,然后在时间允许的情况下逐步扩大到其余部分。同时,Ninject 也有助于在新代码中使用依赖注入,因为一旦你在一开始就使用它,就有助于在整个代码中使用。记住,这是件好事情——它意味着你的代码变得更加灵活!
RB:Ninject 产品可否为每个开发者所使用?或者说 Ninject 以及其他 DI 容器是否真的只能被高级技术人员,例如架构师或者高级开发人员使用?
NK:只有项目中的所有开发人员都使用控制反转,并参与其中,才算得上是成功。正如我所说,这完全是心态问题。Ninject 的设计是要降低入门门槛,也就是说框架要足够简单,使得任何人都可以参与,而无须理解其高级特性。而且,通常控制反转应该从整体上考虑,为了能够为项目所接受,开发带头人或架构师应该对其进行强制规定。有时,这种规定难以推行(“你的意思是我们必须使用这个框架?为什么我们不能直接用’new’去创建对象?”),但这一切都是要去偿还设计的债务。在项目早期使用依赖注入框架,就好比是支付现金而非使用信用卡。当变化不可避免发生时,软件会更容易适应新的需求。以我的经验来看,一旦一次大的重构变得与实现新版本,以及修改绑定一样简单,那么控制反转的价值就变得更加明显了。在内心建立用控制反转编写软件的思想,会使得进行单元测试更加容易,因为你可以替换真实实现而在测试中进行模拟。如果你不需要编写单元测试,也应该这样做!
RB::我注意到 Ninject 支持 Silverlight 2.0 Beta 2,能否就此给与说明?
NK:是的。Ninject 项目的一个主要目标是使得依赖注入能够适用于各种规模和类型的项目。鉴于此,Ninject 1.0 不仅支持.NET 框架 2.0、3.0 和 3.5,而且还支持.NET 精简框架 2.0 和 3.5,以及 Silverlight 2.0 的最新试用版本 beta 2。这种多平台的支持,是我竭力所为,也是我颇感自豪的一点。我想,对于依赖注入的一种误解,就是它只能有效地应用于大型企业项目中,然而 Ninject 确是一种轻型、快速的框架,只要你运行在.NET 运行时上,它都能应付自如。我个人曾经在一些应用程序中成功地应用了 Ninject,这些程序都构建于运行在.NET 精简框架的手持设备上。
RB:Ninject 是开源的,那么其他开发人员应该如何参与,并提交代码?
NK:对,Ninject 基于 Apache License 2.0 进行发布,即各种项目都可以使用它,而无须重新分发源代码。我时刻期待着用户的反馈以改进框架,如果你乐于分享你创建的超酷特性,我很愿意将其放到补丁中。提交它们的最佳方式是在用户组中发布。方法是在 Ninject 网站中选择" speak your mind "链接。同时,如果你有志于贡献额外的文档,包括向导、示例或其他内容,都可以参与到文档Wiki 中。开源是与讨论和社区密切相关的,虽然Ninject 在软件开发方面“自行其是”,但我仍然专注于提供解决方案以满足社区的需要。
RB:开发人员获得 Ninject 1.0 的最佳方式是什么?有无入门的终南捷径?
NK:在 Ninject 网站中可以获得 1.0 版本的二进制文件或源代码。如果你希望关注最新动态,则可以检查 Subversion 上提供的最新构建版本。如果要提交补丁,则应该检查一下版本服务器,以确保你拥有的是最新版本。
RB:Ninject 可有详细的文档,以及代码示例 / 最佳实践?
NK:当然有!这些内容都放在 Dojo 上了。这里提供的内容可谓是 Ninject 入门的终南捷径,同时,示例程序则演示了更多高级特性。Dojo 仍在不断完善之中,随着 1.0 的发布,我也计划抽出时间来编写更多的文档。开源软件通常会因为缺乏好的文档而遭遇“滑铁卢”,我不希望看到 Ninject 重蹈覆辙。
RB:Nate,非常感谢百忙之中接受采访。
更多信息以及详细文档,可在 Ninject 的官方网站上下载并获得支持。有关框架作者 Nate Kohari 的信息,可以从他的博客中找到。
查看英文原文: Nate Kohari on Releasing Ninject 1.0 。
志愿参与 InfoQ 中文站内容建设,请邮件至 editors@cn.infoq.com 。也欢迎大家到 InfoQ 中文站用户讨论组参与我们的线上讨论。
评论