Sessions is temporarily moving to YouTube, check out all our new videos here.

Adopting Better Ember Patterns

Sarup Banskota speaking at EmberFest in October, 2017
Great talks, fired to your inbox 👌
No junk, no spam, just great talks. Unsubscribe any time.

About this talk

A quick walk through various Ember codebase scenarios, and suggestions on improving them - including better use of closure actions, Ember data methods, avoiding observers and what I like to call "chatty templates".


Alright, hello Berlin. And I didn't originally have introduction slides. But yesterday I watched Miguel's talks and then his cute pictures from Spain and then I couldn't resist showing off some of mine. So I'm Sarup and my name is Sarup Banskota. Generally I live in Singapore, but that's more theoretic. In practise I'm like a nomad, also known as homeless person. And, that's my home. I'm just kidding. So in Singapore I worked for a company called Messages. And we are a FinTech. And I started working on Ember for the last one year, roughly. And this is actually my first JS event, that I'm attending or even speaking at. For the last year, I mean I've been working with a small engineering team and over time I've started to work on multiple Ember apps. Over time the timeline went something like the first three months I was getting familiarised with the framework, just going through what I like to call the honeymoon phase, or the magical phase. And then the next three months were just trying to understand more of the magic. We were also being bombarded by some deadlines, so I was trying to make sure that in the deadline I can figure out what the magic was all about. I think after that three, after six months, I started to get a better understanding of how things work. And I started to review more pull requests. After looking at few different repos and few different Ember projects, and different people, I found a few patterns across a few all the repos. Some of them felt like, I don't know, they should have been more common sense, and why would people do those? But some of them were quite tricky and I didn't get them until quite recently. So this talk is basically I'm just presenting some of those instances and how if you have those issues, how you could resolve them. So this is not a big picture talk like the previous one. This is very low picture. Okay I'll skip this one. Since we are at a JS event, like all the other events I went to before were not JavaScript events. So I couldn't really say I look forward to write JavaScript. People will ask you what are smoking? To clarify, I don't mean we should write a logic-less handlebars template because that once happened. In one pull request, I said hey, this is a lot of logic, I think we could move it to the JavaScript, and then just keep the computer property which will show on the template. Eventually somebody came up with a huge pull request in which the handlebars is completely clean and all the logic was under JavaScript. I think that this also work. So like an example, if you look at this slide, in this app there are two kinds of users. Two kinds of login. There is the customer who can login directly from the app. Then there is the admin who can login and then emulate a customer, switch the user. And then it so happens that the regular customer, their currency detail is stored under session, oh no sorry, aug manger dot current user base currency. For the other one it's a session dot switched user dot base currency. When you're normally reading this code if you just want to skim this file I know that it's not as complicated but it just takes some amount of brain cells and takes some time to figure out what really is going on. How I would approach this scenario is to take that logic out and just keep the base currency there. I think this is much easier to read, I think you'll all agree. It's easier to just read that as base currency. The logic itself is now moved into the JS as a computer property. Then the if case handles it. This doesn't mean that every single time we have logic we do that. Like in my next slide sometimes when you have single-liners I think it's okay to have logic because it's quicker to read it and it just feels natural. Now imagine putting this logic also in the Java Script. That would mean too much switching back and forth. I think that's not ideal. I like to call this kind of stuff chatted templates. Whenever pull requests show up if I see this pattern I just call it that's that chatted template. There's another one which I saw very often. I think the most common case I've seen it is somebody creates a component. When they create the component they create it because they need one of those let's say there's a pie chart and there's one pie chart at a time so they make a pie chart component. But over time they need more pie chart so they just create another pie chart, whatever the five different pie charts. But then it's basically the same thing over and over again when they could have just used the component helper. They would just keep writing it like in this example. One way to clean it up again is to move it to the JS. Even until you can write something of this sort and just iterate over an area or something. That's basically chatted templates. Okay this one, this one is a bit funny. Yesterday I was going around asking Lauren and Valent where have they seen services being abused? Because initially I put this on the slide and then forgot why exactly I put it there. But trust me on this one I've seen some really crazy services and I will just show you one if I manage to open. That's actually like a service file and then there is even like compare numbers all that much like properties for each of the things they wanted to store in that route. So much of business logic. I really wanted to enjoy Berlin this weekend but I think I'm gonna end up fixing this one. I think services are not I think that's what it was intended for. Services are useful when you want an app-wide situation where the same thing is going to be utilised throughout the app. Like say geolocation or if you want to keep track of browser, which browser is going on. Another example, logging at something. For that kind of stuff services work well. But where I've seen it being abused is people make different routes then for each route they make a new service. Sometimes when you make styles you make one style per route. Something of that sort. Service for every single route in the application. That I think is overkill. I think every single time this has happened it almost always arise in this form. Sometimes you have custom endpoints and the are just not, they don't play very well with Ember data if you have to use it directly. What someone will do is make a new component. Now they want to call the custom service and it's just too much work to model it, then serialise it and so on. What they tend to do is they will create a data insert element then write an AJAX code within it. Then handle the then case, and the serialise the data, then render it. But now they need to do some error handling. This function just starts to get bigger. The easy route is to just take all of this huge meta, put it in the route like a service then reference it like service steps or whatever. Over time it just gets bigger and bigger. You don't have the guilt anymore because you can just say inject service and you're not seeing that huge code anymore. Until you really have a problem and you have to look through what exactly was going on in the serialisation phase. This is one example of something that I was just showing. Select too much business logic or storing data for every single route in a service. That's really overkill. The reason I was asking Valent and Lauren now I do remember what was the other abuse case. I will talk about it more in one of my subsequent slides. Okay, that's that. The next two or three slides are a bit related. This is with using Moar Ember-data methods. Against this one comes when you don't have customs, when you have non-standard endpoints. I will give you an example. We were making an app and it was a FinTech app. There was lots of data on it. Especially there was this route where we wanted to render a table. Imagine a regular table then you want to group the table by some property. Then you want to group this group by another group and then group that by another group. It can get a bit funky there. How it was done when I approached this was initially there was a component for the table. Inside whatever did insert element there was the data being searched, serialisation being done. And all the data was being stored in a service. It was like a really big file. It was not really clear where do I start? I figured it was not fun to refactor it so I just decided to rewrite it as always. I thought that the best way to start it was to first use and Ember-data method like url. This forced me to think of how could I actually model this? Because sometimes custom endpoints will not make it easy for you to do relationships, for example, which is why people don't want to model it. I just started with something like this one. Now I could write a proper model for it. Once the modelling was done it just made everything else very easy. Now you can create as usual. I think this one it pretty famous. Stefan Penner has a talk on this topic. As he likes to say, every time you use an observer, add dollar twenty to the observer tip jar. But that was a while ago so now you can adjust for inflation and add like 28.5. What I've noticed is that every single time you use an observer you can almost always not use an observer. I think it's worth talking a little bit about why not to do it. This is one of those things which I found personally hard to grasp until not very long ago. As opposed to like computer properties, observers are more eager and they just execute immediately. Computer properties return value so you can actually use them within your template. Some cases like for example let's say in this case where you wanted to use the most classic example there is first name and last name. Then you want to create a full name out of it. If you wrote an observer and then made it work in this fashion this would just execute immediately. But actually, okay I got confused with my own slide. Basically you could replace the first case with a computer property. Then you can return it. The advantage of this is that also now you can just use full name within the template. Then the second case this is when you have a parent component then a child component within it. The parent component is passing some values down to the child component. You are watching for if the property that was being passed has changed. Then you want to make some changes on the child. Often I've seen observers being used there. I think instead it's much easier and better to use lifecycle event hooks. Generally if you see observer usage almost always like 98% of the time the two person is because I don't remember every single instance. First one, always try to see if you can use a computer property. It most always will solve it. The other one is to use a component lifecycle hook. The third one which I will talk a bit about later is to think of this in terms of data down actions up approach. That almost always solves it. This was the magic one. This morning I still didn't get it like what exactly was it that I didn't remember. So I put in an alarm at five a.m., five-thirty, six. Then now I know what it was. What I was talking about where service were being abused was now that I understand data down, actions up approach, before I didn't. I was thinking how else do you do it when you don't do it data down, actions up? So how else it's done is you make a service for everything. Say you have a parent component and then a child component, and then a child component within it. But you're not passing data down. What you do is when something changes on the parent component you just update the service. Now the service has shared state everywhere so you can also access it in the child most component. This way the service is being a kind of replacement for global. That's a case you really want to avoid. Just to make sure we are on the same page, data down, actions up like what you want to do is when you have nesting of components this way when something changes on the parent component you want to pass down the property and you want to bubble up the actions. But even with that I have seen two cases now. One is that sometimes it just gets abused. You have all the state and all the parent component. Literally everything has been chart. It's like an overuse of data down, actions up. I think you want to keep a state at the topmost level where you have the most oversight. Imagine you have a good case would be a button and then something that's gonna show when you click this button. Nothing else above it is going to be affected. Most likely it makes sense to keep all of this state on that component itself and not bubble it down. Our form validations is one example. You have a form with validations, I think it mostly never makes sense to bubble down all the validations up. That's that one. Recently there are also add-ones which do this very well. I haven't really used it but I was telling Miguel that I am going to try it out. If you read the documentation, in fact that's where I actually heard about this term the first time. It followsroute. I just talked, those are a few techniques, like six of them. I hope all of you try it out. Often you will feel, you will see this being really abused and you don't know where to start. But as I said I think one good approach is like you always try it. The goal is always to try and use Ember data more. So you try to model it first, then the rest of it sorts itself. If it doesn't, once as we saw from Miguel's slides, if you have enough of seafood and nice views you can always solve your problems. So I guess thanks a lot. Also since it's my first JS conf and since I haven't been using Java Script for that long I really wanted to take the opportunity to thank the organisers, speakers, attendees. But also like so many people who helped me on Slack every time I was stuck, it's a bit weird how come people are that helpful. Ricardo, every single time I bugged him I really wanted to thank him. Also Lauren, Valent, and Marie, I read their blog posts and they were very helpful. I'm not sure how I would figure this framework out if not for some of these blog posts and resources. Thanks a lot and I will be at the I will be at the hallway. If you have any questions just ping me.