The document discusses how JavaScript code can become messy and difficult to maintain over time as new features are added in a rushed manner without proper architecture. It advocates applying object-oriented principles like decoupling components, making components testable, and pushing events rather than state changes. Specific patterns like mediator, observer and service bus are presented as ways to better structure JavaScript code and avoid spaghetti code as an application evolves.
6. A Developer’s Problem
Building a great user experience is hard.
It’s even harder to build them so that they can
grow painlessly.
Developers are the only people in the
organization that wear every single hat.
Friday, June 29, 12
7. Problem (part 2)
JavaScript lends itself very well to building really
horrible code that doesn’t scale. At all. Ever.
Friday, June 29, 12
8. A Typical Product Lifecycle
Somewhat dramatized...
Friday, June 29, 12
23. Some time passes
‘Some time’ is defined as:
Just long enough that the developer doesn’t remember
exactly how his original code works.
Friday, June 29, 12
35. No developers were harmed in the making
of this dramatic reenactment.
Friday, June 29, 12
36. Additional Features + Short Sighted Architecting
= Horrible JavaScript Spaghetti
Friday, June 29, 12
37. Why does this happen?
This is where you earn audience participation points.
Friday, June 29, 12
38. Some Reasons
• JavaScript isn’t real code
• We don’t treat client side things as real features
• We can’t easily test it
• We don’t like writing it
• It behaves differently in different browsers
Friday, June 29, 12
39. This really all boils down to one thing.
We developers suck at JavaScript.
Friday, June 29, 12
40. Three JavaScript Principles
• Decouple everything
• Make it testable
• Push events, not state
Friday, June 29, 12
41. Decouple Everything
Start thinking about UI pieces as individual JS objects.
Remove dependencies between objects.
Apply your OO best practices here too.
Friday, June 29, 12
42. Make It Testable
Separate DOM dependent stuff into a single layer.
Put the rest of the stuff in classes that you can test.
Friday, June 29, 12
43. Push Events, Not State
Know about the Law of Demeter.
Let controls worry about their own state.
Inform other controls that “X happened to Y”, not “Y is
in X state”
Friday, June 29, 12
45. OO
• Think in terms of classes
• Give behaviors to objects
• Keep state inside of objects
Friday, June 29, 12
46. Mediator Pattern
"The essence of the Mediator Pattern is to "Define an
object that encapsulates how a set of objects interact.
Mediator promotes loose coupling by keeping objects
from referring to each other explicitly, and it lets you
vary their interaction independently."
-Design Patterns: Elements of Reusable Object-Oriented Software
Friday, June 29, 12
47. NavControlMediator
itemSelected()
unselectAll()
Events from some
other object
Friday, June 29, 12
48. Observer Pattern
"Define a one-to-many dependency between objects so
that when one object changes state, all its dependents
are notified and updated automatically."
-Design Patterns: Elements of Reusable Object-Oriented Software
Think jQuery $(‘.something’).click()
Friday, June 29, 12
49. NavControlMediator
itemSelected()
viewModel
unselectAll()
Events from some
other object
Friday, June 29, 12
51. Pub/Sub + Fairy Dust = Service Bus
Pub/Sub is great to make sure events propagate.
It starts to get brittle with lots of different controls.
Friday, June 29, 12
52. Way Too Much Pubbing and Subbing
Friday, June 29, 12
53. Service Bus
A service bus is another layer that sits outside controls.
Controls that want to communicate speak through it.
Your controls are then only coupled to a single thing.
Friday, June 29, 12
55. Service Bus + Mediator
• Controls no longer need to know about others.
• We can remove/replace controls individually.
• We can add controls that listen to the same events
without modifying the publisher.
• We can re-use pieces more easily because they work
in a standard way.
Friday, June 29, 12
56. NavControlMediator
itemSelected()
viewModel
Service Bus
unselectAll()
Events from some
other object
ReportMediator
itemChanged()
viewModel
unselectAll()
Friday, June 29, 12
57. HistoryControl
NavControlMediator
itemSelected()
viewModel
Service Bus
unselectAll()
Events from some
other object
ReportMediator
itemChanged()
viewModel
unselectAll()
Friday, June 29, 12
58. Service Bus
TeamControl
No view model
Gets team changed
message, makes AJAX
call for this team’s data,
rewrites team with template
Friday, June 29, 12
78. A KO Warning
It’s really easy to go overboard with KO events.
I prefer to use KO for the VM binding (observables and
computeds) but rely on jQuery for events.
jQuery’s .on() binding and a good understanding of ‘this’
makes for much cleaner events.
Friday, June 29, 12
79. Easy Testing
Try to have layers of your application’s JS that don’t
touch any HTML elements.
Store data in models inside individual controls and test
that published messages change the state of those
models correctly.
Friday, June 29, 12
82. NavControlMediator
itemSelected()
viewModel
Service Bus
unselectAll()
Events from some
other object
ReportMediator
itemChanged()
viewModel
unselectAll()
Friday, June 29, 12
83. Tools Make This Easier
Underscore.js
Coffeescript
Templates
Friday, June 29, 12
84. Knockout.js - Observer pattern (pub/sub)
http://knockoutjs.com/
http://learn.knockoutjs.com/
Postal.js - Service bus
https://github.com/ifandelse/postal.js
http://freshbrewedcode.com/jimcowart/2011/12/05/client-side-messaging-with-postal-js-part-1/
http://www.jaredthenerd.com/2012/01/using-postaljs-for-client-side.html
Patterns
http://arguments.callee.info/2009/05/18/javascript-design-patterns--mediator/
http://msdn.microsoft.com/en-us/magazine/hh201955.aspx (Pub/Sub)
Friday, June 29, 12
85. Rate Me
http://spkr8.com/t/12731
My Stuff
@jaredthenerd
jfaris@gmail.com
https://github.com/jaredfaris
http://jaredthenerd.com
Friday, June 29, 12