 since Ember is becoming more and more template driven. So as Jamie says, my name is Lauren, and I was born in the year of the rabbit. You can find me on Twitter as Trigopirate with an underscore or on GitHub as potato with an E. When I'm not working on open source or just work in general, I sometimes play Overwatch. It's quite an addictive game. But thankfully, I have a little puppy, Zelda, who keeps me grounded in reality because I have to take her out for walks and stuff. She's almost a year old now, and I miss her a lot. She's back in Boston. Wish I could have brought her here, but unfortunately, I couldn't. And so a year and a half ago, I was still living in Australia. And I moved to Boston last year to work at Dockyard. Dockyard works on a ton of Ember and Elixir applications, as well as very many open source libraries, including Ember and Elixir. It's been a really amazing experience working at Dockyard, so it's a little bit of a bittersweet moment for me. But this month, I'll be leaving, and I will be starting work at Netflix on the Studio Apps team, where I'll be helping to build tools for producing Netflix originals. So that means I'll be moving to California, so hooray warm weather. Now the title of the talk is a bit of a troll statement. I mean, you could probably write an application in Ember app without handlebars, but you're gonna have a bad time, and you lose out on a lot of things that Ember is good at. Now in case you're wondering why the talk is titled this way, it's based on a really bad pun on a song called Handlebars by Flo Watt. And I mean, it would be actually a really cool trick to be able to write an ever app without handlebars, but just like a bicycle, handlebars exists for a reason in Ember as we shall see in this talk. So when I was still figuring out what to speak about a couple of months ago, I only had a rough idea that I wanted to talk about helpers because I think components get a lot of the spotlight in Ember, but helpers don't get as much love as I think they should. So Jamie, a very wonderful MC, pointed me to a talk by Guy Steele. He delivered this talk in 1998, and it was titled Growing a Language, and it asked some really interesting questions. He asked if programming languages should be small or large. On one hand, a smaller language is quicker to learn. It's quicker and easier to learn, but it takes more work to get going because you have to write your own tools, basically. Whereas a larger language is slower and more difficult to learn, but there are already many tools available for you to use. And as Tom said earlier, the current Ember would be considered a large language because of the object model and just all the mental gymnastics you need to understand before you can get productive in it. Now there was a quote from Guy Steele's talk that I really liked, but I think it was a little bit confusingly worded. So the gist is in his talk is that language design is a pattern for making more patterns or a tool for making more tools of the same kind. So let's explore this idea a little bit more. An Ember app is basically written in a language that you've designed. And you define this vocabulary of UI and your application using components, helpers, and Ember primitives in handlebars. And according to Steele, a language that's ideal for growth is a means that users can easily grow it themselves. For example, the ability to define functions that look like and can be used like primitives is a really good sign that language that the language can grow to suit your purposes and feel more natural to use. And what you end up with is a language of components and helpers that is unique to your application, almost like a domain-specific language or DSL. And as we saw earlier, if you know handlebars, you could very easily build a standalone Glimmer 2 application without Ember itself, which I think is really exciting. So round of applause for the core team. It's really awesome stuff. Now since templates make up such a large portion of our applications, let's first explore the question of how much logic we should have in our templates because I know that's a really big question these days. And then we'll talk a little bit about declarative templating and what it means to have your UI as a language. And finally we'll close off with a few technical tips and tricks to writing good helpers. So a template is basically data with logic embedded in it. And as we shall see, how much logic is a contentious question. Despite a very common claim, handlebars is not a logical template engine. It only restricts what logic is allowed. And given the nature of UIs, a strictly logical templating language wouldn't be very useful and you probably end up finding it to do what you want. And template engines basically exist on a spectrum with sometimes very different philosophies. On one extreme you have template engines like plates where all you can do is interpolate some data into HTML. There is no logic and the engine basically encourages you to keep your templates completely logic-free. And in the middle of that spectrum you have engines like handlebars and mustache which allow some logic but they enforce a separation of concerns. Here you have what looks like some logic in your template but the actual implementation of this greater than helper is in JavaScript land and it's not in the template itself. And of course you have your other extreme where more flexibility and more power is encouraged. Now in programming we don't often deal in absolutes. So one isn't objectively better than the other. I think it really depends on the circumstances and the kind of problems you're trying to solve. But in number the intention of handlebars is to allow template authors to create logic outside of the template and we do this using components and helpers which encourage this separation of concerns by design. So even though it looks like there's logic we encapsulate it outside of it and we use that helper in handlebars as a declarative way of handling that logic. Now sub expressions in handlebars have been around for quite a long time. I think it's almost three years if I'm not wrong but they've only recently begun getting popular in Ember and sub expressions are really great for composition. You can do really interesting things with them but like any other tool it can be abused and it probably will be abused. So deeply nested sub expressions or deeply nested helpers are very much an anti-pattern and should be avoided. The point of a good template is to be declarative and to communicate intent. When you write something like this which is pretty horrible I think we can all agree you should step back and think and basically avoid programming in your template because this is really hard to read. It's also really hard to test and probably very brittle and hard to maintain. And in this particular example you're probably better off using a computed property. Another way to think about helpers is to think of them as computed property macros that you can use right in the template. If you find yourself doing a lot of boilerplate presentational logic where you're just like repeating yourself like a million times across all your components that could be a good candidate for being extracted into a reusable helper. For example many generic computed properties could be replaced with helpers for example like in the Ember Composable Helper Ember Composable Helper add-on which I authored with Martin. The logic is not so extreme that it's programming in your template and the bonus is you no longer need to worry about dependent keys and just trying to figure out what to observe and inherently it becomes more usable. But then I hear you say at this point why not just use JSX. Well there is a rule called the rule of least power also known as the principle of least power and this rule if I'm not wrong originated from the W3C. The reason we use HTML to mark up our documents in the browser is instead of writing code to generate them is basically because the rules suggest to use the least powerful language for a given task. And just like anything in life there is no black and white it's evaluated on a spectrum and it also some ways similar to the question of how much logic should live in your template. A language with constraints like handlebars is straightforward to analyze to read a lot more easier to reason about and in Ember Components helpers and keywords let us express our unique UI in this language that is declarative without having too much logic in the template. The converse of the rule is to use the most powerful flexible solution for a given purpose and usually that means it's quite imperative but you can do anything that is imaginable because there are no constraints. But because of the rule of least power Ember still prefers handlebars over something more powerful and flexible. And it's actually handlebars that is the reason why we could get all these performance benefits that Yehuda and Tom talked about earlier. For example here we have we know that this H1 is static it's value will never change and that the P tag is the only thing in this block of HTML that contains a dynamic value. Now if you inspect the element for this HTML this is actually what Ember will eventually render and you can see that the P tag is actually split over three lines. And that's because Glimmer rendered three tech nodes and since we know that the only tech node is that is dynamic is the name we only need to watch that value for changes and update the DOM accordingly because the other tech nodes are always static. And this kind of optimization is comparatively easier to do in a language with constraints compared to something with unlimited flexibility. Now I spoke about a little bit about keywords and helpers but what is the difference? Remember that Geisel says that a good language design means that user defined functions can also be used just like language primitives and you can basically think of Ember keywords as handlebar primitives which operate on a much lower level. These are all the keywords in the documentation you're probably familiar with most if not all of them. And although you invoke these just like any other component or helper with double curlies they are very different. For example, keywords are reserved they have access to template, the scope, the environment, the morph and so on there's a lot of stuff that keywords have access to. While helpers that you define are only received the positional primers that you pass into it. Here for example it would be model and ABC or options which would look like something like this async equals true. But as we can see in the next part of our talk even though helpers aren't quite as powerful as keywords you can still do really really interesting things of them and again this is the rule of least power at work. So let's explore what declarative templating means. Being declarative means that templates communicate as much intent as possible. You're describing a result you're not telling the computer exactly what to do and that's because templates even more than code are meant to be read. And at the same time the more code you have in your app the more likely you are to have bugs and nobody likes bugs. And relying and being able to rely on generic well tested helpers and components means in some cases you can actually remove that unnecessary logic that you don't have to maintain yourself. Templates are the blueprint to describe the result you want. Instead of embedding data and code we turn things inside out and we embed code inside data. Conversely here we're embedding data inside code and this produces HTML only as a side effect. The code doesn't really describe the result and even though this approach is a lot more powerful and flexible and you can do all sorts of crazy things the previous example was much more easier to reason about and maintain. Embedding logic in data is what modern template engines use and because ember is becoming more and more template driven let's look at the spectrum of logic again. There is a fine balance to be achieved here. Obviously we can't have no logic at all but then you don't want to get too extreme either and have logic everywhere in your templates so let's look at some examples. Here we have a very simple computer property that returns an array of employees that are filtered. The logic for this lives on our component as a computer property and this is still fine, fine and dandy since the logic isn't very complicated. In fact I could have probably used a computed property macro here I think. And now let's say you wanted to group those filtered employees by role or if you wanted to do some more say intermediate processing on that this array of employees you have to add more presentational logic to your component that you now have to maintain and test and to make things worse if you wanted to replicate this filtering and grouping in another component you now either need to extract these series of computer properties into like this very powerful macro which can be very complicated to write because now you need to determine how to get those dependent keys that you need in order to observe all these like the employees or you might even need to make a mix in which can be very error prone. Now on the other hand you could also use helpers to eliminate those computer properties and do the filtering and grouping directly. Now this approach shifts the presentational logic into the template in a declarative way. I mean you could even take it a step further and compose those helpers together which is a bit more concise but maybe a little harder to read and honestly I think this is definitely the most nesting I would do. And you know which is the better approach I think again it's a very common theme in this talk. That like anything it's a trade off. If you find yourself writing very many boilerplate presentational computer properties that are repeated everywhere you could be better off making a helper to use that as a macro in your template but obviously you don't want to get too carried away because remember you only want some logic non-extreme logic. So again you should strive to stay within a sensible limit and the previous example I showed just now with the grouping and filtering done helpers. In my preference it's probably pushing that limit but really it's up to your good judgment. And again don't program in your template just because you have all these cool helpers doesn't mean you need to abuse them. Handle bar strikes are really good balance in the amount of logic and it's actually really very well designed templating language and enables really nice DSLs like Ember Form 4 written by Martin who's giving a top next because everyone loves building a form, right? So now that out of the way let's look at how we can write some good helpers. There is a documentary called Jiro Dreams of Sushi. Jiro is a sushi chef in Tokyo. He has his restaurant, I think it's underground which is a three Michelin starred restaurant and he's basically devoted his life to sushi. And it's a really good documentary I highly recommend watching it if you like food in general. Now in this documentary Jiro said something that has stuck with me for a very long time something I'm unable to forget. He said that you must eat delicious food in order to make delicious food and you can't make good food without good taste. And I think this quote applies to programming as well and creative pursuits in general and this belief was even more so after listening to Guy Steele talk on growing a language. In other words to write in the context of Ember and Ember can to write good helpers we should first understand what good helpers might look like. A good helper must be pure because Ember makes no guarantees that multiple users of a helper will run at any given point. For example this capitalized helper will only be run once even though it's being used twice and this is really good because it means Ember can optimize rendering but that means helpers must be carefully written to not rely on side effects. Here is a really simple addition helper with no side effects. It's just taking A and D and returning that value. And because it's a pure function it will always yield the correct result no matter how many times it's rendered. And then here's a really bad example of an impure helper with a side effect. I hope no one has ever written something like this. This will lead to all sorts of strange behavior especially since Glimmer is all about re-rendering things in an optimized way. But yeah again pure functions will always give us the correct results no matter how many times rendering is performed. Now you're probably thinking that was obvious I would never write code like that. And it's simple because values in JavaScript are immutable but you have to be really careful when your arguments are an object or an array because in JavaScript objects and arrays are passed by reference. So here I've written what looks like a helper to sort an array. I don't know if you can see what the problem is straight away. But what I mean by passing by reference means that in simple terms when you modify this object or array it will actually modify that for everyone else. And the previous sort helper that I showed just now is flawed because when the helper first runs it mutates the array that was passed into it. And now that original array of numbers over here you see that it used to be two five four one three but now when I invoke it again it's become the sorted array which is not really what I want. So yeah, so be careful when you deal with objects or arrays as arguments in your helpers and if you need to you should make, try to make a copy of that array or object instead. Another thing when designing helpers is to think of them as ways to use modules or add-ons or a kind of entry way to some code that you've written right in your template. For example, I recently made an add-on called EverChangedSet. A change set is essentially a collection of atomic changes that you apply onto some model or object. And this add-on was inspired by Ecto which is an Elixir library that is a DSL for creating SQL queries. And EverChangedSet is basically a really functional approach to modifying data and making sure that those modifications are validated. So let's look quickly at how I use the helper as the main interface for creating these change sets. Now the logic for the add-on is roughly like this. It takes some object or some model and it returns you a change set. But creating this change set in JavaScript land doesn't communicate intent as much as in the template. And the helper itself is actually quite simple and it abstracts away the logic that you need to know about, to create these change sets. And now in your template it's way more explicit and declarative because now I can tell straight away just from reading my template what is a change set and what is a model. And you can also easily tell how it's validated. It may or may not be obvious from what I just mentioned but whatever your helper returns dictates how it's used. When returning these primitives it's pretty straightforward and not surprisingly they just yield the value. There's nothing too exciting about this. You should be pretty comfortable with these kind of helpers. But it does get a little bit more exciting when your helper returns an array. Here is a repeat helper which takes some value and some length and repeats it by the length. And the code is actually pretty simple. It creates an array with that length and then it maps over it and returns that value that was passed in. And not surprisingly you can use the each keyword when your helper returns an array or in any other keyword or helper or component that expects an array. And you can already imagine some interesting use cases for this in your application. Now what about objects? Using the change set example from before you could even use the with keyword to make a really crude ember form for it. And when you're returning an object you can even do something as crazy as this or what I call the contextual helper. When I first realized you could do this I thought it was kind of silly but it turns out you can use this technique to do something you're probably already familiar with in object oriented programming. And what it allows you to do is basically component dependency injection. So here we have a parent component with some child components and you can see that these components are actually passed in from the outside through a hash which gives you an object. And now in my parent components template I basically decoupled those components from the parent or container component and my parent component no longer needs to know anything about those child components. And now if you do a lot of component integration tests you can better test that component in isolation. And here I have a helper which is available online to do essentially to be able to register a dummy component. So now in your test you can actually stub out those child components. And as you can see what you return in a helper really changes how it's used. You can even return functions in helper. For example here we have a toggle helper which inverses a Boolean property on some object. And in JavaScript a function that returns a function is known as a higher order function. And a higher order function helper lets you basically make Ember action helpers. I'm sure you've written some action like toggle is expanded or toggle is displayed or toggle something many times before. You could actually extract that as a helper and because it's so generic it's a lot more usable and you only need to, you no longer need to basically maintain that presentation logic yourself. And higher order functions by definition take in other functions as arguments. For example the Ember Composable Helpers add-on has a helper called the pipe helper. And since in Ember actions are just functions you can actually pass those actions in as arguments to the helper. And what this pipe helper does is let you invoke those actions sequentially by passing the return value from one action to the next action kind of like an elixir pipe if you're familiar with that. And there's actually not much code involved but you can see how something like this can help you dry up a lot of boilerplate UI logic where for example if you click a button you wanna also submit record and show a dropdown and you wanna basically compose these actions together. And you can easily imagine different use cases that can emerge from this kind of pattern. So again even though helpers aren't as powerful as the keywords that Ember provides us you can do really really interesting things with them. The previous examples were all simple helpers. For more complex needs you can make a class-based helper which you can think of as an Ember object. And that means you can use computer properties, services even access to container and whatever else crazy thing you wanna do. Here is an I18N helper where you can look up translations on a local service. And now your helper can listen to a change in locale and when that locale changes all your translations will automatically update even though that locale isn't being explicitly passed into the helper. And if you notice there's a little bit of a friend here observer. So it's currently only okay to use observers in class-based helpers so don't use them anywhere else. Okay you're probably pretty excited about all these cool helpers but when should we prefer to use a computer property and when should we prefer a helper? So the first thing you learn about in Ember is probably a computer property. Most likely the first name, last name to get the full name example. And it's a really nice way to compute a value updating automatically. But auto updates as we've learned can be a double-edged sword because you can't really control when those values update. So computer properties are best suited for business logic. But knowing what keys to observe in that computer property can sometimes be quite tricky. Sometimes you need to know ahead what those dependent keys are. Sometimes you even need to be able to determine what those keys are at runtime which can be quite complicated and also can be quite hard to extract to make that a reusable computer property macro which you can use anywhere. Helpers on the other hand are best suited for generic utilities especially things like this where you might want to repeat a block of HTML a couple of times. They're not really directly related to the domain that your app is trying to solve not really related to business logic but you can see how these generic helpers can help us dry up our app and give us nicer markup. And you don't have the same problems in a computer property where you have to figure out what dependent keys to observe. But remember just don't get too carried away with helpers because again this is really bad so don't do it. Okay in conclusion a template is logic and beta and data and the amount of logic in your template lies on a spectrum. Nothing is black and white. Handlebars enforces a separation of concerns so don't program in your template and remember the rule of lease power. And your templates are a UI language for your app that's unique to you so keep it declarative and how much logic you have in your templates is a bit of a fluid balance because sometimes a little bit more is better sometimes less is better. It really depends but generally you can think of helpers as a nice way to dry up your code especially when they are very generic. And finally what your helper returns changes how it can be used. You can return anything from a string to an array to an object to a function and many different use cases can emerge from this pattern. And if you need access to services or computer properties use a class based helper. So I'm really bad at Q&A when I give talks like my brain free this. So come chat with me during lunch and I'll also give you some very limited edition sugar pirate stickers which you can see over there. Thank you for listening.