KEMBAR78
Organizing JavaScript | ODP
Modules in JavaScript
Or How to Break Your Code
(Into Little Pieces)
A Talk by Michael Cordingley
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
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
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.
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!
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
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!
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.
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
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
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
Logical Modules
●

Where do your objects, functions, and variables all live?
–

Hint: Not in the global namespace.

–

I'm not lying this time!
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
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
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
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
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”
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?
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
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
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
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
Thank You
●

This talk can be found in article format at:
–

http://michaelcordingley.me/articles/when-spaghetti-overflow

Organizing JavaScript

  • 1.
    Modules in JavaScript OrHow to Break Your Code (Into Little Pieces) A Talk by Michael Cordingley
  • 2.
    Module Types ● Modules aresometimes 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 ofStructure 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 yourcode 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 ● ● Itisn'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 likerequire.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 ● ● ● Updateyour 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 inthe 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 doyour 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 ApplicationObject ● 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 isgreat! 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 ApplicationObject ● 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 doI 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 ● Reducecomplexity – 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 talkcan be found in article format at: – http://michaelcordingley.me/articles/when-spaghetti-overflow