SlideShare a Scribd company logo
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
IDIOMATIC EMBER
Finding the Sweet Spot of Performance & Productivity
・ D O C K YA R D ・
• hi everyone!
• today i want to share some ideas with you about how
we can write idiomatic ember apps that are both
performant and productive
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
bit.ly/idiomatic-ember
• if you can't see the slides clearly, you can look them up
on
• bitly idiomatic dash ember (repeat it)
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• but first with a heavy heart, let's address the elephant
in the room –
• what's an idiomatic talk without idioms?
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• they say time is money
• so i'm gonna just cut to the chase
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
🐰 LAUREN TAN
SUGARPIRATE_
POTETO
• my name is lauren, and i was born in the year of the
rabbit
• you can find me on the interwebs as sugarpirate or
poteto on github
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• when i'm not working on client work or open source, i
sometimes play final fantasy 14
• it's a game that can be quite addictive, but thankfully i
have
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
🐶 ZELDA
• a little puppy Zelda who keeps me grounded in reality
• unfortunately she couldn't be here today to give this
talk, so you'll have to listen to me instead
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
I WORK AT
DOCKYARD
• a year ago i was still living in australia
• but i moved to Boston last year to work at DockYard
• we work on a ton of Ember and Elixir apps as well very
many open source libraries including ember addons
• in 2 days it will be the end of my 1st year at dockyard,
and i have to say that it's been one of the best jobs i've
ever had
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• the best part is, we're hiring senior ember engineers
• so please talk to me, brian, marten or estelle later if
you're interested in finding out more
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• and if you come speak to me after my talk, i'll give you
a very limited edition sugarpirate sticker!
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
THE STATE OF
JAVASCRIPT IN 2016
• now before we start talking about ember, let's look at
what it's like to build a modern javascript app in the
year 2016
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• react has been steadily gaining ground and
mindshare
• and for good reasons
• some of its ideas have even made their way into ember
and other frameworks
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• but despite how far we've come from our early days,
modern web dev is getting really hard
• i mean, it used to be so simple, right?
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• in the Good Old Days™, all you had to do was write some
html, maybe some css, slap some jQuery on a page
• and even use a plugin or 5
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• but these days we spend so much time configuring
things
• and we spend valuable time writing glue code instead
of working on what matters
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• you have to make a ton of choices for your front end
stack
• which can be quite paralyzing
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
leftpad
• & its easy to build a tangled web of dependencies
• which can lead to all sorts of problems…
• <dramatic pause> 🙃
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
“I hand-rolled my own
front-end stack using the
most organic, gluten-free
and artisanal micro-
libraries.”
🤓
• it's tempting to fall victim to javascript hype
• and try to build your own makeshift framework
• that might end up slowing you down bc you have to make
sure everything plays nicely together
• why go through that pain?
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• but that's why we use an opinionated framework like
ember, right?
• with ember, we opt into convention over configuration
• problems are shared across the community
• bc chances are, your app isn't a special snowflake
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Performance Productivity
• these strong standards have given the ember community
hands down the best tooling experience available
• we have things like ember-cli, the ember inspector, more
than 2,000 addons, which is an incredible number
• and all of this would not have been possible without the
community
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
❤❤
• and i think it's fair to say that ember has one of the most
welcoming and friendly communities out there
• our slack channel is always active, and getting help is easy
• there are a few people in there that don't seem to sleep
• so if you have a question, there will almost always be
someone available to help you out
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
THE EMBER WAY?
• because ember is opinionated, it also means there is
an "ember" way of doing things
• instead of rebuilding the wheel and inventing your own
abstractions
• we leverage the community's exp in building web apps
• with ember 2.0 being released last year in august, quite
a few things have changed since then
• changes are main motivation for talk
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Data
Component
Owner
Action
• for example, there has been lots of discussion around
data down, actions up
• this is a pattern for one way data flow that we adapted
• and is meant to make your apps easier to reason about
& maintain
• i'll cover this more in detail later
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• we've also established conventions that singleton
state should live in services instead of controllers
• services are excellent for handling the long lived state
of things such as shopping carts, activity feeds and
notification messages
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
this.attrs.fooAction(val);
this.get('fooAction')(val);
VS
• actions have been getting a little confusing lately
• with the future introduction of glimmer components
• these action calls will be subtly different, although
they may appear to be the same right now
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• we also know that controllers are going away in the
future
• i'll talk a little more about what that means and share
some techniques you can use to ease the transition to
routable components
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• in a nutshell, things have changed
• and dealing with change can be hard
• these changes can be diff to deal with bc
• things that used to be best practices may no longer be
true
• and lack of updated info about new way of doing
things
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
MORE JAVASCRIPT
• going forward, we can expect to see Ember become
more closely aligned with JavaScript, and for things to
become more explicit and less magical
• ES2017 features and beyond are going to play a pivotal
role in Ember's future
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
DECORATORS
Stage 1
https://github.com/wycats/javascript-decorators
• for example, you can already use decorators today
using rwjblue's excellent addon
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
https://github.com/rwjblue/ember-computed-decorators
@computed('first', 'last')
name(first, last) {
return `${first} ${last}`;
}
• this is currently a stage 1 proposal, but is incredibly
useful for DRYing up your code
• the most obvious example is with CPs, as you can see
this is much nicer than what we have to do today
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
ASYNC/AWAIT
Stage 3
https://github.com/tc39/ecmascript-asyncawait
• async/await functions are also on the horizon, and are
1 stage away from becoming included into the spec
• these let us write asynchronous operations as if they
were synchronous
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
await fillIn('.display-title', 'Hello!');
await click('.update-display-title');
assert.equal(find('.display-title').text(), 'Hello!');
https://github.com/emberjs/rfcs/pull/119
• if you ever been trolled by Promises and async
programming, you'll love this new feature
• for example, in rwjblue's RFC for making tests great
again, he describes how we might make use of async/
await to clean up tests
• as a result, code & tests are much easier to read and
follow
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
GENERATORS
ES2015
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
• generator functions are already a part of es2015
• and are really cool
• they allow you to write co-operative code – you can
pause, resume and restart them as well as end them
early
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
countingTask: task(function* () {
this.set('count', 0);
while (this.get('count') < 5) {
this.incrementProperty('count');
yield timeout(300);
}
this.set('count', 'DONE!');
}).restartable()
https://github.com/machty/ember-concurrency
• these are really powerful, and you should definitely
checkout Machty's addon called ember-concurrency
• it allows you to write Tasks to do things you would have
a hard time replicating without generator functions
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
❤
• as you can see, when you use Ember, you're betting on
JavaScript
• we're going to become even more closely aligned with
the latest JS features, meaning that you'll be able to
write more JavaScript and less Ember
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
– Yehuda Katz
“All good ideas will eventually
end up in Ember.”
• i think it's fair to say that ember is the solution to
javascript hype fatigue
• and that is why i'm excited to give this talk, bc with
ember, we don't have to sacrifice performance for
productivity
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
THE EMBER WAY 🙏
• so in this talk, i want to cast away any doubt you might
have about what the ember way really is
• and hopefully you'll take away some useful ideas you
can use straight away in your apps
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
I. Data Down, Actions Up?
II. Controllers are Dead
III.Declarative & Composable Templates
• very broadly, i'll be speaking about patterns and anti-
patterns in modern ember apps
• first, i want to talk about an important concept
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
I. Data Down, Actions Up?
II. Controllers are Dead
III.Declarative & Composable Templates
• data down actions up is one of the core principles
driving modern ember apps
• by architecting our applications in this manner, we can
build apps that are easier to maintain and reason about
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• data down, actions up describes flow of data thru
app
• eg this is what app might look like once routable
components land
• fetch data from API, which gets normalized and
pushed into ED store
• records then get passed in as attrs to routable
component
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• you might have noticed controllers were missing
from that diagram
• and that's because they're going to be deprecated and
removed in the future
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Is MVC Dead? ☠
• but why remove controllers if they already work?
• well, core team found that a component could easily
take the place of a controller + view, as components
are superior implementations
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Is MVC Dead? ☠NOPE
• does this mean the death of MVC?
• no, but there has been a lot of confusion on this topic,
so i'll address it in more detail later
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
2 WAY BINDINGS 💣
• what React taught us is that the biggest problem of
the frameworks that predate it is the very thing that
made them popular
• and that is two way bindings
• implicit changes are hard to reason about, and
• you can very easily cause an infinite cascade of
changes if you're not careful
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
💎
• when glimmer or angle bracket components land,
data bindings will become one way by default
• and instead of mutating data, we will have to send
actions to update it
• this becomes a nice, functional way of building
applications that are still reactive
• and easier to reason about
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• by ignoring 2 way bindings and instead re-rendering
multiple times efficiently, we can have changes
propagate immediately without introducing all the
cascading semantics of a 2 way bind
• and this is made possible with one way data flow and
making renders pure and idempotent
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Who owns the data?
• with DDAU, a guiding principle is to ask who owns
the data
• only the owner should be allowed to modify it
• this is particularly important when that data is
application state, which we should strive to keep as
single sources of truth
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Component A
Component A.1 Component A.2 Component A.3
Route
Owns the shared
state of A1 - A3
• for example, here's a diagram of what a simple ember
app might look like on a given route
• lets say Component A only allowed to show 1 child
component at a time
• perhaps after doing some config in a child component,
we need to programmatically show the next one
• where would the best place be to do that?
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Component A
Component A.1 Component A.2 Component A.3
Route
Owns the shared
state of A1 - A3
{{component configComponent user=user changeStep=(action "changeStep")}}
• if we follow the DDAU principle, we need to ask
ourselves – "Who owns the data?"
• In this case, which config component to render is the
concern of Component A, it owns the shared state of
all its children
• so, in order to mutate the current step property, we
should send an action up to Component A
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
{{component configComponent user=user currentStep=currentStep}}
// don't do this in the child component!
export default Component.extend({
actions: {
next() {
set(this, 'currentStep', 'configure-foo');
}
}
});
This is bad ☹
• what we must avoid doing is mutating the
"currentStep" in the child component
• it's a subtle difference, but it means an app that is
easier to reason about and maintain
• you won't need to spend hours figuring out who is
changing what
• because you know there is only one place it is being
changed
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
…or someone else's state!
• but the action is changing the property anyway, why
not just do it directly?
• when you change the state that someone else owns,
you're stealing
• effectively it means that the owner no longer controls
the data and you have bypassed the owner's interface
• however, in the future these problems will likely go
away
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
<configure-username user={{user}} currentStep={{currentStep}}>
...
</configure-username>
• Glimmer Components will be 1 way by default
• so even if you tried mutating `currentStep` in the child
component, it would not flow up to mutate the
currentStep prop of the parent component
• unless you explicitly opt-in to doing so with the `mut`
helper
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
export default Service.extend({
init() {
this._super(...arguments);
this.data = [];
}
});
• another thing to note is that services can also own
their own data,
• and this is an important part of the Ember
programming model
• this will be especially useful to know when routable
components land,
• as singleton state must be moved into a service bc
components are stateless
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
I. Data Down, Actions Up?
II. Controllers are Dead
III.Declarative & Composable Templates
• with ddau and routable components coming, what do
we do with controllers?
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• so, as i mentioned earlier
• controllers aren't completely dead yet…
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
ROUTABLE CONTROLLER
• one important thing to note about controllers is that
the concept itself isn't going away
• however, the implementation is changing
• essentially, the concept of a controller decorating a
model still exists, but it is implemented as a routable
component instead
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
export default Controller.extend({
queryParams: ['category'],
category: null
});
• you might still need to use a controller right now if you
want to use query params and in certain cases of
bubbling actions
• but these will be moved to the route eventually when
routable components land
• that said, don't get too creative in trying to avoid
controllers, only remove when it makes sense
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
ROUTABLE CONTROLLER
• Ember 1.x was a straightforward implementation of
MVC, we had a controller and a view
• but we've deprecated views in favor of components
• and it turns out that what the controller + view was
doing could be better handled by a component and
service
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
ROUTABLE COMPONENT
• so the routable component was introduced
• the major difference you have to keep in mind is that a
routable component is not a singleton like its controller
counterpart
• but conceptually, they should do the same things,
which is decorate a model
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Component = Controller + View
• a simpler concept is to think of the routable
component as the unification of what we call a
controller and a view
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
<h1>Alpaca Route Template</h1>
<div class="my-amazing-template">
{{#each alpacas as |alpaca|}}
<span>
I'm a cute little {{alpaca}}!
</span>
{{/each}}
</div>
{{foo-alpaca alpacas=alpacas}}
move to
• there are things you can do today to make this
transition easier
• the first key thing you can do is to move your route-level
template into a top-level component
• when routable components land, it basically just moves
that invocation into the route implicitly
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
// shopping-cart top-level component
export default Component.extend({
shoppingCart: inject.service(),
actions: {
remove(product) {
// ...
}
}
});
{{#each shoppingCart.products as |product|}}
<h2>{{product.title}}</h2>
<p>{{product.description}}</p>
<button {{action "remove" product}}>Remove</button>
{{/each}}
• the reason it's a good idea to use a top level
component now is that it forces you to separate your
stateful, singleton logic out and into a service
• a transition to a service for the stateful bits and a
component for the stateless bits is most likely to be
future proof
• and will make the transition an easier one
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Controller
Action
Action
Action
Route
Action
Action
Action
move to
• another thing you can do is to move actions that deal
with data to the route
• these actions are likely better located in the route as
that is where they'll eventually live when routable
components land
• however, actions that deal with UI or presentational
logic should remain on the routable component
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
ACTIONS 🎬
• there are some gotchas with moving controller actions
to your route, so i'll share a way to do so a little later
• but first, let's take a look at actions
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
{{foo-bar submit="submit"}}
{{foo-bar click=(action "submit")}}
• currently, actions can be a little confusing
• for example, you could define a classic action on a
component by giving it a string property of the action
name
• or you could use a new style action
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
New-style Actions 👍
aka Closure Actions
• as a best practice, you should always prefer to use a
new-style or closure action
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
{{foo-bar click=(action "submit")}}
• a new-style action is essentially just a regular
javascript function
• which means you can do things like make use of return
values, partially apply arguments and more
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Classic Actions 👎
aka String Actions
• while classic or string actions are very implicit in
nature
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
{{foo-bar submit="submit"}}
• and make things hard to debug
• for example, it would be easy to mistake submit for a
string property
• and it would be difficult to trace where the action
actually lives
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
this.sendAction('someMysteriousAction', args);
• another thing is when you use classic actions you have
to use `sendAction` in your components
• which is kinda like sending your action to space
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Your classic action
• because you send it up somewhere and hope
something is listening to it
• who knows where it's going
• and the worst part is it never comes back with a return
value
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
get(this, 'submit')(...args);
• on the other hand, new-style actions are awesome
• they're one of my favorite additions to ember and
they've been available since 1.13
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• don't let the word new-style or closure action scare
you
• it's really just a regular javascript function
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
actions: {
saveAndDoStuff(item) {
get(this, 'save')(item)
.then((savedItem) => // do stuff);
}
}
• as i said earlier, you have return values
• these are especially useful when dealing with async
operations like saving a record
• you can return the save promise and then handle it
from inside the component
• e.g. handle success and failure state
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
ember install ember-route-action-helper
https://github.com/DockYard/ember-route-action-helper
• so new-style actions are awesome, but out of the box
you can only use them if they're defined on the
controller as they do not bubble like classic actions
• but if you want to move your actions that deal with data
to the route this seems rather lame
• so rwjblue and i built a little addon you can use today
• it's called the ember-route-action-helper
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
{{foo-bar
value=value
updateFoo=(route-action "updateFoo")
}}
• by using `route-action` in place of `action`
• this lets you have new-style actions that work with
routes, and when the time comes, you can search and
replace route-action back to action
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
SERVICES
• if you recall, controllers without routes can be created,
and it was a common practice to manage singleton
state with them
• a service is a long lived singleton we can use to manage
long lived state
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• a great example for a service is a shopping cart or
activity feed
• for things that have singleton state, you can extract that
logic into a service and then inject it into the objects
you need to
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
export default Service.extend({
init() {
this._super(...arguments);
this.cart = [];
},
addToCart(item) {
// ...
},
removeFromCart(item) {
// ...
}
});
• a shopping cart is an excellent example of a service,
because there can only be one singleton cart in the
application, and it needs to have long lived state
across the app
• you can implement a cart with as little as setting a
property on a service to be an array
• or you could do more
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• what we must be careful about is not to abuse services
• if your main reason for creating a service is to use it as a
global bucket to avoid passing things around, that's a
bad sign
• instead, adhere to data down actions up and don't use
services for something that doesn't need long lived
singleton state
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
I. Data Down, Actions Up?
II. Controllers are Dead
III.Declarative & Composable Templates
• now i want to talk about templating, something i'm
sure is close to all of our hearts
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
{{if (eq fullName "Jim Bob") "You're the chosen one"}}
https://github.com/jmurphyau/ember-truth-helpers
• another of my fav new things in Ember is the new
Helper impl
• introduced in Ember 1.13 and great for expressing
presentation logic
• for example, this `eq` helper can be found in ember-
truth-helpers addon, which we pretty much use for all
our apps
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
{{concat "configure-" configName}}
http://emberjs.com/api/classes/Ember.Templates.helpers.html
• Ember itself also ships with a bunch of useful Helpers
like `concat`, `hash` and the`get` helper
• the best thing about Helpers is that it basically lets you
power up your templates
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
import Ember from 'ember';
export function add([a, b]) {
return a + b;
}
export default Ember.Helper.helper(add);
• again, because Ember is converging towards just being
JavaScript
• a helper is really just a regular JavaScript function
• one of the reasons i like helpers is that it forces you to
keep your functions small and free of side effects
• you can basically create 2 kinds of helpers, this one is a
simple one that will recompute every time the params
change
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
export default Helper.extend({
// ...
});
• for more complex needs, you can also make a class
based helper, which is essentially an ember object
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
export default Helper.extend({
localesService: inject.service('locales'),
currentLocale: readOnly('localesService.currentLocale'),
compute([key]) {
let currentLocale = get(this, 'currentLocale');
return get(this, 'localesService').lookup(currentLocale, key);
},
localeDidChange: observer('currentLocale', function() {
this.recompute();
})
});
• this means you can do things like define CPs, use
services and so on
• for example this is a helper that looks up translations
on a locales service
• specifically you might want to listen for a change in
locale
• and then all the translations should auto-update, even
though the locale itself is not passed into the helper
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• some of you might have noticed i used an observer in
my previous example
• class based helpers are currently the only place it is ok
to use one
• bc it is still a lightweight implementation (almost mvp),
and its lifecycle hooks are not implemented yet
• when those become available, we can use them to
recompute instead
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
export default Component.extend({
isDropdownDisplayed: false,
actions: {
saveUserAndHideDropdown(user) {
get(this, 'save')(user)
.then((user) => {
// do stuff
set(this, 'isDropdownDisplayed', false);
});
}
}
});
• another reason i like helpers is because it means a lot
of UI logic can be moved back to where it belongs
• for example, how many times have you written
something like this?
• this feels a little dirty because it mixes data and UI logic
together
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
export default Component.extend({
isDropdownDisplayed: false,
actions: {
hideDropdown() {
set(this, 'isDropdownDisplayed', false);
},
saveUser(user) {
return get(this, 'save')(user);
}
}
});
• so one thing you could do is to split them up into 2
actions right?
• but now you have a problem, because you can't invoke
them both
• what i'm about to show you demonstrates how
powerful helpers can be
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
<button {{action (pipe saveUser hideDropdown) user}}>
Save and Close
</button>
• let's say we had a hypothetical helper called `pipe`
• it would let you take the return value from 1 action, and
pass it along to the next one
• and it would keep passing that value down to each
function in the pipe
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
A(B(C(D('E'), 'F'), 'G'), 'H');
• if you've used the programming language elixir before,
this pipe helper is essentially the same as the pipe
operator
• the pipe operator lets you express the above, which
isn't very nice to read, as
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
filing =
DB.find_customers
|> Orders.for_customers
|> sales_tax(2016)
|> prepare_filing
E
|> D
|> C("F")
|> B("G")
|> A("H")
http://elixir-lang.org/
• a series of data transforms
• this is a lot easier to read compared to the 1st example
• since we use Elixir a lot at DockYard, it was a language
feature we wanted to use in ember
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
<button {{action (pipe addToCart purchase redirectToThankYouPage) item}}>
1-Click Buy
</button>
• so the pipe helper was born to let you compose small,
pure actions to allow more declarative templating
• in this e.g. the item argument at the end gets passed
into 1st action, then its return value piped into the rest
• as you can see, helpers can be really powerful tools to
extend templating in your app
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
ember install ember-composable-helpers
https://github.com/DockYard/ember-composable-helpers
• together with my colleague Marten Schilstra, we've
built an addon called ember-composable-helpers
• which contains the pipe helper and other declarative
helpers
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
<button {{action (pipe save closeDropdown) item}}>Save and Close</button>
<button {{action (pipe save quitApp) item}}>Save and Quit</button>
• the best part about helpers is composability
• helpers can do things that might be more complex to
express in your component
• using the pipe helper example again, you don't need to
define 2 actions called `saveAndClose` and
`saveAndQuit`, you can just compose them directly
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
{{#if (eq (not (incr (count user))) (decr (count user))))}}
💩
• that said, you shouldn't try to get too ambitious with
nesting helpers inside of each other
• and when your template looks like this, you're better off
creating a CP instead
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• it can be easy to get carried away with using helpers
• how much logic you want to have in your templates
depends on your comfort level
• so use them with caution and exercise best judgement
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• the point is, helpers are better suited for dealing with
UI / presentational logic
• which quite often is highly abstract and unrelated to
the exact data in question
• in contrast to CPs which are coupled to data
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• which brings us to our next question
• when we do need to perform computation, what is the
best way?
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
COMPUTED VS HELPER
VS COMPONENT HOOKS
• generally speaking, we have 3 ways of doing so
• you could express it as a CP, use a helper in the
template, or use a component hook to set a value
• each approach has its pros and cons, lets look at when
we should prefer to use one over the other
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
COMPUTEDS
• CPs are one of the first things you learn in Ember
• they can range from simple to powerful, and are a nice
way of keeping some computation up to date
• but these auto updates can be double edged sword
• bc observing changes are implicit, so when a CP
recomputes, don't always know why it did
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• the best analogy for a CP is an excel spreadsheet
• it would be painful to sum a1 and b1 by placing event
listeners on the cells and then getting their DOM values
• a CP lets you declaratively express logic that changes
automatically when the dependents change
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
export default Component.extend({
@computed('payment', 'rate', 'periods')
annuity(payment, rate, periods) {
let factor = ((1 - Math.pow(1 + rate, -periods)) / rate);
return payment * factor;
}
});
• i would recommend using CPs for expressing business
logic
• one of the best things about CPs is that they can
become reusable macros
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
export function customMacro(dependentKey, ...keys) {
return computed(dependentKey, ...keys, {
get() {
// computed property logic
}
});
}
• you can extract a CP into a macro by creating a
function that returns a CP
• you can then pass in any arbitrary key or value into the
macro,
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
export default Component.extend({
myValue: customMacro('myKey', 'foo', 'bar'),
someValue: customMacro('someKey', 'baz', 'qux'),
otherValue: customMacro('otherKey', 'meow', 'woof')
});
• and then you can import and use it like you would any
other macro
• this is a great way to DRY up your code and test your
business logic
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• another awesome thing about CPs is that they are
cached
• meaning expensive work is only done when it needs to
be done
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
💪👔👍 Business logic
👍👍👍👍 Reusable
⚛⚛⚛⚛ React to changes
🤔 Changes can be implicit
Totally arbitrary emojis
• so basically CPs are great for business logic and have
potential for reuse in other ember objects
• they update when dependents change, but you can
'subscribe' to these explicitly by specifying keys
• however it can be sometimes difficult to trace why a CP
recomputes
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
HELPERS
• helpers can be simple functions or class based
• they don't have a DOM element and are simple to
debug – you know where the data is coming from, and
what comes out of it
• just like CPs, we should strive to keep these pure and
free of side effects
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
{{#each (repeat 3) as |nil index|}}
<div data-thing={{concat "foo-" index}}>
{{!some HTML block}}
</div>
{{/each}}
https://github.com/DockYard/ember-composable-helpers#repeat
• helpers are best suited for generic utility functions,
and are especially useful for UI logic
• for example, this little helper repeats the block inside of
it, 3 times
• it's non-business logic related but helps us DRY up our
templates, so you can use this nice markup instead of
copy pasting a block of HTML 3 times
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
{{capitalize "hello"}} {{capitalize "hello"}}
• another thing to note about helpers is that ember
doesn't guarantee that multiple uses of the helper will
actually run at any given point
• for example, this capitalize helper will only run once,
even though it's used 2x
• this is a good thing as it means ember can optimize
rendering
• but that means helpers must be carefully written to not
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
export function toggle([obj, prop]) {
return function() {
set(obj, prop, !get(obj, prop));
};
}
https://github.com/DockYard/ember-composable-helpers#toggle
• you may or may not be surprised to note that helpers
can be used as an action if it returns a function
• again, this is really useful for expressing UI logic, we
might use this toggle helper to toggle a dropdown or a
popover
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
<button {{action (toggle this "isExpanded")}}>
{{if isExpanded "I am expanded" "I am not"}}
</button>
• you can then use your action helper like this,
• which is much nicer than defining yet another
`toggleIsExpanded` action in your components
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
🎨🖌 Express UI logic
✍❤📖 Composable
😶💭 Simple mental model
🏃 🏃 Can be used as action
🕵🔬🔍 No hooks available (yet)
Totally arbitrary emojis
• so helpers are great for UI and presentational logic
• & inherently composable with sub-expr or nested
helpers
• they're easy to understand and can also be used as
actions
• & bc they're still lightweight implementations, we
sometimes have to use observers to recompute
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
COMPONENT HOOKS
• component hooks are also a nice explicit way of
handling computation
• for example, when props change from the outside, we
can handle it easily
• however, they can be quite tricky to use, so you should
prefer a CP unless you know why you need to use a
lifecycle hook
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
export default Component.extend({
didReceiveAttrs() {
this.updateChart(get(this, 'data'));
},
updateChart(data) {
// update the chart's data
}
});
• lifecycle hooks are best used when you need side
effects, and should be preferred over an observer
• for example, you might have a component that wraps a
chart library which has some kind of render method
• you can use a hook like `didReceiveAttrs` to update the
chart whenever new data flows into the component
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Initial Render
init
didReceiveAttrs
willRender
didInsertElement
didRender
External attr changed
didUpdateAttrs
didReceiveAttrs
willUpdate
willRender
didUpdate
didRender
Internal value changed
willUpdate
willRender
didUpdate
didRender
• this is a simple diagram showing the order of hooks
that fire when components render or re-render
• when using these hooks, its important to think about
whether the changes are 'idempotent'
• in other words, these hooks should work no matter how
many times they are called
• as you cannot easily control the order and timing of the
hook
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
export default Component.extend({
didRender() {
// this is an infinite loop that will crash your browser
let isFoo = get(this, 'isFoo');
set(this, 'isFoo', !isFoo);
}
});
• for example, this might look like fairly innocent
• you might want to toggle some property after a
component has rendered
• but because it has side effects, it will cause a re-render,
which fires the `didRender` hook again, which re-
renders, and so on until your browser explodes
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
🐘💨🙊 Dealing with side effects
😭➿😱 Can cause infinite loops
🔨🔨 "Just re-render it"
🚀🚀🚀 Not invoked in FastBoot environment
Totally arbitrary ratings
• in a nutshell, lifecycle hooks are useful for replacing
observers and for controlling side effects
• however, they can also be potential footguns, as you
can easily cause an infinite loop or sync issues if your
logic is not idempotent
• so use them with caution
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
SHOULD I USE AN
OBSERVER?
• and finally the age old question, should i use an
observer???
• this topic has been covered quite in detail already,
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• but basically, you almost never want to use an
observer
• they're low level primitives used by ember so you don't
have to
• as i mentioned earlier, the only place it is ok to use one
is in a class based helper bc no lifecycle hooks are
implemented yet
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
https://youtu.be/vvZEddrClAQ
• you should remember that every time you use an
observer, Stefan Penner dies a little inside
• so don't do it
• and watch his Wicked Good Ember talk on observers
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
THE FUTURE
• i want to close off the talk by briefly mentioning what
we can learn from game renderers
• and what the future might hold for how we build web
apps
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• game renderers are surprisingly similar to web
applications
• this diagram shows the rendering architecture for
Doom 3
• there is an idea of a "front end" and a "back end" as well
as an Intermediate Representation (IR) that sits
between
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Game world
state
Front End IR Back End
DirectX / OpenGL
OS
Screen
• the front end captures the state of the world and
determines what contributes to the view
• this is then expressed as an IR, which is then passed
into the backend where it goes through a hardware
abstraction layer like DirectX or OpenGL before
reaching your GPU and then your screen
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Application
state
Front End HTMLBars Glimmer
DOM APIs
Browser
Screen
• an ember app is similar
• we capture the state of the app and determine what to
render
• our templates go through HTMLBars and Glimmer, and
then to DOM APIs
• this is then taken by your browser and rendered onto
your screen
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• so if games and web apps are so similar
• how can games that are so much more complex and
graphically rich sometimes run faster than a web app?
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Hidden blocks rendered,
CPU time wasted
Line of SightCamera
Without occlusion culling
• the answer is that games are heavily optimized to
make use of your GPU
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Hidden blocks not rendered,
CPU time saved
Line of SightCamera
With occlusion culling
• & use a bunch of tricks like occlusion culling to
optimize rendering performance
• i'm really excited to see the trailblazing work Chris
Thoburn (@runspired) is doing in this area, you should
follow him for updates
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• in fact, Mozilla is actually working on an experimental
web renderer for Servo, that aims to draw web content
like a modern game engine
• early prototypes are able to render at hundreds of FPS
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
https://air.mozilla.org/bay-area-rust-meetup-february-2016/#@1m53s
• i won't go into further detail, but you can check out the
video for more info
• i think web apps have a lot to learn from game
rendering, and i'm excited to see us moving in that
direction to optimize performance
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
TL;DR
• to summarize
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• we looked at the state of javascript and we saw that
ember is going to closely align itself to new features
from ES2017 and beyond
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
I. Data Down, Actions Up?
II. Controllers are Dead
III.Declarative & Composable Templates
• we then looked at what DDAU means and how to
implement it by keeping in mind who the owner of the
data is
• and to avoid mutating data directly
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
I. Data Down, Actions Up?
II. Controllers are Dead
III.Declarative & Composable Templates
• then, we cleared the air on controllers
• routable components and services are superior impl
• & will still play the part of a controller, which is to
decorate a model
• we also looked at using ember-route-action-helper for
using route actions in templates
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
I. Data Down, Actions Up?
II. Controllers are Dead
III.Declarative & Composable Templates
• and finally, we looked at ways to power up your
handlebars templates
• helpers are a great way of performing UI logic in a
composable and easily testable way
• you can write your own or use ember-composable-
helpers to make your templates more declarative
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• i want to thank dockyard for allowing me to give this
talk and being an awesome place to work at
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
• we're organizing the WickedGoodEmber conference
this june, so please check out our website for more
info
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
🐰 LAUREN TAN
SUGARPIRATE_
POTETO
• once again, please get in touch if you have any
questions
IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY
EMBERCONF 2016
Thanks!
🐰 LAUREN TAN
SUGARPIRATE_
POTETO
• remember to speak to me if you're interested in
working AT or WITH DockYard
• and i'll give you a sticker too
• thank you all so much for listening!

More Related Content

Similar to EmberConf 2016 – Idiomatic Ember (Speaker Notes)

Beyond your daily coding - The Conf Brazil 2017 Keynote
Beyond your daily coding - The Conf Brazil 2017 KeynoteBeyond your daily coding - The Conf Brazil 2017 Keynote
Beyond your daily coding - The Conf Brazil 2017 Keynote
Emerson Macedo
 
A call to JS Developers - Let’s stop trying to impress each other and start b...
A call to JS Developers - Let’s stop trying to impress each other and start b...A call to JS Developers - Let’s stop trying to impress each other and start b...
A call to JS Developers - Let’s stop trying to impress each other and start b...
Christian Heilmann
 
Blackberry: Looking for the iPod effect
Blackberry: Looking for the iPod effectBlackberry: Looking for the iPod effect
Blackberry: Looking for the iPod effect
Stanislas Thomann
 
Surviving a Hackathon and Beyond
Surviving a Hackathon and BeyondSurviving a Hackathon and Beyond
Surviving a Hackathon and Beyond
imoneytech
 
New Rules of The Responsive Web
New Rules of The Responsive WebNew Rules of The Responsive Web
New Rules of The Responsive Web
Matt Carver
 
Stapling and patching the web of now - ForwardJS3, San Francisco
Stapling and patching the web of now - ForwardJS3, San FranciscoStapling and patching the web of now - ForwardJS3, San Francisco
Stapling and patching the web of now - ForwardJS3, San Francisco
Christian Heilmann
 
Built With ❤ - Why Developer Experience Matters - Web Unleashed 2019
Built With ❤ - Why Developer Experience Matters - Web Unleashed 2019Built With ❤ - Why Developer Experience Matters - Web Unleashed 2019
Built With ❤ - Why Developer Experience Matters - Web Unleashed 2019
Arthur Maltson
 
Let’s learn how to use JavaScript responsibly and stay up-to-date.
Let’s learn how to use JavaScript responsibly and stay up-to-date. Let’s learn how to use JavaScript responsibly and stay up-to-date.
Let’s learn how to use JavaScript responsibly and stay up-to-date.
Christian Heilmann
 
Umbraco Show & Tell, London 2017
Umbraco Show & Tell, London 2017Umbraco Show & Tell, London 2017
Umbraco Show & Tell, London 2017
Andy Butland
 
WSO2Con EU 2015: Opening Keynote - Helping You Connect the World
WSO2Con EU 2015: Opening Keynote - Helping You Connect the WorldWSO2Con EU 2015: Opening Keynote - Helping You Connect the World
WSO2Con EU 2015: Opening Keynote - Helping You Connect the World
WSO2
 
Built With ❤ - Why Developer Experience Matters - DevOps Days Boston 2019
Built With ❤ - Why Developer Experience Matters - DevOps Days Boston 2019Built With ❤ - Why Developer Experience Matters - DevOps Days Boston 2019
Built With ❤ - Why Developer Experience Matters - DevOps Days Boston 2019
Arthur Maltson
 
Eating our own Dogfood - Twitter Mobile
Eating our own Dogfood - Twitter MobileEating our own Dogfood - Twitter Mobile
Eating our own Dogfood - Twitter Mobile
lrechis
 
Imago 9_14
Imago 9_14Imago 9_14
Imago 9_14
Janelle Laguette
 
Innovation - road to value TopConf Nov2015
Innovation - road to value TopConf Nov2015Innovation - road to value TopConf Nov2015
Innovation - road to value TopConf Nov2015
Alek Kozlov
 
GFAR webinar "The future of online media" - webdesign trends
GFAR webinar "The future of online media" - webdesign trendsGFAR webinar "The future of online media" - webdesign trends
GFAR webinar "The future of online media" - webdesign trends
GCARD Conferences
 
Conversion Conference - Schuh's journey to RWD
Conversion Conference - Schuh's journey to RWDConversion Conference - Schuh's journey to RWD
Conversion Conference - Schuh's journey to RWD
Stuart McMillan
 
Overboard.js - where are we going with with jsconfasia / devfestasia
Overboard.js - where are we going with with jsconfasia / devfestasiaOverboard.js - where are we going with with jsconfasia / devfestasia
Overboard.js - where are we going with with jsconfasia / devfestasia
Christian Heilmann
 
Windows Phone Dev Day Bournemouth Presentation
Windows Phone Dev Day Bournemouth PresentationWindows Phone Dev Day Bournemouth Presentation
Windows Phone Dev Day Bournemouth Presentation
James Mundy
 
Moore vs. May - everything is faster and better: we can fix that
Moore vs. May - everything is faster and better: we can fix thatMoore vs. May - everything is faster and better: we can fix that
Moore vs. May - everything is faster and better: we can fix that
Christian Heilmann
 
How pair programming can strengthen teams
How pair programming can strengthen teamsHow pair programming can strengthen teams
How pair programming can strengthen teams
Hugo Messer
 

Similar to EmberConf 2016 – Idiomatic Ember (Speaker Notes) (20)

Beyond your daily coding - The Conf Brazil 2017 Keynote
Beyond your daily coding - The Conf Brazil 2017 KeynoteBeyond your daily coding - The Conf Brazil 2017 Keynote
Beyond your daily coding - The Conf Brazil 2017 Keynote
 
A call to JS Developers - Let’s stop trying to impress each other and start b...
A call to JS Developers - Let’s stop trying to impress each other and start b...A call to JS Developers - Let’s stop trying to impress each other and start b...
A call to JS Developers - Let’s stop trying to impress each other and start b...
 
Blackberry: Looking for the iPod effect
Blackberry: Looking for the iPod effectBlackberry: Looking for the iPod effect
Blackberry: Looking for the iPod effect
 
Surviving a Hackathon and Beyond
Surviving a Hackathon and BeyondSurviving a Hackathon and Beyond
Surviving a Hackathon and Beyond
 
New Rules of The Responsive Web
New Rules of The Responsive WebNew Rules of The Responsive Web
New Rules of The Responsive Web
 
Stapling and patching the web of now - ForwardJS3, San Francisco
Stapling and patching the web of now - ForwardJS3, San FranciscoStapling and patching the web of now - ForwardJS3, San Francisco
Stapling and patching the web of now - ForwardJS3, San Francisco
 
Built With ❤ - Why Developer Experience Matters - Web Unleashed 2019
Built With ❤ - Why Developer Experience Matters - Web Unleashed 2019Built With ❤ - Why Developer Experience Matters - Web Unleashed 2019
Built With ❤ - Why Developer Experience Matters - Web Unleashed 2019
 
Let’s learn how to use JavaScript responsibly and stay up-to-date.
Let’s learn how to use JavaScript responsibly and stay up-to-date. Let’s learn how to use JavaScript responsibly and stay up-to-date.
Let’s learn how to use JavaScript responsibly and stay up-to-date.
 
Umbraco Show & Tell, London 2017
Umbraco Show & Tell, London 2017Umbraco Show & Tell, London 2017
Umbraco Show & Tell, London 2017
 
WSO2Con EU 2015: Opening Keynote - Helping You Connect the World
WSO2Con EU 2015: Opening Keynote - Helping You Connect the WorldWSO2Con EU 2015: Opening Keynote - Helping You Connect the World
WSO2Con EU 2015: Opening Keynote - Helping You Connect the World
 
Built With ❤ - Why Developer Experience Matters - DevOps Days Boston 2019
Built With ❤ - Why Developer Experience Matters - DevOps Days Boston 2019Built With ❤ - Why Developer Experience Matters - DevOps Days Boston 2019
Built With ❤ - Why Developer Experience Matters - DevOps Days Boston 2019
 
Eating our own Dogfood - Twitter Mobile
Eating our own Dogfood - Twitter MobileEating our own Dogfood - Twitter Mobile
Eating our own Dogfood - Twitter Mobile
 
Imago 9_14
Imago 9_14Imago 9_14
Imago 9_14
 
Innovation - road to value TopConf Nov2015
Innovation - road to value TopConf Nov2015Innovation - road to value TopConf Nov2015
Innovation - road to value TopConf Nov2015
 
GFAR webinar "The future of online media" - webdesign trends
GFAR webinar "The future of online media" - webdesign trendsGFAR webinar "The future of online media" - webdesign trends
GFAR webinar "The future of online media" - webdesign trends
 
Conversion Conference - Schuh's journey to RWD
Conversion Conference - Schuh's journey to RWDConversion Conference - Schuh's journey to RWD
Conversion Conference - Schuh's journey to RWD
 
Overboard.js - where are we going with with jsconfasia / devfestasia
Overboard.js - where are we going with with jsconfasia / devfestasiaOverboard.js - where are we going with with jsconfasia / devfestasia
Overboard.js - where are we going with with jsconfasia / devfestasia
 
Windows Phone Dev Day Bournemouth Presentation
Windows Phone Dev Day Bournemouth PresentationWindows Phone Dev Day Bournemouth Presentation
Windows Phone Dev Day Bournemouth Presentation
 
Moore vs. May - everything is faster and better: we can fix that
Moore vs. May - everything is faster and better: we can fix thatMoore vs. May - everything is faster and better: we can fix that
Moore vs. May - everything is faster and better: we can fix that
 
How pair programming can strengthen teams
How pair programming can strengthen teamsHow pair programming can strengthen teams
How pair programming can strengthen teams
 

Recently uploaded

CHINA’S GEO-ECONOMIC OUTREACH IN CENTRAL ASIAN COUNTRIES AND FUTURE PROSPECT
CHINA’S GEO-ECONOMIC OUTREACH IN CENTRAL ASIAN COUNTRIES AND FUTURE PROSPECTCHINA’S GEO-ECONOMIC OUTREACH IN CENTRAL ASIAN COUNTRIES AND FUTURE PROSPECT
CHINA’S GEO-ECONOMIC OUTREACH IN CENTRAL ASIAN COUNTRIES AND FUTURE PROSPECT
jpsjournal1
 
官方认证美国密歇根州立大学毕业证学位证书原版一模一样
官方认证美国密歇根州立大学毕业证学位证书原版一模一样官方认证美国密歇根州立大学毕业证学位证书原版一模一样
官方认证美国密歇根州立大学毕业证学位证书原版一模一样
171ticu
 
CSM Cloud Service Management Presentarion
CSM Cloud Service Management PresentarionCSM Cloud Service Management Presentarion
CSM Cloud Service Management Presentarion
rpskprasana
 
22CYT12-Unit-V-E Waste and its Management.ppt
22CYT12-Unit-V-E Waste and its Management.ppt22CYT12-Unit-V-E Waste and its Management.ppt
22CYT12-Unit-V-E Waste and its Management.ppt
KrishnaveniKrishnara1
 
ACEP Magazine edition 4th launched on 05.06.2024
ACEP Magazine edition 4th launched on 05.06.2024ACEP Magazine edition 4th launched on 05.06.2024
ACEP Magazine edition 4th launched on 05.06.2024
Rahul
 
Advanced control scheme of doubly fed induction generator for wind turbine us...
Advanced control scheme of doubly fed induction generator for wind turbine us...Advanced control scheme of doubly fed induction generator for wind turbine us...
Advanced control scheme of doubly fed induction generator for wind turbine us...
IJECEIAES
 
ML Based Model for NIDS MSc Updated Presentation.v2.pptx
ML Based Model for NIDS MSc Updated Presentation.v2.pptxML Based Model for NIDS MSc Updated Presentation.v2.pptx
ML Based Model for NIDS MSc Updated Presentation.v2.pptx
JamalHussainArman
 
DEEP LEARNING FOR SMART GRID INTRUSION DETECTION: A HYBRID CNN-LSTM-BASED MODEL
DEEP LEARNING FOR SMART GRID INTRUSION DETECTION: A HYBRID CNN-LSTM-BASED MODELDEEP LEARNING FOR SMART GRID INTRUSION DETECTION: A HYBRID CNN-LSTM-BASED MODEL
DEEP LEARNING FOR SMART GRID INTRUSION DETECTION: A HYBRID CNN-LSTM-BASED MODEL
gerogepatton
 
Embedded machine learning-based road conditions and driving behavior monitoring
Embedded machine learning-based road conditions and driving behavior monitoringEmbedded machine learning-based road conditions and driving behavior monitoring
Embedded machine learning-based road conditions and driving behavior monitoring
IJECEIAES
 
Unit-III-ELECTROCHEMICAL STORAGE DEVICES.ppt
Unit-III-ELECTROCHEMICAL STORAGE DEVICES.pptUnit-III-ELECTROCHEMICAL STORAGE DEVICES.ppt
Unit-III-ELECTROCHEMICAL STORAGE DEVICES.ppt
KrishnaveniKrishnara1
 
Electric vehicle and photovoltaic advanced roles in enhancing the financial p...
Electric vehicle and photovoltaic advanced roles in enhancing the financial p...Electric vehicle and photovoltaic advanced roles in enhancing the financial p...
Electric vehicle and photovoltaic advanced roles in enhancing the financial p...
IJECEIAES
 
Engineering Drawings Lecture Detail Drawings 2014.pdf
Engineering Drawings Lecture Detail Drawings 2014.pdfEngineering Drawings Lecture Detail Drawings 2014.pdf
Engineering Drawings Lecture Detail Drawings 2014.pdf
abbyasa1014
 
Understanding Inductive Bias in Machine Learning
Understanding Inductive Bias in Machine LearningUnderstanding Inductive Bias in Machine Learning
Understanding Inductive Bias in Machine Learning
SUTEJAS
 
Properties Railway Sleepers and Test.pptx
Properties Railway Sleepers and Test.pptxProperties Railway Sleepers and Test.pptx
Properties Railway Sleepers and Test.pptx
MDSABBIROJJAMANPAYEL
 
Modelagem de um CSTR com reação endotermica.pdf
Modelagem de um CSTR com reação endotermica.pdfModelagem de um CSTR com reação endotermica.pdf
Modelagem de um CSTR com reação endotermica.pdf
camseq
 
5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...
5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...
5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...
ihlasbinance2003
 
Comparative analysis between traditional aquaponics and reconstructed aquapon...
Comparative analysis between traditional aquaponics and reconstructed aquapon...Comparative analysis between traditional aquaponics and reconstructed aquapon...
Comparative analysis between traditional aquaponics and reconstructed aquapon...
bijceesjournal
 
IEEE Aerospace and Electronic Systems Society as a Graduate Student Member
IEEE Aerospace and Electronic Systems Society as a Graduate Student MemberIEEE Aerospace and Electronic Systems Society as a Graduate Student Member
IEEE Aerospace and Electronic Systems Society as a Graduate Student Member
VICTOR MAESTRE RAMIREZ
 
BPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdf
BPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdfBPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdf
BPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdf
MIGUELANGEL966976
 
spirit beverages ppt without graphics.pptx
spirit beverages ppt without graphics.pptxspirit beverages ppt without graphics.pptx
spirit beverages ppt without graphics.pptx
Madan Karki
 

Recently uploaded (20)

CHINA’S GEO-ECONOMIC OUTREACH IN CENTRAL ASIAN COUNTRIES AND FUTURE PROSPECT
CHINA’S GEO-ECONOMIC OUTREACH IN CENTRAL ASIAN COUNTRIES AND FUTURE PROSPECTCHINA’S GEO-ECONOMIC OUTREACH IN CENTRAL ASIAN COUNTRIES AND FUTURE PROSPECT
CHINA’S GEO-ECONOMIC OUTREACH IN CENTRAL ASIAN COUNTRIES AND FUTURE PROSPECT
 
官方认证美国密歇根州立大学毕业证学位证书原版一模一样
官方认证美国密歇根州立大学毕业证学位证书原版一模一样官方认证美国密歇根州立大学毕业证学位证书原版一模一样
官方认证美国密歇根州立大学毕业证学位证书原版一模一样
 
CSM Cloud Service Management Presentarion
CSM Cloud Service Management PresentarionCSM Cloud Service Management Presentarion
CSM Cloud Service Management Presentarion
 
22CYT12-Unit-V-E Waste and its Management.ppt
22CYT12-Unit-V-E Waste and its Management.ppt22CYT12-Unit-V-E Waste and its Management.ppt
22CYT12-Unit-V-E Waste and its Management.ppt
 
ACEP Magazine edition 4th launched on 05.06.2024
ACEP Magazine edition 4th launched on 05.06.2024ACEP Magazine edition 4th launched on 05.06.2024
ACEP Magazine edition 4th launched on 05.06.2024
 
Advanced control scheme of doubly fed induction generator for wind turbine us...
Advanced control scheme of doubly fed induction generator for wind turbine us...Advanced control scheme of doubly fed induction generator for wind turbine us...
Advanced control scheme of doubly fed induction generator for wind turbine us...
 
ML Based Model for NIDS MSc Updated Presentation.v2.pptx
ML Based Model for NIDS MSc Updated Presentation.v2.pptxML Based Model for NIDS MSc Updated Presentation.v2.pptx
ML Based Model for NIDS MSc Updated Presentation.v2.pptx
 
DEEP LEARNING FOR SMART GRID INTRUSION DETECTION: A HYBRID CNN-LSTM-BASED MODEL
DEEP LEARNING FOR SMART GRID INTRUSION DETECTION: A HYBRID CNN-LSTM-BASED MODELDEEP LEARNING FOR SMART GRID INTRUSION DETECTION: A HYBRID CNN-LSTM-BASED MODEL
DEEP LEARNING FOR SMART GRID INTRUSION DETECTION: A HYBRID CNN-LSTM-BASED MODEL
 
Embedded machine learning-based road conditions and driving behavior monitoring
Embedded machine learning-based road conditions and driving behavior monitoringEmbedded machine learning-based road conditions and driving behavior monitoring
Embedded machine learning-based road conditions and driving behavior monitoring
 
Unit-III-ELECTROCHEMICAL STORAGE DEVICES.ppt
Unit-III-ELECTROCHEMICAL STORAGE DEVICES.pptUnit-III-ELECTROCHEMICAL STORAGE DEVICES.ppt
Unit-III-ELECTROCHEMICAL STORAGE DEVICES.ppt
 
Electric vehicle and photovoltaic advanced roles in enhancing the financial p...
Electric vehicle and photovoltaic advanced roles in enhancing the financial p...Electric vehicle and photovoltaic advanced roles in enhancing the financial p...
Electric vehicle and photovoltaic advanced roles in enhancing the financial p...
 
Engineering Drawings Lecture Detail Drawings 2014.pdf
Engineering Drawings Lecture Detail Drawings 2014.pdfEngineering Drawings Lecture Detail Drawings 2014.pdf
Engineering Drawings Lecture Detail Drawings 2014.pdf
 
Understanding Inductive Bias in Machine Learning
Understanding Inductive Bias in Machine LearningUnderstanding Inductive Bias in Machine Learning
Understanding Inductive Bias in Machine Learning
 
Properties Railway Sleepers and Test.pptx
Properties Railway Sleepers and Test.pptxProperties Railway Sleepers and Test.pptx
Properties Railway Sleepers and Test.pptx
 
Modelagem de um CSTR com reação endotermica.pdf
Modelagem de um CSTR com reação endotermica.pdfModelagem de um CSTR com reação endotermica.pdf
Modelagem de um CSTR com reação endotermica.pdf
 
5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...
5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...
5214-1693458878915-Unit 6 2023 to 2024 academic year assignment (AutoRecovere...
 
Comparative analysis between traditional aquaponics and reconstructed aquapon...
Comparative analysis between traditional aquaponics and reconstructed aquapon...Comparative analysis between traditional aquaponics and reconstructed aquapon...
Comparative analysis between traditional aquaponics and reconstructed aquapon...
 
IEEE Aerospace and Electronic Systems Society as a Graduate Student Member
IEEE Aerospace and Electronic Systems Society as a Graduate Student MemberIEEE Aerospace and Electronic Systems Society as a Graduate Student Member
IEEE Aerospace and Electronic Systems Society as a Graduate Student Member
 
BPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdf
BPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdfBPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdf
BPV-GUI-01-Guide-for-ASME-Review-Teams-(General)-10-10-2023.pdf
 
spirit beverages ppt without graphics.pptx
spirit beverages ppt without graphics.pptxspirit beverages ppt without graphics.pptx
spirit beverages ppt without graphics.pptx
 

EmberConf 2016 – Idiomatic Ember (Speaker Notes)

  • 1. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 IDIOMATIC EMBER Finding the Sweet Spot of Performance & Productivity ・ D O C K YA R D ・ • hi everyone! • today i want to share some ideas with you about how we can write idiomatic ember apps that are both performant and productive IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 bit.ly/idiomatic-ember • if you can't see the slides clearly, you can look them up on • bitly idiomatic dash ember (repeat it)
  • 2. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • but first with a heavy heart, let's address the elephant in the room – • what's an idiomatic talk without idioms? IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • they say time is money • so i'm gonna just cut to the chase
  • 3. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 🐰 LAUREN TAN SUGARPIRATE_ POTETO • my name is lauren, and i was born in the year of the rabbit • you can find me on the interwebs as sugarpirate or poteto on github IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • when i'm not working on client work or open source, i sometimes play final fantasy 14 • it's a game that can be quite addictive, but thankfully i have
  • 4. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 🐶 ZELDA • a little puppy Zelda who keeps me grounded in reality • unfortunately she couldn't be here today to give this talk, so you'll have to listen to me instead IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 I WORK AT DOCKYARD • a year ago i was still living in australia • but i moved to Boston last year to work at DockYard • we work on a ton of Ember and Elixir apps as well very many open source libraries including ember addons • in 2 days it will be the end of my 1st year at dockyard, and i have to say that it's been one of the best jobs i've ever had
  • 5. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • the best part is, we're hiring senior ember engineers • so please talk to me, brian, marten or estelle later if you're interested in finding out more IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • and if you come speak to me after my talk, i'll give you a very limited edition sugarpirate sticker!
  • 6. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 THE STATE OF JAVASCRIPT IN 2016 • now before we start talking about ember, let's look at what it's like to build a modern javascript app in the year 2016 IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • react has been steadily gaining ground and mindshare • and for good reasons • some of its ideas have even made their way into ember and other frameworks
  • 7. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • but despite how far we've come from our early days, modern web dev is getting really hard • i mean, it used to be so simple, right? IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • in the Good Old Days™, all you had to do was write some html, maybe some css, slap some jQuery on a page • and even use a plugin or 5
  • 8. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • but these days we spend so much time configuring things • and we spend valuable time writing glue code instead of working on what matters IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • you have to make a ton of choices for your front end stack • which can be quite paralyzing
  • 9. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 leftpad • & its easy to build a tangled web of dependencies • which can lead to all sorts of problems… • <dramatic pause> 🙃 IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 “I hand-rolled my own front-end stack using the most organic, gluten-free and artisanal micro- libraries.” 🤓 • it's tempting to fall victim to javascript hype • and try to build your own makeshift framework • that might end up slowing you down bc you have to make sure everything plays nicely together • why go through that pain?
  • 10. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • but that's why we use an opinionated framework like ember, right? • with ember, we opt into convention over configuration • problems are shared across the community • bc chances are, your app isn't a special snowflake IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Performance Productivity • these strong standards have given the ember community hands down the best tooling experience available • we have things like ember-cli, the ember inspector, more than 2,000 addons, which is an incredible number • and all of this would not have been possible without the community
  • 11. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 ❤❤ • and i think it's fair to say that ember has one of the most welcoming and friendly communities out there • our slack channel is always active, and getting help is easy • there are a few people in there that don't seem to sleep • so if you have a question, there will almost always be someone available to help you out IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 THE EMBER WAY? • because ember is opinionated, it also means there is an "ember" way of doing things • instead of rebuilding the wheel and inventing your own abstractions • we leverage the community's exp in building web apps • with ember 2.0 being released last year in august, quite a few things have changed since then • changes are main motivation for talk
  • 12. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Data Component Owner Action • for example, there has been lots of discussion around data down, actions up • this is a pattern for one way data flow that we adapted • and is meant to make your apps easier to reason about & maintain • i'll cover this more in detail later IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • we've also established conventions that singleton state should live in services instead of controllers • services are excellent for handling the long lived state of things such as shopping carts, activity feeds and notification messages
  • 13. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 this.attrs.fooAction(val); this.get('fooAction')(val); VS • actions have been getting a little confusing lately • with the future introduction of glimmer components • these action calls will be subtly different, although they may appear to be the same right now IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • we also know that controllers are going away in the future • i'll talk a little more about what that means and share some techniques you can use to ease the transition to routable components
  • 14. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • in a nutshell, things have changed • and dealing with change can be hard • these changes can be diff to deal with bc • things that used to be best practices may no longer be true • and lack of updated info about new way of doing things IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 MORE JAVASCRIPT • going forward, we can expect to see Ember become more closely aligned with JavaScript, and for things to become more explicit and less magical • ES2017 features and beyond are going to play a pivotal role in Ember's future
  • 15. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 DECORATORS Stage 1 https://github.com/wycats/javascript-decorators • for example, you can already use decorators today using rwjblue's excellent addon IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 https://github.com/rwjblue/ember-computed-decorators @computed('first', 'last') name(first, last) { return `${first} ${last}`; } • this is currently a stage 1 proposal, but is incredibly useful for DRYing up your code • the most obvious example is with CPs, as you can see this is much nicer than what we have to do today
  • 16. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 ASYNC/AWAIT Stage 3 https://github.com/tc39/ecmascript-asyncawait • async/await functions are also on the horizon, and are 1 stage away from becoming included into the spec • these let us write asynchronous operations as if they were synchronous IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 await fillIn('.display-title', 'Hello!'); await click('.update-display-title'); assert.equal(find('.display-title').text(), 'Hello!'); https://github.com/emberjs/rfcs/pull/119 • if you ever been trolled by Promises and async programming, you'll love this new feature • for example, in rwjblue's RFC for making tests great again, he describes how we might make use of async/ await to clean up tests • as a result, code & tests are much easier to read and follow
  • 17. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 GENERATORS ES2015 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function* • generator functions are already a part of es2015 • and are really cool • they allow you to write co-operative code – you can pause, resume and restart them as well as end them early IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 countingTask: task(function* () { this.set('count', 0); while (this.get('count') < 5) { this.incrementProperty('count'); yield timeout(300); } this.set('count', 'DONE!'); }).restartable() https://github.com/machty/ember-concurrency • these are really powerful, and you should definitely checkout Machty's addon called ember-concurrency • it allows you to write Tasks to do things you would have a hard time replicating without generator functions
  • 18. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 ❤ • as you can see, when you use Ember, you're betting on JavaScript • we're going to become even more closely aligned with the latest JS features, meaning that you'll be able to write more JavaScript and less Ember IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 – Yehuda Katz “All good ideas will eventually end up in Ember.” • i think it's fair to say that ember is the solution to javascript hype fatigue • and that is why i'm excited to give this talk, bc with ember, we don't have to sacrifice performance for productivity
  • 19. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 THE EMBER WAY 🙏 • so in this talk, i want to cast away any doubt you might have about what the ember way really is • and hopefully you'll take away some useful ideas you can use straight away in your apps IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 I. Data Down, Actions Up? II. Controllers are Dead III.Declarative & Composable Templates • very broadly, i'll be speaking about patterns and anti- patterns in modern ember apps • first, i want to talk about an important concept
  • 20. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 I. Data Down, Actions Up? II. Controllers are Dead III.Declarative & Composable Templates • data down actions up is one of the core principles driving modern ember apps • by architecting our applications in this manner, we can build apps that are easier to maintain and reason about IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • data down, actions up describes flow of data thru app • eg this is what app might look like once routable components land • fetch data from API, which gets normalized and pushed into ED store • records then get passed in as attrs to routable component
  • 21. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • you might have noticed controllers were missing from that diagram • and that's because they're going to be deprecated and removed in the future IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Is MVC Dead? ☠ • but why remove controllers if they already work? • well, core team found that a component could easily take the place of a controller + view, as components are superior implementations
  • 22. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Is MVC Dead? ☠NOPE • does this mean the death of MVC? • no, but there has been a lot of confusion on this topic, so i'll address it in more detail later IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 2 WAY BINDINGS 💣 • what React taught us is that the biggest problem of the frameworks that predate it is the very thing that made them popular • and that is two way bindings • implicit changes are hard to reason about, and • you can very easily cause an infinite cascade of changes if you're not careful
  • 23. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 💎 • when glimmer or angle bracket components land, data bindings will become one way by default • and instead of mutating data, we will have to send actions to update it • this becomes a nice, functional way of building applications that are still reactive • and easier to reason about IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • by ignoring 2 way bindings and instead re-rendering multiple times efficiently, we can have changes propagate immediately without introducing all the cascading semantics of a 2 way bind • and this is made possible with one way data flow and making renders pure and idempotent
  • 24. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Who owns the data? • with DDAU, a guiding principle is to ask who owns the data • only the owner should be allowed to modify it • this is particularly important when that data is application state, which we should strive to keep as single sources of truth IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Component A Component A.1 Component A.2 Component A.3 Route Owns the shared state of A1 - A3 • for example, here's a diagram of what a simple ember app might look like on a given route • lets say Component A only allowed to show 1 child component at a time • perhaps after doing some config in a child component, we need to programmatically show the next one • where would the best place be to do that?
  • 25. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Component A Component A.1 Component A.2 Component A.3 Route Owns the shared state of A1 - A3 {{component configComponent user=user changeStep=(action "changeStep")}} • if we follow the DDAU principle, we need to ask ourselves – "Who owns the data?" • In this case, which config component to render is the concern of Component A, it owns the shared state of all its children • so, in order to mutate the current step property, we should send an action up to Component A IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 {{component configComponent user=user currentStep=currentStep}} // don't do this in the child component! export default Component.extend({ actions: { next() { set(this, 'currentStep', 'configure-foo'); } } }); This is bad ☹ • what we must avoid doing is mutating the "currentStep" in the child component • it's a subtle difference, but it means an app that is easier to reason about and maintain • you won't need to spend hours figuring out who is changing what • because you know there is only one place it is being changed
  • 26. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 …or someone else's state! • but the action is changing the property anyway, why not just do it directly? • when you change the state that someone else owns, you're stealing • effectively it means that the owner no longer controls the data and you have bypassed the owner's interface • however, in the future these problems will likely go away IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 <configure-username user={{user}} currentStep={{currentStep}}> ... </configure-username> • Glimmer Components will be 1 way by default • so even if you tried mutating `currentStep` in the child component, it would not flow up to mutate the currentStep prop of the parent component • unless you explicitly opt-in to doing so with the `mut` helper
  • 27. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 export default Service.extend({ init() { this._super(...arguments); this.data = []; } }); • another thing to note is that services can also own their own data, • and this is an important part of the Ember programming model • this will be especially useful to know when routable components land, • as singleton state must be moved into a service bc components are stateless IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 I. Data Down, Actions Up? II. Controllers are Dead III.Declarative & Composable Templates • with ddau and routable components coming, what do we do with controllers?
  • 28. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • so, as i mentioned earlier • controllers aren't completely dead yet… IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 ROUTABLE CONTROLLER • one important thing to note about controllers is that the concept itself isn't going away • however, the implementation is changing • essentially, the concept of a controller decorating a model still exists, but it is implemented as a routable component instead
  • 29. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 export default Controller.extend({ queryParams: ['category'], category: null }); • you might still need to use a controller right now if you want to use query params and in certain cases of bubbling actions • but these will be moved to the route eventually when routable components land • that said, don't get too creative in trying to avoid controllers, only remove when it makes sense IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 ROUTABLE CONTROLLER • Ember 1.x was a straightforward implementation of MVC, we had a controller and a view • but we've deprecated views in favor of components • and it turns out that what the controller + view was doing could be better handled by a component and service
  • 30. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 ROUTABLE COMPONENT • so the routable component was introduced • the major difference you have to keep in mind is that a routable component is not a singleton like its controller counterpart • but conceptually, they should do the same things, which is decorate a model IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Component = Controller + View • a simpler concept is to think of the routable component as the unification of what we call a controller and a view
  • 31. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 <h1>Alpaca Route Template</h1> <div class="my-amazing-template"> {{#each alpacas as |alpaca|}} <span> I'm a cute little {{alpaca}}! </span> {{/each}} </div> {{foo-alpaca alpacas=alpacas}} move to • there are things you can do today to make this transition easier • the first key thing you can do is to move your route-level template into a top-level component • when routable components land, it basically just moves that invocation into the route implicitly IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 // shopping-cart top-level component export default Component.extend({ shoppingCart: inject.service(), actions: { remove(product) { // ... } } }); {{#each shoppingCart.products as |product|}} <h2>{{product.title}}</h2> <p>{{product.description}}</p> <button {{action "remove" product}}>Remove</button> {{/each}} • the reason it's a good idea to use a top level component now is that it forces you to separate your stateful, singleton logic out and into a service • a transition to a service for the stateful bits and a component for the stateless bits is most likely to be future proof • and will make the transition an easier one
  • 32. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Controller Action Action Action Route Action Action Action move to • another thing you can do is to move actions that deal with data to the route • these actions are likely better located in the route as that is where they'll eventually live when routable components land • however, actions that deal with UI or presentational logic should remain on the routable component IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 ACTIONS 🎬 • there are some gotchas with moving controller actions to your route, so i'll share a way to do so a little later • but first, let's take a look at actions
  • 33. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 {{foo-bar submit="submit"}} {{foo-bar click=(action "submit")}} • currently, actions can be a little confusing • for example, you could define a classic action on a component by giving it a string property of the action name • or you could use a new style action IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 New-style Actions 👍 aka Closure Actions • as a best practice, you should always prefer to use a new-style or closure action
  • 34. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 {{foo-bar click=(action "submit")}} • a new-style action is essentially just a regular javascript function • which means you can do things like make use of return values, partially apply arguments and more IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Classic Actions 👎 aka String Actions • while classic or string actions are very implicit in nature
  • 35. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 {{foo-bar submit="submit"}} • and make things hard to debug • for example, it would be easy to mistake submit for a string property • and it would be difficult to trace where the action actually lives IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 this.sendAction('someMysteriousAction', args); • another thing is when you use classic actions you have to use `sendAction` in your components • which is kinda like sending your action to space
  • 36. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Your classic action • because you send it up somewhere and hope something is listening to it • who knows where it's going • and the worst part is it never comes back with a return value IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 get(this, 'submit')(...args); • on the other hand, new-style actions are awesome • they're one of my favorite additions to ember and they've been available since 1.13
  • 37. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • don't let the word new-style or closure action scare you • it's really just a regular javascript function IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 actions: { saveAndDoStuff(item) { get(this, 'save')(item) .then((savedItem) => // do stuff); } } • as i said earlier, you have return values • these are especially useful when dealing with async operations like saving a record • you can return the save promise and then handle it from inside the component • e.g. handle success and failure state
  • 38. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 ember install ember-route-action-helper https://github.com/DockYard/ember-route-action-helper • so new-style actions are awesome, but out of the box you can only use them if they're defined on the controller as they do not bubble like classic actions • but if you want to move your actions that deal with data to the route this seems rather lame • so rwjblue and i built a little addon you can use today • it's called the ember-route-action-helper IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 {{foo-bar value=value updateFoo=(route-action "updateFoo") }} • by using `route-action` in place of `action` • this lets you have new-style actions that work with routes, and when the time comes, you can search and replace route-action back to action
  • 39. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 SERVICES • if you recall, controllers without routes can be created, and it was a common practice to manage singleton state with them • a service is a long lived singleton we can use to manage long lived state IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • a great example for a service is a shopping cart or activity feed • for things that have singleton state, you can extract that logic into a service and then inject it into the objects you need to
  • 40. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 export default Service.extend({ init() { this._super(...arguments); this.cart = []; }, addToCart(item) { // ... }, removeFromCart(item) { // ... } }); • a shopping cart is an excellent example of a service, because there can only be one singleton cart in the application, and it needs to have long lived state across the app • you can implement a cart with as little as setting a property on a service to be an array • or you could do more IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • what we must be careful about is not to abuse services • if your main reason for creating a service is to use it as a global bucket to avoid passing things around, that's a bad sign • instead, adhere to data down actions up and don't use services for something that doesn't need long lived singleton state
  • 41. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 I. Data Down, Actions Up? II. Controllers are Dead III.Declarative & Composable Templates • now i want to talk about templating, something i'm sure is close to all of our hearts IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 {{if (eq fullName "Jim Bob") "You're the chosen one"}} https://github.com/jmurphyau/ember-truth-helpers • another of my fav new things in Ember is the new Helper impl • introduced in Ember 1.13 and great for expressing presentation logic • for example, this `eq` helper can be found in ember- truth-helpers addon, which we pretty much use for all our apps
  • 42. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 {{concat "configure-" configName}} http://emberjs.com/api/classes/Ember.Templates.helpers.html • Ember itself also ships with a bunch of useful Helpers like `concat`, `hash` and the`get` helper • the best thing about Helpers is that it basically lets you power up your templates IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 import Ember from 'ember'; export function add([a, b]) { return a + b; } export default Ember.Helper.helper(add); • again, because Ember is converging towards just being JavaScript • a helper is really just a regular JavaScript function • one of the reasons i like helpers is that it forces you to keep your functions small and free of side effects • you can basically create 2 kinds of helpers, this one is a simple one that will recompute every time the params change
  • 43. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 export default Helper.extend({ // ... }); • for more complex needs, you can also make a class based helper, which is essentially an ember object IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 export default Helper.extend({ localesService: inject.service('locales'), currentLocale: readOnly('localesService.currentLocale'), compute([key]) { let currentLocale = get(this, 'currentLocale'); return get(this, 'localesService').lookup(currentLocale, key); }, localeDidChange: observer('currentLocale', function() { this.recompute(); }) }); • this means you can do things like define CPs, use services and so on • for example this is a helper that looks up translations on a locales service • specifically you might want to listen for a change in locale • and then all the translations should auto-update, even though the locale itself is not passed into the helper
  • 44. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • some of you might have noticed i used an observer in my previous example • class based helpers are currently the only place it is ok to use one • bc it is still a lightweight implementation (almost mvp), and its lifecycle hooks are not implemented yet • when those become available, we can use them to recompute instead IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 export default Component.extend({ isDropdownDisplayed: false, actions: { saveUserAndHideDropdown(user) { get(this, 'save')(user) .then((user) => { // do stuff set(this, 'isDropdownDisplayed', false); }); } } }); • another reason i like helpers is because it means a lot of UI logic can be moved back to where it belongs • for example, how many times have you written something like this? • this feels a little dirty because it mixes data and UI logic together
  • 45. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 export default Component.extend({ isDropdownDisplayed: false, actions: { hideDropdown() { set(this, 'isDropdownDisplayed', false); }, saveUser(user) { return get(this, 'save')(user); } } }); • so one thing you could do is to split them up into 2 actions right? • but now you have a problem, because you can't invoke them both • what i'm about to show you demonstrates how powerful helpers can be IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 <button {{action (pipe saveUser hideDropdown) user}}> Save and Close </button> • let's say we had a hypothetical helper called `pipe` • it would let you take the return value from 1 action, and pass it along to the next one • and it would keep passing that value down to each function in the pipe
  • 46. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 A(B(C(D('E'), 'F'), 'G'), 'H'); • if you've used the programming language elixir before, this pipe helper is essentially the same as the pipe operator • the pipe operator lets you express the above, which isn't very nice to read, as IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 filing = DB.find_customers |> Orders.for_customers |> sales_tax(2016) |> prepare_filing E |> D |> C("F") |> B("G") |> A("H") http://elixir-lang.org/ • a series of data transforms • this is a lot easier to read compared to the 1st example • since we use Elixir a lot at DockYard, it was a language feature we wanted to use in ember
  • 47. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 <button {{action (pipe addToCart purchase redirectToThankYouPage) item}}> 1-Click Buy </button> • so the pipe helper was born to let you compose small, pure actions to allow more declarative templating • in this e.g. the item argument at the end gets passed into 1st action, then its return value piped into the rest • as you can see, helpers can be really powerful tools to extend templating in your app IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 ember install ember-composable-helpers https://github.com/DockYard/ember-composable-helpers • together with my colleague Marten Schilstra, we've built an addon called ember-composable-helpers • which contains the pipe helper and other declarative helpers
  • 48. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 <button {{action (pipe save closeDropdown) item}}>Save and Close</button> <button {{action (pipe save quitApp) item}}>Save and Quit</button> • the best part about helpers is composability • helpers can do things that might be more complex to express in your component • using the pipe helper example again, you don't need to define 2 actions called `saveAndClose` and `saveAndQuit`, you can just compose them directly IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 {{#if (eq (not (incr (count user))) (decr (count user))))}} 💩 • that said, you shouldn't try to get too ambitious with nesting helpers inside of each other • and when your template looks like this, you're better off creating a CP instead
  • 49. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • it can be easy to get carried away with using helpers • how much logic you want to have in your templates depends on your comfort level • so use them with caution and exercise best judgement IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • the point is, helpers are better suited for dealing with UI / presentational logic • which quite often is highly abstract and unrelated to the exact data in question • in contrast to CPs which are coupled to data
  • 50. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • which brings us to our next question • when we do need to perform computation, what is the best way? IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 COMPUTED VS HELPER VS COMPONENT HOOKS • generally speaking, we have 3 ways of doing so • you could express it as a CP, use a helper in the template, or use a component hook to set a value • each approach has its pros and cons, lets look at when we should prefer to use one over the other
  • 51. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 COMPUTEDS • CPs are one of the first things you learn in Ember • they can range from simple to powerful, and are a nice way of keeping some computation up to date • but these auto updates can be double edged sword • bc observing changes are implicit, so when a CP recomputes, don't always know why it did IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • the best analogy for a CP is an excel spreadsheet • it would be painful to sum a1 and b1 by placing event listeners on the cells and then getting their DOM values • a CP lets you declaratively express logic that changes automatically when the dependents change
  • 52. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 export default Component.extend({ @computed('payment', 'rate', 'periods') annuity(payment, rate, periods) { let factor = ((1 - Math.pow(1 + rate, -periods)) / rate); return payment * factor; } }); • i would recommend using CPs for expressing business logic • one of the best things about CPs is that they can become reusable macros IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 export function customMacro(dependentKey, ...keys) { return computed(dependentKey, ...keys, { get() { // computed property logic } }); } • you can extract a CP into a macro by creating a function that returns a CP • you can then pass in any arbitrary key or value into the macro,
  • 53. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 export default Component.extend({ myValue: customMacro('myKey', 'foo', 'bar'), someValue: customMacro('someKey', 'baz', 'qux'), otherValue: customMacro('otherKey', 'meow', 'woof') }); • and then you can import and use it like you would any other macro • this is a great way to DRY up your code and test your business logic IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • another awesome thing about CPs is that they are cached • meaning expensive work is only done when it needs to be done
  • 54. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 💪👔👍 Business logic 👍👍👍👍 Reusable ⚛⚛⚛⚛ React to changes 🤔 Changes can be implicit Totally arbitrary emojis • so basically CPs are great for business logic and have potential for reuse in other ember objects • they update when dependents change, but you can 'subscribe' to these explicitly by specifying keys • however it can be sometimes difficult to trace why a CP recomputes IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 HELPERS • helpers can be simple functions or class based • they don't have a DOM element and are simple to debug – you know where the data is coming from, and what comes out of it • just like CPs, we should strive to keep these pure and free of side effects
  • 55. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 {{#each (repeat 3) as |nil index|}} <div data-thing={{concat "foo-" index}}> {{!some HTML block}} </div> {{/each}} https://github.com/DockYard/ember-composable-helpers#repeat • helpers are best suited for generic utility functions, and are especially useful for UI logic • for example, this little helper repeats the block inside of it, 3 times • it's non-business logic related but helps us DRY up our templates, so you can use this nice markup instead of copy pasting a block of HTML 3 times IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 {{capitalize "hello"}} {{capitalize "hello"}} • another thing to note about helpers is that ember doesn't guarantee that multiple uses of the helper will actually run at any given point • for example, this capitalize helper will only run once, even though it's used 2x • this is a good thing as it means ember can optimize rendering • but that means helpers must be carefully written to not
  • 56. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 export function toggle([obj, prop]) { return function() { set(obj, prop, !get(obj, prop)); }; } https://github.com/DockYard/ember-composable-helpers#toggle • you may or may not be surprised to note that helpers can be used as an action if it returns a function • again, this is really useful for expressing UI logic, we might use this toggle helper to toggle a dropdown or a popover IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 <button {{action (toggle this "isExpanded")}}> {{if isExpanded "I am expanded" "I am not"}} </button> • you can then use your action helper like this, • which is much nicer than defining yet another `toggleIsExpanded` action in your components
  • 57. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 🎨🖌 Express UI logic ✍❤📖 Composable 😶💭 Simple mental model 🏃 🏃 Can be used as action 🕵🔬🔍 No hooks available (yet) Totally arbitrary emojis • so helpers are great for UI and presentational logic • & inherently composable with sub-expr or nested helpers • they're easy to understand and can also be used as actions • & bc they're still lightweight implementations, we sometimes have to use observers to recompute IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 COMPONENT HOOKS • component hooks are also a nice explicit way of handling computation • for example, when props change from the outside, we can handle it easily • however, they can be quite tricky to use, so you should prefer a CP unless you know why you need to use a lifecycle hook
  • 58. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 export default Component.extend({ didReceiveAttrs() { this.updateChart(get(this, 'data')); }, updateChart(data) { // update the chart's data } }); • lifecycle hooks are best used when you need side effects, and should be preferred over an observer • for example, you might have a component that wraps a chart library which has some kind of render method • you can use a hook like `didReceiveAttrs` to update the chart whenever new data flows into the component IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Initial Render init didReceiveAttrs willRender didInsertElement didRender External attr changed didUpdateAttrs didReceiveAttrs willUpdate willRender didUpdate didRender Internal value changed willUpdate willRender didUpdate didRender • this is a simple diagram showing the order of hooks that fire when components render or re-render • when using these hooks, its important to think about whether the changes are 'idempotent' • in other words, these hooks should work no matter how many times they are called • as you cannot easily control the order and timing of the hook
  • 59. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 export default Component.extend({ didRender() { // this is an infinite loop that will crash your browser let isFoo = get(this, 'isFoo'); set(this, 'isFoo', !isFoo); } }); • for example, this might look like fairly innocent • you might want to toggle some property after a component has rendered • but because it has side effects, it will cause a re-render, which fires the `didRender` hook again, which re- renders, and so on until your browser explodes IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 🐘💨🙊 Dealing with side effects 😭➿😱 Can cause infinite loops 🔨🔨 "Just re-render it" 🚀🚀🚀 Not invoked in FastBoot environment Totally arbitrary ratings • in a nutshell, lifecycle hooks are useful for replacing observers and for controlling side effects • however, they can also be potential footguns, as you can easily cause an infinite loop or sync issues if your logic is not idempotent • so use them with caution
  • 60. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 SHOULD I USE AN OBSERVER? • and finally the age old question, should i use an observer??? • this topic has been covered quite in detail already, IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • but basically, you almost never want to use an observer • they're low level primitives used by ember so you don't have to • as i mentioned earlier, the only place it is ok to use one is in a class based helper bc no lifecycle hooks are implemented yet
  • 61. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 https://youtu.be/vvZEddrClAQ • you should remember that every time you use an observer, Stefan Penner dies a little inside • so don't do it • and watch his Wicked Good Ember talk on observers IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 THE FUTURE • i want to close off the talk by briefly mentioning what we can learn from game renderers • and what the future might hold for how we build web apps
  • 62. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • game renderers are surprisingly similar to web applications • this diagram shows the rendering architecture for Doom 3 • there is an idea of a "front end" and a "back end" as well as an Intermediate Representation (IR) that sits between IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Game world state Front End IR Back End DirectX / OpenGL OS Screen • the front end captures the state of the world and determines what contributes to the view • this is then expressed as an IR, which is then passed into the backend where it goes through a hardware abstraction layer like DirectX or OpenGL before reaching your GPU and then your screen
  • 63. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Application state Front End HTMLBars Glimmer DOM APIs Browser Screen • an ember app is similar • we capture the state of the app and determine what to render • our templates go through HTMLBars and Glimmer, and then to DOM APIs • this is then taken by your browser and rendered onto your screen IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • so if games and web apps are so similar • how can games that are so much more complex and graphically rich sometimes run faster than a web app?
  • 64. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Hidden blocks rendered, CPU time wasted Line of SightCamera Without occlusion culling • the answer is that games are heavily optimized to make use of your GPU IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Hidden blocks not rendered, CPU time saved Line of SightCamera With occlusion culling • & use a bunch of tricks like occlusion culling to optimize rendering performance • i'm really excited to see the trailblazing work Chris Thoburn (@runspired) is doing in this area, you should follow him for updates
  • 65. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • in fact, Mozilla is actually working on an experimental web renderer for Servo, that aims to draw web content like a modern game engine • early prototypes are able to render at hundreds of FPS IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 https://air.mozilla.org/bay-area-rust-meetup-february-2016/#@1m53s • i won't go into further detail, but you can check out the video for more info • i think web apps have a lot to learn from game rendering, and i'm excited to see us moving in that direction to optimize performance
  • 66. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 TL;DR • to summarize IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • we looked at the state of javascript and we saw that ember is going to closely align itself to new features from ES2017 and beyond
  • 67. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 I. Data Down, Actions Up? II. Controllers are Dead III.Declarative & Composable Templates • we then looked at what DDAU means and how to implement it by keeping in mind who the owner of the data is • and to avoid mutating data directly IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 I. Data Down, Actions Up? II. Controllers are Dead III.Declarative & Composable Templates • then, we cleared the air on controllers • routable components and services are superior impl • & will still play the part of a controller, which is to decorate a model • we also looked at using ember-route-action-helper for using route actions in templates
  • 68. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 I. Data Down, Actions Up? II. Controllers are Dead III.Declarative & Composable Templates • and finally, we looked at ways to power up your handlebars templates • helpers are a great way of performing UI logic in a composable and easily testable way • you can write your own or use ember-composable- helpers to make your templates more declarative IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • i want to thank dockyard for allowing me to give this talk and being an awesome place to work at
  • 69. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 • we're organizing the WickedGoodEmber conference this june, so please check out our website for more info IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 🐰 LAUREN TAN SUGARPIRATE_ POTETO • once again, please get in touch if you have any questions
  • 70. IDIOMATIC EMBER – FINDING THE SWEET SPOT OF PERFORMANCE & PRODUCTIVITY EMBERCONF 2016 Thanks! 🐰 LAUREN TAN SUGARPIRATE_ POTETO • remember to speak to me if you're interested in working AT or WITH DockYard • and i'll give you a sticker too • thank you all so much for listening!