Development Using Namespaces
Pros, Cons, Myths and Hypesteria
Using global Namespaces for web development is a long forgotten practice, banished, cursed and buried deep under tons of senseless hype. In this post I will try to provide an overview of the pros and cons in using Global Namespaces. How the development workflow compares to the Module Definition Patterns* and debunk a few myths and notions that exist about this matter.
If you are on the go, just skip to the take-aways, otherwise buckle up, it's gonna be a rough ride.
window object. Every
var declaration performed in the global context will create the variable under the
window object, making it available globally.
Developing using the namespacing pattern implies that you take advantage of this feature and create a single huge object that contains all the parts of your application.
IIFEs and single global variables may work fine for applications in the small to medium range, however, larger codebases requiring both namespaces and deep sub-namespaces require a succinct solution that promotes readability and scales. I feel this pattern achieves all of these objectives well.
Debugging Using Namespaces
Development with namespacing patterns enables you to observe any part of your code from your Browser's console.
I don't want to expose the internal methods and variables!
Sure! Your development environment, has nothing to do with how your application will eventually be served to the end-client. You can feel free to expose everything during development and be rest assured that you won't be exposed. After your application is built, add one more simple step to wrap your bundled code in an IIFE, whoop nothing exposed!
Testing Using Namespaces
No one can argue against testing your code. Quite the contrary actually, we have been blessed with so many testing suites and tools that it's like living in heaven! There are all sorts of test types and diving into them is beyond the scope of this article. I will however pick two distinct types that I find to serve a specific and very useful role, TDD and BDD tests.
I perceive Behavioral Driven Development (BDD) as the kind of tests that will run against your development and your production code. They examine the API or functionality that is exported using any means possible (faking DOM elements, mocking, stubbing, etc).
Test Driven Development (TDD) or Unit Tests run only against your development code. They test components and parts of your application that are not exposed and most typically are the core building blocks of your app. Unit testing requires a very isolated environment so they can test the smallest possible unit of your code. Achieving that isolation is the most challenging part of testing.
A challenge that namespaces have absolutely no problem with.
Performing the same with the AMD pattern can prove quite a challenging task. Jamison Dance makes a very good job at describing what your options are for testing AMD modules in this Jul 2012 post, following up on that here is a comment that gives the state on Feb 2013.
Every third-party library exposes its API through a global variable. So requiring those libraries is as simple as referencing their namespace, ie
jQuery. To my disappointment, there is a notion between edge developers to let go of the Global namespace alltogether and only expose the API of their libraries by using the Universal Module Definition. You can easily tackle these unfortunate situations by creating a thin module definition:
Admittedly, the biggest pain when working with namespaces is the verbosity. Typing
myApp.user.auth.plugin.twitter.isAuthed(); is not so sexy. The solution to this problem is shortcut assignment. While the exact implementation can vary, what you can do is shortcut assign frequently used parts of your code to more convenient namespaces:
Myths, Drugs and Hypesteria
Let's debunk a few myths, you will get annoyed, it will be fun.
Modules, Common and Asynchronous
Modular programming is a software design technique that emphasizes separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality. 1
There has been a huge misunderstanding about what modules are, what is modular programming and what a module loader is. It is sad but true, but in the JS community, the words file and module have become a synonym.
Modular Code !== Module Definition
- Writing Modular Code does not require that you use any Module Definition Pattern, CJS or AMD (or even harmony for that matter).
- Module (file) loading is something that you only need during development. In production your codebase goes through a build process that bundles and minifies your code into a single pact file, the Built-Module.
- Every third-party library you consume can come in any possible format (AMD, CJS, Namespace) and you will consume it nonetheless.
- You will also include any third-party dependencies in your production bundle file.
Sooo, why do our visitors need an extra stack (AMD) being transported over the wire? Well, it's all about the convenience of File (module) loading while developing. If it wasn't for the loader's functionality, it wouldn't make much sense to use any Module Definition Pattern in web development.
One could argue that you may want to lazy-load Built-Modules on production. Yes. That-is-what-module-loading-actually-is. If and when you reach to that set of problems, you will soon realize that the Module Loading part is the least of your concerns.
Global Namespace Pollution
namespaces are so 2005 – AMD modules (RequireJS, curl.js, etc) solves the global conflicts and also helps to keep the code organized into small reusable blocks
The global namespace pollution scare is the most hilarious of them all. It is exactly like the stories our moms told us that strangers will put drugs in our drinks to get us addicted and then we'll end up being crack-whores. In the same night.
Seriously now, when was the last time you ever had a namespace collision problem? Think really hard when this happened. If it ever happened and how much time it took you to find out about it and resolve it. I dare say that I never had such an incident. Should such an incident ever appear, the problem would be so obvious that it would require no more than 10 minutes to resolve.
Now please take a moment to consider the moments you found yourself in frustration using AMD on the browser. How much time did you spent to consider yourself an expert? Is your web development workflow flowing effortlessly? Or do you have to deal with an occasional AMD mishap every now and then? Really, take a moment on this and draw your own conclusions.
ES6 will support modules!
Yes. It will and it will be awesome! But again, don't confuse files with modules. At the end of the day, you will bundle and minify your library one way or another. You library will become a Built-Module to be consumed by other libraries or served as the end product to the end-consumer. What your library ends up exposing as a whole has nothing to do with how your library is structured.
It is either Modules or Namespaces
Actually no. That's not true for either. There is nothing stopping you from declaring a global variable within a Module Definition. It definitely is not advised, but it happens. I have seen it in every large setup (i.e. a company's codebase). On the other hand using Namespaces does not prevent you from exporting your API via a Module Definition. UMD does a very good job at that to use as boilerplate for your library.
The Take Aways
These are the take-aways from this article...
- Modern day build flows provide the developers with unprecedented freedom and power.
- The development environment is decoupled from production.
- Module Definition Patterns and Module loading are two different things.
- Modules !== Files
- Modular Programming is not a trademark of AMD, CJS or any Module Definition Pattern.
- Developing using Namespaces will greatly enhance your productivity, maintainability and scalability.
- Namespaced applications and libraries are easier to test and debug.
Now you can eat me.blog comments powered by Disqus