Post on 01-Nov-2014
description
transcript
Building Rich User Experienceswithout
JavaScript Spaghetti
by Jared Faris
@jaredthenerd
jaredthenerd.com
About me
Traditional Web Development
Web assets are created last to glue together things.
Stakeholders, architects and developers define the
“real” application.
The application is built model first (from the DB up).
Traditional Web Development
The design is focused on making the CRUD pretty, not
usable
The design of the UI/UX happens in Photoshop... if it
happens at all.
Most of the application is just CRUD.
We have a widgets
table
We need a
widgets
screen!
Traditional Web Development
“Advanced” web developers write lots of unorganized
bits of jQuery.
Most user interactions result in lots of POSTS back
to the server.
JavaScripts are something someone download from
hotscripts.com.
We have a widgets
table
We need a
widgets
screen!
Make sure you
add a date picker
And a lighbox!
JavaScript: Not a “Real” Language
Patternless design.
Built as a glue to bind pieces together, not as a core
component of the application.
Not thought through like server-side code.
Not Real? Why?
A lot of development tools traditionally hid the JS behind
configurable controls.
Libraries like jQuery make it really easy to pile on lots of
little events.
JS used to be a tool for doing image rollovers.
Is That A Problem?
In a workflow-based application it falls apart.
For form-based apps that was mostly fine.
Customized, reusable controls and a modular
application design needs something more.
Questions So Far?
A Typical Product LifecycleSomewhat dramatized...
Designer Developer
We need this
feature
I got this
?
Tweaking time...
I got another
great idea
Now you tell
me
The developer bolts on some more code
And another
thing...
grrr
We don’t
‘really’need this
Uh, yeah we
do
The developer bolts on some more code
Some time passes
‘Some time’ is defined as:
Just long enough that the developer doesn’t remember
exactly how his original code works.
I’ve got a new
feature
Angry developers
can really do this.
IT managers be
warned.
Protective Beret
More messy code
The last bug
Oh wait, one more
Finally
(14 tests ought to be enough for anybody)
The next day...
Two weeks pass.
I’ve got a new
featureGahh!
No developers were harmed in the making
of this dramatic reenactment.
Poor design patterns
+ crappy code
= JavaScript spaghetti
Why does this happen?
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*
* Or at least it used to
This really all boils down to one thing.
We developers suck.
Three JavaScript Principles
Push events, not state
Write small, discrete bits of code
Decouple everything
Decouple Everything
Apply your OO best practices here too.
Remove dependencies between objects.
Start thinking about UI pieces as individual JS objects.
Small Chunks Of Code
Even if you don’t test everything, learning how to
write testable code means learning
how to write better code
Put the rest of the stuff in classes that you can test.
Separate DOM dependent stuff into a single layer.
Push Events, Not State
Inform other controls that “X happened to Y”,
not “Y is in X state”
Let controls worry about their own state.
Know about the Law of Demeter.
Writing Better JavaScript
Find the tools that make your life easier.
Use the design patterns you already know.
Leverage language features whether JS has them or not.
Language Features
Keep state inside of the objects and expose methods.
Objects have state and behavior.
JavaScript loves its objects. Create them to represent
page elements.
Language “Features”
Consider using namespaces.
JavaScript Namespacing
Language “Features”
Use inheritance or faux subclassing.
Consider using namespaces.
JavaScript Prototyping
Coffeescript Classes
Language “Features”
Pass JSON around asynchronously.
Use inheritance or faux subclassing.
Consider using namespaces.
Design Patterns
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
NavControlMediator
itemSelected()
Events from some
other object
unselectAll()
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()
NavControlMediator
itemSelected()
Events from some
other object
unselectAll()
viewModel
Tools & Frameworks
Knockout
Magic.
Setup a template with some markup binding it.
Setup a JavaScript object with some KO code.
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.
Backbone
Views help you control the visual rendering.
Routers help you organize page flow.
While KO is Model < > View magic, Backbone is structure.
Models help you keep track of state.
Backbone Use Case
What about all the other
frameworks?
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.
Way Too Much Pubbing and Subbing
Service Bus
Your controls are then only coupled to a single thing.
Controls that want to communicate speak through it.
A service bus is another layer that sits outside controls.
Postal.js
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.
NavControlMediator
itemSelected()
Events from some
other object
unselectAll()
viewModel
ReportMediator
itemChanged()
unselectAll()
viewModel
Service Bus
NavControlMediator
itemSelected()
Events from some
other object
unselectAll()
viewModel
ReportMediator
itemChanged()
unselectAll()
viewModel
Service Bus
HistoryControl
Service Bus
TeamControl
Gets team changed
message, makes AJAX
call for this team’s data,
rewrites team with template
No view model
Service Bus
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.
Underscore
Underscore
Underscore w/ Coffeescript
What Else?
I don’t have a third bullet point here
Browser Debuggers
Templates
A Typical Product LifecycleRound Two
We need this
feature
I got a few
questions
?
Tweaking time...
I got another
great idea
Ok, Cool
And another
thing...
Done.
Two weeks pass...
I’ve got a new
feature
No worries.
Wha? Ohhhk.
A short time later...
Examples
Questions?
Special thanks to
He did the frame art
Blame me for
everything else
My Stuff@jaredthenerd
jfaris@gmail.com
https://github.com/jaredfaris
http://jaredthenerd.com