微信号:infoqchina

介绍:有内容的技术社区媒体

【实践】当IoC遇见了Node.js

2014-06-06 17:58 InfoQ

没有IoC的年代

一个简单的例子:

var Engine = require('./engine');

var Wheel = require('./wheel');


var Car = function() {

this.engine = new Engine();

this.wheel = new Wheel();

}


Car.prototype.run = function() {

this.engine.run();

this.wheel.run();

console.log('run car...');

}


module.exports = Car;

在例子中,汽车(car)需要依赖轮子(wheel)和发动机(engine)才能跑起来。为了处理好这一关系,必须首先人为的通过requireenginewheel引入进来,然后通过new操作实例化,这样car才能真正的run起来。


这个例子非常简单,但是存在着一些问题:

  1. require的时候,需要直接知道enginewheel的文件位置、文件名、以及所exports的是什么。一旦engine或者wheel的文件名、所在位置、exports方式发生了变化,require操作必须做出相应的改变

  2. car直接依赖于enginewheel,因此如果我们试图做单元测试,则会发现mock engine或者wheel非常困难,要么就是修改enginewheel的代码,要么就是修改car的代码


这个例子只有3个对象,读者可能觉得也没啥要紧的,这样直接做也没多大问题。但是一旦系统里面的对象数量变大了呢?


这样的系统紧密耦合,往往会造成难以维护、难以重构、难以做单元测试,尤其是当一个新人加入团队的时候,也会因为这份复杂性变得举步维艰,看不明白也改不动。


步入IoC

使用IoC之后,car的代码就会变成如下所示:

var Car = function(engine) {

this.engine = engine;

this.wheel = null;

}


Car.prototype.run = function() {

this.engine.run();

this.wheel.run();

console.log('run car...');

}


module.exports = Car;


car无需知道enginewheel的具体所在以require进来,也无需知道enginewheel什么时候实例化以调用run方法跑起来,一切都变得如此简单与美好!

  1. 去除了enginewheel的直接依赖,随便enginewheel叫什么名字,写在哪里(甚至可以是一个remote对象),重构变得轻而易举

  2. 想对car进行单元测试,只需要依赖注入一个mockenginewheel对象即可完成,再也不需要直接修改car或者enginewheel的代码了


IoC发挥作用

本文通过Bearcat所提供的IoC容器来让IoCNode.js中发挥作用。


Bearcat IoC 使用非常简单,只需要提供一个简单的配置文件即可让IoC容器管理下的系统运转起来。


更多精彩内容,请点击阅读原文。


 
InfoQ 更多文章 Facebook如何实现PB级别数据库自动化备份 学术派Google软件工程师Matt Welsh谈移动开发趋势 Spotify为什么要使用一些“无聊”的技术? 妹纸们放假了,汉纸们做啥? 大多数重构可以避免
猜您喜欢 Multidex解决方法数越界 301真想说...... 10步成为专业iOS开发者——从零起步 | 干货 上海 Android Wear GDG&eoe同城活动火热报名中! 浅析 Android 打包流程