Genislab builds better products and faster go-to-market with Lean project man...
Organizing JavaScript
1. Modules in JavaScript
Or How to Break Your Code
(Into Little Pieces)
A Talk by Michael Cordingley
2. Module Types
●
Modules are sometimes
misunderstood
–
●
File Modules
–
Confusion in naming
Each piece of code to
its own file
They come in different
flavors
–
File
–
●
●
Logical
In an ideal world, the two
overlap 1:1
●
Logical Modules
–
Each piece of code to
its own predictable code
location
3. The Cost of Structure
Three different difficulty
levels
–
Different trade-offs of
fixed versus variable
costs
Complexity vs. Scale
Project Complexity
●
Project Scale
Simple
Moderate
Complex
4. File Modules
●
Break your code out into separate files
–
●
●
Ideally, one file per idea
Files should be small and logically arranged on the filesystem
Don't forget about production!
–
Files need to be concatenated and minified as part of
your build process.
5. File Modules – Simple
●
●
If a project uses very little JavaScript, throw it it all into a
single file for each page.
Didn't you just say one idea per file?
–
●
It's more maintainable to have everything in one place, if that
place isn't too cluttered.
–
●
I lied.
We only need organization schemes when we have too
much.
When starting a new project, START WITH THIS ONE unless
you have good reason to do otherwise!
6. File Modules – Moderate
●
Break code out into separate files and load them each with
a script tag.
–
●
Don't forget to bundle these into a single file that gets
loaded as a giant blob for production
Doesn't this get hard to keep up with all of the
dependencies?
–
Only if you have several files
–
Most projects never reach that scale
7. Transitioning to Moderation
●
●
It isn't a clean break
Just start pulling your nouns out into separate files as your
project acquires them
–
–
●
These are probably reusable across pages anyway
Pulling them out also encourages you to write a clean
interface
If you page script exceeds 200 lines, you probably have
lurking nouns, or at least some code that could be DRYed
out.
–
Please don't wait this long!
8. File Modules – Complex
●
So you went for the moderate route and now you're
drowning in files?
–
●
Time to level up.
Pull in a formalized way to load and compile files
–
require.js
–
yepnope.js
–
etc.
9. Caveat Emptor
●
Things like require.js are geared more for single-page
apps than for multi-page apps
–
Most of your projects are probably multi-page apps
–
You're probably only drowning in JS files if you have a
single-page app
–
require.js becomes painful very quickly if you want to
use it on a multi-page app
10. Transitioning to Complexity
●
●
●
Update your file module to conform to your module-loader
of choice
Update every usage of that module to be loaded with the
module-loader
Don't forget the whole concatenation/minification thing
–
This is where the pain ramps up
–
You need to define blobs
●
Separate bundlings of code that load together
11. File Modules in the Future
●
ECMAScript 6 (Harmony) will bring native modules to the
language
–
Shim:
https://github.com/ModuleLoader/es6-module-loader
–
Despite the shim, this is not yet ready for general
consumption
●
The spec isn't finished yet
12. Logical Modules
●
Where do your objects, functions, and variables all live?
–
Hint: Not in the global namespace.
–
I'm not lying this time!
13. Logical Modules – Simple
●
Just keep 'em in your page script
–
●
If you haven't broken it out into its own file anyway, it
probably isn't very big or very complicated
Pull it out into a logical module at the same time that you'd
pull it out into a file module and for the same reasons
14. Logical Modules – Moderate
●
OK, so it's out into its own file
–
Don't make it a global!
–
Projects get cluttered this way
It needs a home that is globally-accessible
●
●
●
It may be an object that you reuse across pages
It may be repeated functionality
– Like enhancing your site navigation
15. Introducing the Application Object
●
Make a global
–
–
●
But only one!
For now, it's just an object literal
Call it “App” or the name of your project: “FooBarFighters”
–
No, I'm not actually familiar with their music
–
Yes, the puns are always intentional, even when bad
16. Application Object – Continued
●
Attach your modules to this object
–
–
●
e.g. App.Navigation, App.Forms, App.InstantiableObject
Submodules go as properties on their parent modules
If your module needs initialization, add an “init” or
“initialize” method to it.
–
–
●
e.g. App.Navigation.initialize();
This is responsible for calling submodule intializers
If you have modules that need initialization, also have an
“App.initialize();” method that gets called on DOM ready
17. Application Object – Finish
●
This application object can and should be broken out across
multiple files.
–
The “App.initialize()” method saves you from having to
worry about the order in which they load
The Application object just comes first
Don't forget about “this”
●
●
–
Useful to avoid having to bake the full module name into
functions that use other functions
–
e.g. Inside of “App.Navigation.initialize()” “this” is
“App.Navigation”
18. The Catch
●
“This is great! Everything is cleanly separated out into its own
place, but I need to load a module after the page load and
then initialize it.”
–
●
“Oh yeah, and I don't know if it'll have loaded before the
Application starts or not.”
–
●
OK.
Um, K.
“And this other piece needs to run only (before|after) the rest
is all set up.”
–
…why are you doing this to me?
19. Logical Modules – Complex
●
Introducing the Application object!
–
●
But this time, it's a real, instantiated object
“var App = new Application();”
–
You could write the definition of “Application” yourself,
but it's best not to
–
We'll get to that
20. The New Application Object
●
When a new module gets loaded after the application has
started, this will automatically start it.
–
●
Otherwise, it'll wait until the application starts
It also publishes events
–
–
●
So you can run code just before and just after the
application starts
It even doubles as a free event bus
The modules also get events
–
Same deal as the Application
21. And where do I get this?
●
What, you don't want to reinvent the wheel?
–
●
Fine, here it is:
https://github.com/marionettejs/backbone.marionette/blob/m
“But, I don't use or want Underscore, Backbone, and the
whole rest of Marionette!”
–
Jeez, you're picky.
–
https://github.com/mcordingley/Appliance
22. The End Goal
●
Reduce complexity
–
Whenever you introduce a new organizational tool,
make sure it reduces project complexity
–
Use the simplest scheme you can get away with
–
Make things as easy as possible for anyone who has to
maintain your code after you've left it behind
23. Thank You
●
This talk can be found in article format at:
–
http://michaelcordingley.me/articles/when-spaghetti-overflow