can think of scope as the world a particular line of code can see. In
var keyword for a variable, that variable
applications intentionally use global variables to organize the system.
Alternatively, a better pattern has emerged in which modules are used to access
the other parts of the system. At first glance, this appears to be similar to an
import in Java, a
#include in C/C++, or a
require in Ruby. But there is a
a scope that can hold state which is shared between all consumers of that
libraries. The application used a framework that allowed for the creation of
controllers and views. When a controller was defined, it was attached to the
global scope by, in effect, omitting the
var keyword. If this controller
variable to access it. The use of globals tightly coupled the system together in
ways which made it hard to write new code using test-driven development. The
tests would need to mock out all of the globals accessed by the code under test.
After working with the system for a couple of months, it was apparent to us that
this two year old application felt like it had four to five years of technical
The good news was that we were not the only ones who felt this way. While the
framework was firmly entrenched in the application, the team began to chip away
at the globals and the whole approach that encouraged creation of these globals.
The first step was adding asynchronous module definition to the frameworks
dependency management function with
require functions. We took
this old school code:
And converted it to:
Here SubjectController is defined by subject_controller.js. This makes it trivial to define SubjectController as a mock. However one of the problems is that now the mock has replaced the SubjectController for the entirety of the scope. Having to put all the tests that depend on the mock in one file and the other tests in a different file seemed like a serious limitation, particularly when one might want to use different mocks for the same module.
In response, the team added a
factoryFor function that would behave like so:
Now if subjectcontroller.js_ depends on modules like so:
We can, with the factory, inject our own definitions for these modules:
While these examples are simple, they are obfuscating some aspects. So lets rewind and see a practical example.
The point of this code is to check the web browser engine and version. The code
in browser.js is a slightly modified version of the deprecated jQuery.browser.
Remember the part about how modules are basically shared scope? We can see this
in browser.js, because any consumer of the module is going to get the exact same
instance as the first consumer. The first time the code is consumed, lines 3-13
are executed. These extract the engine and the version. The scope within the
module now has engine and version defined. All consumers after the first will
have only the return value supplied to them. This return value is an anonymous
version methods. These methods are run within the
scope of the module so they will of course have access to the already set
Moving on to the test, it becomes clear that we need to be able to inject a
userAgent string that typically would be accessed from the current browser via
navigator.userAgent (as it is done on line 3 of browser.js). After getting the
browser, we inject jQuery and a known userAgent string for
Internet Explorer 10.