Idiomatic Ember: Sweet Spot of Performance and Productivity
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 37 | |
Author | ||
License | CC Attribution - ShareAlike 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/34703 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
EmberConf 201622 / 37
4
5
7
10
11
13
14
15
16
17
20
23
24
25
26
27
29
30
31
32
00:00
VideoconferencingCodeScripting languageJava appletEuclidean vectorGroup actionSynchronizationConvex hullElectric generatorRule of inferenceConcurrency (computer science)Task (computing)Function (mathematics)Game controllerDeclarative programmingTemplate (C++)Query languageComponent-based software engineeringDefault (computer science)VolumeKeyboard shortcutStatisticsMedical imagingGroup actionConfiguration spaceRight angleSoftware frameworkCASE <Informatik>InfinityState of matterFilm editingConnectivity (graph theory)Multiplication signNumberClient (computing)Computer programmingNatural numberStapeldateiAxiom of choiceSingle-precision floating-point formatGame controllerDataflowWeb 2.0Category of beingRoundness (object)DiagramView (database)Source codeMobile appSemantics (computer science)Dimensional analysisTask (computing)AngleShared memoryResultantPropagatorWeb pagePoisson-KlammerOpen sourceSoftware developerOperator (mathematics)HorizonMathematicsVideoconferencingLevel (video gaming)InformationNeuroinformatikService (economics)Cartesian coordinate systemRow (database)Data storage deviceAddress spaceImplementationPattern languageCore dumpBitCodeDefault (computer science)Generating functionFormal grammarCovering spaceWeb applicationSoftware maintenanceWeight functionBuildingOnline helpDifferent (Kate Ryan album)Keyboard shortcutLibrary (computing)Limit (category theory)Order (biology)MereologyQuicksortMultilaterationMessage passingIdempotentProduct (business)RoutingStandard deviationFunctional (mathematics)Slide ruleWeb-DesignerAttribute grammarPlug-in (computing)Goodness of fitProcess (computing)Open setPivot elementArithmetic meanWritingOcean currentSoftware testingXMLComputer animation
09:54
Configuration spaceDefault (computer science)Service (economics)Game controllerAbelian categoryView (database)Euclidean vectorTemplate (C++)Group actionProduct (business)Installation artDecision tree learningDeclarative programmingDew pointFunction (mathematics)Electric currentDrop (liquid)Computer fileOrder (biology)Venn diagramGame controllerDefault (computer science)Category of beingService (economics)State of matterProgramming paradigmConnectivity (graph theory)LogicRow (database)WordAlgebraic closureOperator (mathematics)Decision tree learningQuery languageGroup actionView (database)Functional (mathematics)ImplementationSeries (mathematics)AdditionDeclarative programmingMereologyExistential quantificationInheritance (object-oriented programming)Endliche ModelltheorieString (computer science)SpacetimeNatural numberLine (geometry)Presentation of a groupTemplate (C++)RoutingParameter (computer programming)Shared memoryCartesian coordinate systemState observerMultiplication signMixed realityFormal languageLocal ringBitLevel (video gaming)Translation (relic)Bookmark (World Wide Web)Inverter (logic gate)Mobile appSign (mathematics)Different (Kate Ryan album)MathematicsNeuroinformatikOcean currentCycle (graph theory)Video gameObject (grammar)1 (number)FreewareProgramming languageRegular graphPower (physics)Classical physicsProcess (computing)NumberCuboidRaw image formatShape (magazine)Instance (computer science)Revision controlCovering spaceCASE <Informatik>Social classBlock (periodic table)Type theoryArithmetic meanEllipseComputer animation
19:36
Euclidean vectorFrequencyDivisorMathematicsBit rateDefault (computer science)Key (cryptography)LogicCategory of beingFunction (mathematics)Android (robot)Hardware description languageData modelGroup actionExpressionVolumenvisualisierungWeb browserInfinityLoop (music)Arithmetic mean1 (number)Macro (computer science)Category of beingNeuroinformatikSoftware testingLogicConnectivity (graph theory)Template (C++)Directed graphGroup actionCausalityVector potentialMathematicsMultiplication signWindowOrder (biology)Cellular automatonCASE <Informatik>Service (economics)Game controllerEndliche ModelltheorieWordSpreadsheetEvent horizonFehlererkennungAnalogyTouch typingVideoconferencingIdempotentProjective planeSpring (hydrology)Domain nameCartesian coordinate systemState of matterMotion captureSimilarity (geometry)NumberGame theoryKey (cryptography)Conservation lawBlock (periodic table)Functional (mathematics)TouchscreenDiagramIntermediate languageUtility softwareFront and back endsGeneric programmingComputer architectureVolumenvisualisierungDebuggerState observerSocial classInverse elementFirst-person shooterVideo gameComputerWeb applicationPrimitive (album)Level (video gaming)WebsiteExpressionLibrary (computing)DistanceGraphics processing unitHookingRandomizationInformationContrast (vision)CodeRight angleWeb browserMereologyPresentation of a groupCodeCycle (graph theory)Point (geometry)FreezingImplementationLattice (order)InfinityLoop (music)Direction (geometry)MappingOnline helpContent (media)Web 2.0PrototypeMultiplicationFrame problemMarkup languageSummierbarkeitObject (grammar)Capillary actionGoodness of fitExplosionMobile appComputer hardwareAbstractionView (database)SynchronizationCopyright infringementPower (physics)RoutingArtistic renderingError messageMehrplatzsystemComputer animation
Transcript: English(auto-generated)
00:17
or idiomatic ember apps that are both performant and, if you can't see the slides clearly,
00:23
you can look them up on bit.ly idiomatic-ember. That's idiomatic-ember. But first, we have a heavy heart. Let's address the elephant in the room. What's an idiomatic talk without idioms? They say time is money, so I'm just gonna cut to the chase.
00:42
My name is Lauren, and I was born in the year of the rabbit. You can find me on the interwebs as chugapirate or potato on GitHub. When I'm not working on client work or open source, I sometimes play Final Fantasy XIV. It's an MMO that can be quite addictive, but thankfully, I have a little puppy Zelda who keeps me grounded in reality.
01:01
Unfortunately, she couldn't be here today to give this talk, so you'll have to listen to me instead. 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 as very many open source libraries, including Ember Add-Ons. In two days, it'll be the end of my first year at Dockyard.
01:21
I have to say, it's been one of the best jobs I've ever had. The best part is we're hiring senior Ember engineers, so please talk to me, Brian, Martin, or Estelle later if you're interested in finding out more. If you come speak to me after my talk, I'll give you a very limited edition chugapirate sticker. Now, before we start talking about Ember,
01:40
let's look at what it's like to build a modern JavaScript app in the year 2016. React has been steadily gaining ground in Mindshare and for good reasons. Some of its ideas have even made their way
02:01
into Ember and other frameworks. But despite how far we've come from our early days, modern web development is getting really hard. I mean, it used to be so simple, right? In the good old days, all you needed to do was write some HTML, maybe some CSS, slap some jQuery on a page, and use a plugin or two or five.
02:21
But these days, we spend so much time configuring things, and we spend valuable time writing glue code and configuration instead of working on what matters for our applications. And you have to make a ton of choices for your front-end stack, which can be quite paralyzing. And in some cases, it's also really easy to build a tangled web of dependencies,
02:40
which can lead to all sorts of problems. It's tempting to fall victim to JavaScript hype and try to build your own makeshift framework that might end up slowing you down because you have to make sure everything plays nicely together. So why go through that pain? But that's why we use an opinionated framework like Ember, right?
03:01
With Ember, we opt into convention over configuration, and problems are shared across the community because chances are your app isn't a special snowflake. These strong standards have given the Ember community hands down the best tooling experience available. We have things like the Ember CLI, Ember Inspector, more than 2,000 add-ons, which is an incredible number,
03:20
and all of this would not have been possible without you, the community. 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 really easy. There are a few people in there that don't seem to sleep, so if you have a question, there is almost always someone available to help you out.
03:40
Now, because Ember is so 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 experience in building web applications. Now, with Ember 2.0 being released last year in August, quite a few things have changed since then, and those changes are the main motivation for my talk.
04:01
For example, there has been a lot of discussion around data down, actions up. This is a pattern for one-way data flow that we've adapted, and it's meant to make your apps easier to reason about and maintain. I'm gonna cover this in more detail later. We've also established conventions that single-sense states should live in a service instead of a controller. Services are excellent for handling the long-lived state of things,
04:21
such as shopping carts, activity feeds, and notification messages. Now, actions have been getting a little confusing in Ember 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. And we also know that controllers are going away sometime in the future.
04:41
I'll talk a little bit more about what that really means, and share some techniques you can use to ease the transition to a routable component. So in a nutshell, things have changed, and dealing with changes can be hard. These changes can be difficult to deal with, because things that used to be best practices may no longer be true, and there is a general lack of updated information
05:02
about the proper way of doing things. By 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 gonna play a pivotal role in Ember's future. For example, you can already use decorators today
05:20
using RWJBlue's excellent add-on. This is currently a stage one proposal, but it's incredibly useful for drawing out your code, and the most obvious example is with a computed property. As you can see, this is a lot nicer than what we have to do today. Async await functions are also on the horizon, and are one stage away from being included into the spec. These let us write asynchronous operations
05:41
as if they were synchronous. Now, if you've ever been trolled by promises or async programming like I have all the time, for example, in RWJBlue's RC for making tests great again describes how we might make use of async await to clean up our tests, and as a result, our tests will be a lot easier to read and follow.
06:01
Generator functions are also already a part of ES2015, and they're really cool. They allow you to write cooperative code, meaning you can pause, resume, restart them, as well as end them early, and these are so powerful that you should check out markd's add-on, Ember Concurrency, which I'm sure you've heard a lot of. It allows you to write tasks to do things you would have a really hard time replicating
06:21
without a generator function. So as you can see, when you use Ember, you're betting on JavaScript, and we're gonna become more closely aligned with the latest JavaScript features, meaning you'll be able to write more JavaScript and less Ember. I think it's fair to say that Ember is the solution to JavaScript hype fatigue, and that is why I'm really excited to give this talk,
06:41
because with Ember, we no longer have to sacrifice performance for productivity. So in this talk, I wanna cast away any doubt you might have about what the Ember way really is, and hopefully you'll be able to take away some ideas you can use straight away in your apps. Very broadly, I'll be speaking about patterns and anti-patterns in modern Ember apps.
07:01
First, let's talk about an important concept. Data down, actions up is one of the core principles that drive a modern Ember app. By architecting our applications in this manner, we can build apps that are easier to maintain and reason about. Data down, actions up describes the flow of data through your app. For example, this is what your app might look like
07:21
once routable components land. You fetch data from your API, which gets normalized and pushed into your Ember data store. These records then get passed in as attributes to a routable component, and child components send actions up to modify that data. You might have noticed controllers were missing from that diagram, and that's because they're gonna be deprecated and removed in the future.
07:42
But why remove controllers if they already work? Well, the core team found that a component could easily take the place of a controller in view, as components are superior implementations. Does this mean the death of MVC? No, but there has been a lot of confusion on this topic, so I'm gonna address this in more detail later.
08:03
What React taught us is that the biggest problems 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 can very easily cause an infinite cascade of changes if you're not careful. When glimmer or angled bracket components land,
08:21
data bindings will become one-way by default, and instead of mutating data, we will send actions up to update it. And this becomes a really nice, functional way of building applications that are still reactive and easier to reason about. By ignoring two-way bindings, and instead focusing on re-rendering multiple times efficiently through glimmer, we can have changes propagate immediately
08:41
without introducing all the cascading semantics of a two-way bind. And this will be made possible with one-way data flow and making renders pure and idempotent. With data down acted up, a guiding principle is to ask, who owns the data? Only the owner should be allowed to modify it. And this is particularly important when the data is application state,
09:02
which we should strive to keep as single sources of truth. For example, here's a diagram of what a simple Ember app might look like on a given route. Let's say that component A is only allowed to show one child component at a time. And perhaps after doing some configuration in a child component, we need to programmatically show the next one.
09:21
Now where would the best place be to do that? If we follow the data down act as our principle, we need to ask ourselves, who owns the data? And in this case, which configuration component to render is the concern of component A, as it owns the shared state of all of its children. So in order to mutate the current step property, we need to send an action out to component A.
09:43
What we must avoid doing is mutating the current step in the child component. It's a subtle difference, but it means an app that is easier to reason about and maintain. And you won't need to spend hours figuring out who's changing what, because you know there's only one place it's being changed. But the action is changing the property anyway, so why not just do it directly?
10:02
Well, when you change the state that somebody else owns, you're stealing. And effectively, it means that the owner no longer controls the data, and you bypass the owner's interface. However, in the future, luckily for us, these problems will go away. Glimmer components will be one way by default. So even if you try mutating current step
10:20
in the child component, it would not flow up to mutate the current step property of the parent component, unless you explicitly opt into doing so with the mute helper. Another thing to note is that services can also own their own data, and this is an important part of data down actions up and the Ember programming model. And this will be especially important to know when routable components land,
10:42
as singleton state must be moved into a service, because components are stateless. So with data down actions up and routable components coming, what do we do with controllers? So as I mentioned earlier, controllers aren't completely dead yet, and you shouldn't try to avoid them unless you really want to.
11:02
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's gonna be implemented as a routable component instead. You might still need to use a controller right now if you need query parameters,
11:20
or in certain cases, a bubbling action. But these will be moved to the route eventually when routable components land, so as I said before, don't get too creative in trying to remove controllers. You should only do it when it makes sense. Ember 1.0 was a straightforward implementation of MVC. We had a controller and a view. But we've deprecated views in favor of components,
11:42
and it turns out that what the controller and view was doing could be better handled by a component and service. So the routable component was introduced, and 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 still do the same things, which is decorate a model. A simple concept is to think of a routable component
12:03
as the unification of what we call a controller and view. And there are things you can do today to make this transition easier. Again, this is optional, you're not forced to do it, but it's a nice way to make your application a little bit future-proof. The first key thing you can do is to move your route level template
12:21
into a top-level component. When routable components land, it basically just moves that invocation into the route implicitly. 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
12:41
is most likely to be future-proof and will make the transition an easier one. 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 still remain on your routable component
13:01
or controller. There are some gotchas with moving controller actions to the route, though, so I'm gonna share a way to do so a little later. But first, let's take a look at actions. Currently, I'm sure you'll agree with me, actions can be a little confusing in Ember. For example, you could define a classic action on the first line
13:20
by giving it a string property of the action name, or you could use a new style action on the second line. As a best practice, you should always prefer to use the new style or closure action. A new style action is essentially just a JavaScript function, which means you can do things like make use of return values, partially apply arguments, and more.
13:42
While classic or string actions are very implicit in nature and make things hard to debug. For example, it would be really easy to mistake submit for a string property and it would be difficult to trace where the action actually lives. And another thing is when you use classic actions, you have to remember to use send action in your components, which I kind of dislike,
14:01
and to me, it's kind of like sending your action into space. Because you send it up somewhere, you hope something's listening to it, you know, who knows where it's going? And the worst part is it never comes back, but for return values, it's kind of useless. But 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.
14:22
Now don't let the word closure action or new style action scare you, it's really just a JavaScript function. As I said earlier, you have return values, and this is especially useful when dealing with asynchronous operations like saving a record. You can return the same promise and then handle it from inside your component. For example, you might want to handle success or failure states.
14:42
So new style actions are awesome, but out of the box, you can only use them if they're defined on your controller, as they do not bubble like classic actions do. But if you want to move your actions that deal with data to the route, this seems kind of lame. So RWJBlue and I built a little add-on you can use today, and it's called the Ember Route Action Helper.
15:01
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. Now if you recall, controllers without routes could be created, and that was a common practice to manage singleton state with them. A service is a long-lived singleton
15:20
we can use to manage long-lived state. A great example for a service is a shopping cart or activity feed. For things that have singleton logic, you can extract that logic into a service and then inject it into the objects you need to. A shopping cart is an excellent example of a service because it can only be one singleton cart in the application, and it needs to have long-lived state throughout the life cycle of your app.
15:43
And you can implement a cart with as little as setting a property on a service to be an array, or you could do more. But what we must be really 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 really bad sign and should stop.
16:01
Instead, you should adhere to data on actions up and not use a service for something that doesn't need long-lived state. Now I want to talk about templating, something I'm sure is close to all of our hearts, keeps us up at night. Another of my favorite new things in Invert is the new helper implementation. This was introduced in 1.13, and it's great for expressing presentational logic.
16:22
For example, this equal helper can be found in the Ember Truth Helpers add-on, which we pretty much use for all our apps. Ember itself also ships with a bunch of really useful helpers like concat, hash, and the get helper, and the best thing about helpers is it basically lets you power up your templates. Again, because Ember is converging
16:41
towards just being JavaScript, a helper is kind of just like a regular JavaScript function. And one of the reasons I like helpers so much is that it forces you to keep your functions small and free of side effects. You can basically create two kinds of helpers. This one is a simple one that will recompute every time the parameters change. But for more complex needs,
17:01
you can also make a class-based helper, which is essentially an Ember object similar to the ones you've already been using. And this means you can do things like define computed properties on it, use a service, and so on. For example, this is a helper that looks up translations on the locale service. And specifically, you might want to listen for a change in locale,
17:20
and then all the translations using this helper should automatically update, even though the locale itself was never passed into the helper explicitly. Some of you might have noticed I used an observer in my previous example. Class-based helpers are currently the only place it's okay to use one because helpers are still a lightweight implementation, almost an MVP,
17:41
and its lifecycle hooks are not implemented yet. But when those become available sometime soon, maybe, we can use them to recompute instead. Another reason, 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
18:01
because we're mixing data and UI logic together. So one thing you could do is split them up into two 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. Let's say we had a hypothetical helper called pipe. It would let you take the return value from one action and pass it along to the next one,
18:22
and it would keep passing that value down to each function in the pipe. If you've used the programming language Elixir before, this pipe helper is essentially the same as the pipe operator, which lets you express the above, which really isn't very nice to read, as a series of data transforms, and this is a lot easier to read and understand
18:41
compared to the first example. And since we use Elixir so much at Dockyard, it was a language feature we wanted to use in Ember. So the pipe helper was born to let you compose small, pure actions to allow more declarative templating. In this example, the item argument at the end gets passed into the first action, and then its return value gets passed into the next.
19:02
As you can see, helpers are really powerful tools to extend templating in your application. And together with my colleague, Martin Schillstra, we've built an add-on called Ember Composable Helpers, which contains the pipe helper and other declarative helpers. Now the best part about helpers is composability. Helpers can do things that might be more complex
19:22
to express in your component. Using the pipe helper example again, you don't need to define two separate actions called save and quit, and save and close, and save and blah. You can just compose them directly. That said, you should not get too ambitious with nesting helpers inside of each other, and when your template looks like this, you're better off using a computed property instead.
19:44
It can be very easy to get carried away with using helpers, and how much logic you want to have in your templates depends on your comfort level and experience. So please use them with caution and exercise best judgment. But the point is, helpers are better suited for dealing with UI and presentational logic, which quite often is highly abstract
20:02
and unrelated to the data in question, in contrast to computed properties, which are highly often coupled with data. But that brings us to our next question. When we do need to perform computation, what is the best way? Generally speaking, we have three ways of doing so. You could express it as a computed property,
20:22
use a helper in the template, or use a component hook. Each approach has its pros and cons, so let's look at when we should prefer to use one over the other. Computed properties are one of the first things you learn about in Ember. They can be really powerful or really simple, and are a nice way of keeping some computation up to date. But these auto-updates can be a double-edged sword,
20:42
because observing changes are implicit, so when a computed property recomputes, you don't always know why it did. The best analogy for computed property is an Excel spreadsheet. It would be really painful to sum A1 and B1 by placing event listeners on their cell and then getting their DOM values. A computed property lets you declaratively
21:01
express that logic that changes automatically when the dependents change. And I would recommend using computed properties for expressing business logic. One of the best things about computed properties is that they can become reusable macros. And you can extract a computed property into a macro by creating a function that returns a computed property.
21:21
You can then pass in any arbitrary keys or values into the macro, and then you can import it and use it like you would any other, like the ones that ship with Ember, like computed and computed or, et cetera. And this is a great way to dry up your code and test your business logic. Another awesome thing about computed properties is that they are cached, meaning expensive work
21:43
is only done when it needs to be done. So basically, computed properties are great for business logic and a potential for reuse in other Ember objects. They update when their dependents change, but you can subscribe to these explicitly by specifying the keys that the computed property observes.
22:00
However, it can be sometimes difficult to trace why a computed property recomputes. Helpers can be simple functions or class-based. And they don't have a DOM element, but they're simple to debug. You know what goes in and what comes out. And just like computed properties, we should strive to keep these pure and free of side effects. Helpers are best suited for generic utility functions
22:22
and are especially useful for UI logic. For example, this little helper repeats the block inside of it three times. It's not really related to the business domain at all, but it helps us dry up our code and templates so you can use this nice markup instead of copy-pasting a bunch of HTML X number of times.
22:41
Another thing to note about helpers is that Ember doesn't guarantee that multiple users of the helper will actually run at any given point. For example, this capitalized helper will only run once, even though it's used twice. And this is a good thing as it means Ember can optimize rendering. But what that means for you is that helpers must be carefully written to not rely on side effects.
23:02
You may also be surprised to know that helpers can even be used as an action if that helper returns a function. Again, this is really useful for expressing UI logic, and we might use this toggle helper to toggle a dropdown or a popover or something else. And then you can use your action helper like this,
23:21
which is a lot nicer than defining yet another toggle is expanded or toggle is displayed or toggle whatever action in your components. So helpers are great for UI and presentation logic, and they're inherently composable with sub-expressions and nested helpers. And they're also really easy to understand and can be used as an action, which is really cool. And because they're still lightweight implementations,
23:42
we sometimes have to use observers to trigger recomputation in the class-based helper. Component hooks are also a nice, explicit way of handling computation. For example, when properties change from the outside, we can handle it really easily. However, component hooks can be quite tricky to use,
24:01
so you should prefer to use a computed property unless you know why you need to use a lifecycle hook. Lifecycle hooks are best used when you need a side effect, and they 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 the receive adders
24:21
to update the chart whenever new data flows into the component. This is a simple diagram showing the order of hooks that fire when components render or re-render. And when using these hooks, it's really important to think about whether the changes in your hook are idempotent. In other words, your hook should work no matter how many times they're called
24:40
in the initial or updating case, as you cannot easily control the order and timing of these hooks. For example, this might look fairly innocent, and you might wanna toggle some property after a component has rendered. But because this hook has side effects, it will cause a re-render, which fires the did render hook again, which re-renders, and so on until your browser explodes.
25:04
So in a nutshell, lifecycle hooks are useful for replacing observers and for controlling side effects. However, they can also be potential foot guns, as you can easily cause an infinite loop or cause sync issues if your logic isn't idempotent. So please use them with caution.
25:22
And finally, the age-old question, should I use an observer? This topic has been covered quite in detail already, but basically you almost never want to use an observer. There are low-level primitives used by Ember, so you don't have to. And as I mentioned earlier, the only place it's okay to use one right now is in a class-based helper, because no lifecycle hooks are available to use yet.
25:43
So please remember, every time you use an observer, Stefan Penner dies a little inside. So don't do it. And please watch this wicked good Ember talk on observers. It's really great. I want to close off the talk by briefly mentioning what we can learn from game renders and what the future might hold for the way we build web applications.
26:04
Game renders are surprisingly similar to web applications. This diagram shows the rendering architecture for Doom 3, a popular first-person shooter. There is an idea of a front-end and a back-end, as well as an intermediate representation that sits between. The front-end captures the state of the world
26:20
and determines what contributes to the view. This is then expressed as an intermediate representation, which is then passed into the back-end, where it goes through a hardware abstraction layer like DirectX or OpenGL, before reaching your graphics card and then your screen. Similarly, an Ember app captures the state of your application and determines what to render.
26:42
Our templates go through HTML bars and Glimmer, then through DOM APIs, and this is then taken by your browser and rendered onto your screen. But if games and web applications are so similar, how come games that are so much more complex and graphically rich sometimes run faster than a web app?
27:01
The answer is that games are heavily optimized to make use of your graphics card, and they use a bunch of tricks like occlusion culling to optimize rendering performance. I'm really excited to see the trailblazing work Chris Thorburn, or Ranspired, is doing. You should follow him for updates. And in fact, Mozilla is actually working on an experimental web renderer for Servo
27:23
that aims to draw web content like a modern game engine does. And early prototypes of this renderer are able to render existing websites at hundreds and hundreds of frames per second, which is very exciting. Now, I won't go into too much detail about this, but you can check this video out for more information. But I think web apps have a lot to learn
27:41
from game rendering, and I'm excited to see us moving in that direction to optimize performance. To summarize, 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. We then looked at what data down actions up means
28:00
and how to implement it by keeping in mind who the owner of that data is and to avoid mutating data directly. Then we cleared the error on controllers. Routable components and services are superior implementations, and will still play the part of a controller, which is to decorate a model. We also looked at using the Ember Route Action Helper for using route actions in your templates.
28:22
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 you can use Ember composable helpers to make your templates more declarative. I want to thank Dockyard for allowing me to give this talk and for being an awesome place to work at.
28:41
We're organizing the Wicked Good Ember Conference this June, so please check out our website for more information. Once again, please get in touch if you have any questions. And remember to speak with me if you're interested in working at or with Dockyard, or if you have any questions about the talk. And I'll also give you a Sugar Pirate sticker tube. Thank you all so much for listening.