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

Promoting Ember's Best Practices by Linting Code

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

About this talk

Code linting is one of the least talked about, but most useful tools in a front-end developer’s toolbox. It's the easiest thing we can do to significantly improve our code quality. Default Ember.js application blueprints already include basic JavaScript linter setup. But it’s often forgotten how easy and quick it is to go much farther, and ensure extensive, Ember-flavoured static code analysis in your project. Let’s talk about state-of-art solutions that can be used today in any Ember.js project and greatly enhance your development workflow.


Transcript


Today, I'd like to talk about linting code, in Ember applications. It's, I don't think it's the most fashionable topic to talk about, it's not very, there's not much hype around it. It's not FastBoot or I don't know, Glimmer, or progressive web apps. It's just this simple thing to make our lives easier. But I still think they should be treated seriously. And they can really improve the experience of developing an application, as well as improve our product, our application, protected from simple things and for best practises, and so and so on. I'm Adrian. I'm a frontend developer at Netguru, which is a company where we have a small, but focused, community of Ember developers. And we have been working and developing single page applications in Ember for several years now. Also, contributing to opensource. And this is where I've had my first time with Ember and first projects with Ember, which I fell in love with, of course. And it has taught me many, many important things and I think my experiences with Ember really formed me as a developer that I am today, which sounds very cheesy, and it is. So, let's start with the definition. It's nothing special, I think. All of us, I assume, have used some kind of linter some time. Basically, it's a tool that can highlight and flag any suspicious usage or not optimal patterns in our code and notify us of them. We all have used ESLint or JSLint in JavaScript, I guess. I think that today they are not appreciated enough. Again, they are like quiet heroes, not those popular things to talk about in conferences. They are not appreciated enough, they are often either left as like a small perk of the project, not told to be treated seriously. Today, they can do a lot more than they used to. Most of them, the mainstream ones, are applicable, they can be extended with custom rules. And there are lot's of full sets available today. And I think, correct and strict linter setup is a really great asset in any project to ensure that simple problems in our code will simply disappear, they will go out of the window and we won't have to worry about them. And so, we can focus on more important things like actually developing some features or structuring our application, which I think aligns with what Ember does. It allows us to be productive and not worry about low level issues. I like to think of linters as a wall, an impenetrable wall, that won't, basically it won't be crushed by anyone if we set it up correctly. We can define the boundaries in the code that won't be crushed and everything that is defined as a linter rule, is and will be kept in place. And if someone chooses to turn it off or skip it, it has to be a conscious and firm decision. And so, the impenetrable wall... I think this is something you can achieve with linters. Define boundaries in the code that won't be crushed thanks to them and I repeat myself, anything that is defined as a linter rule, is something that we can eliminate from our code once and for all. And I think this is especially important in several situations, in large teams, of course, where we have many developers with different habits, opinions, and not everything is uniform between all people contributing to the code base. Same with projects where we have rotations or new developers joining. I like to call this junior-proofing, and this is based on real-life experience where a junior developer was assigned to our project where I was elite, and every time I saw that his PR was, didn't have green build, I knew that it's because of the linters. And whenever there is a green one, I can actually start looking at the code. Also, simply we are human, we make mistakes and linters are automating a way those simple checks that they can do. And like I said, anything, any deviation from these rules is becoming a conscious decision that we will have to make by ourselves, not because we forgot to, or made a typo, or. Okay, let's continue. So, what can happen if we develop a project without a linter? Or a linter that is not set up in a correct way? I think, especially, in the situation that I've talked about in the previous slide, either code style is not uniform across the project, this is cosmetic issue but still something to think about. Basic code issues are not... Well, are not something that you want to focus on, for example, during code reviews and linters are automating this way, the junior-proofing that I've talked about. And even when they are present, but not taken seriously and ignored, the arrows in the warning that they erase, there is a lot of them, and it's easy to miss the actually important issues. So, what linters can do today? Just several years ago, they were very simple tools, at least, on the front end, I dare to say. Each linter had just a static set of rules that covered language issues. They can do a lot more today and be easily extended. So, I will start off JavaScript which I think is the most important part of our applications and there is this quote that I found somewhere, there is a source which I found yesterday, after like three years of repeating this to everyone. There will be a link to the presentation later on so you can click on the link, but it's not, nothing fancy. Anyway, JavaScript is like a very fluid language, it's loosely typed, there are many quirks, and I think it's a perfect playground to actually lint the code. I mean, this is the language where linting gives us a lot of benefits. So, the basic things that I think, most of us think about when linters are mentioned, are basic language level rules. Things like typos, invariable names, duplicate object properties, code formatting, semicolons. Those are the things that come up, come to our minds when we talk about linting code the most, still. And what is the case today, is several years ago, I believe it was 12, 13, the first mainstream pluggable linter for JavaScript appeared and so everyone was able to rewrite their own plugins with own rules. Most importantly, dedicated to specific solutions like frameworks, libraries. It was ESLint, and yeah, I think that's it about ESLint itself, pluggable linting utility for JavaScript, there is a link to repository with a list of all the rules that are truly used and maintained, and so on and so on, including what's on the next slide, which is eslint-plugin-ember. There are several plugins like this, but I think it's the most developed, and most maintained and most standard one. It holds several tens of rules dedicated to ember.js code, focusing on ember code basis. So, yeah, 27, tens of rules. It's held under Ember CLI organisation and the full list is in the read-me file. So, feel invited. I just wanted to show several examples of the rules and show you how the rules are targeting specifically Ember code, that is generally JavaScript, and what can be done thanks to them. So, first it's pretty basic, use-brace-expansion when defining dependent computed properties. So, you can see the good example, the bad example, it saves us some repetition and also makes code more readable. This my favourite one, it's idle troll, which I think was introduced without bad intentions when defining Ember objects. Basically, if we do something like this, then the value of items will become a static shared property of all instances of this component. So, let's say we have one component which pushes item to... To the items array, it will be populated across all the components in the whole application. This is pretty known pattern, and what ESLint plugin Ember can do, thanks to this rule, avoid leaking state in components, is detected, notify us of it, and make sure that we actually define this values in hook. No side effects, it's also related to computed properties. It makes sure, of course, it can detect all patterns like calling external libraries. But... In this case, we're trying to set, set object property in computed property, which is quite universally a bad practise. And we shouldn't do it. So, this rule detects this and... Yep. That's a good way to approach it. New module import, it's again, pretty basic one. But I think popular, and it has been mentioned several times, on several times? Today, as well. The new module imports, and what this rule does, is it force us to actually use them compared to the old practise of importing whole Ember object, and maybe the constructing it. So, linters can do a lot today, they have gotten much more powerful than they used to be several years ago, that's the bottom line of it. And that's JavaScript, we also have styles and templates in our applications. And I won't be elaborating too much on it but, I wanted to show you the most common, I think, solutions to use in Ember applications. Styles. There is stylelint, which I think could be called, simply, ESLint for CSS. And it's plugable as well, there are tonnes of rules, and tonnes of extensions allowing it to lint any, any flavour of CSS you can imagine, I think. Less sauce, CSS variance. And Ember template lint, which is, well, as you can see by the name, is dedicated to Ember handlebars templates. And it recently got updated to allow writing our plugins as well, I don't think there are too many of them just yet, but, that's in the future. All of this is not worth too much if we don't really use linters in a correct way. I mean, we can define a very fancy config, really strict, with tonnes of rules covering all the parts of both the framework and language, but they have to be practical to use in development, and also, actually, we have to make sure that they are followed by everyone contributing to the repo. So, I'd just like to go through several ways in which we can do this. First is the most basic one, launch comments from command line, this is sometimes useful, but not very practical when developing. It's just not nice to launch it manually a hundred times when we're writing the code. Text editor integrations, there are available ones for all the mainstream editors, and what they do, I think it's the most common way to lint the code. Basically, you can see the lint warnings are arrowed directly when editing the code. So, it gives you immediate feedback, it still can and sooner or later, will be ignored because you can miss some units to import, or mistypo. It's simply not reliable, even though used most of the time. We have git hooks, which are pre-commit most often, sometimes pre-push git hooks which launch some kind of linter on our code. We have example where we have ESLint, which doesn't pass. We also have Ember template lint hook, in this case, which passes. And this is already quite a strong wall stopping us from committing any bad code that doesn't lint correctly. But still, sometimes the configuration isn't right on someone's machine, or they can be just skipped with single common-length parameter. So, again, useful, but not necessarily reliable. And tis is the most important part, I think. This is... This is what creates the wall I have talked about, it's treating linters as part of application tests. So, we won't be able to merge anything that doesn't lint correctly. And I'm telling this because code linting is actually testing your code. While not for business logic, or the actual scenarios in the application, it tests your code for having correct syntax, formatting, for conformance with conventions in the project and style guide. I think it's quite a big one because linter config, at the same time, can define and document, as well as enforce specific quirks related to the project. And also, making sure that simple, good practises, the one that we can statically analyse are followed. Also, ones related to specific frameworks like with ESLint plugin member. And this is... At the beginning I said something about Ember teaching me many lessons, and this is one of them. When I had my first project in Ember, that's when I started approaching code linting seriously and pushing it upon everyone that I meet, and every project that I'm involved with. Basically, even by default, when just creating new Ember application, we have basic ESLint setup, which is run as part of tests. So... Any error that is erased by linters is the same as... Well, you won't be able to merge the code unless you're naturally, running your tests. But I don't think it describes anyone. So, Ember already does it and I think it's pretty amazing. And it's the first framework that I worked with and has this approach taken on by default. So, Ember CLI ESLint, this is the add-on that integrates ESLint into the testing pipeline, and is there by default, and is just as easy to add other linters, to basically be a part of tests. Ember CLI stylings, template lint. And they are all just one common other way Ember installed the add-on name, which is pretty amazing. And also, maybe one more slide to stay sensible about linters. I'm not sure if any of you has experienced this, I did, for sure, especially when you're not working with them too long, they can be taken too seriously. There are some rules which are simply annoying, in most of the cases, they are present as default config in some of the popular ones that we are basing off. And... When you find yourself spending time instead of avoiding things that they point out, this is the case where you can and should, for example, turn some rules off, the ones that annoy you and don't give you any real benefit. There's nothing wrong with having some exceptions in some places, in the case by code commands, which turn off the linters for some parts, blocks, of the code. I can think of example of overriding some method from external repository and you don't really want to modify anything in the code except one line, and you don't want to rework it to pass your lint, and things like this. Or maybe there is a rule to not allow using observers, but maybe you have this one place in your application where you actually want to use an observer, and there's nothing wrong with it, just make sure that you know what you're doing. There's this nice quote that someone said to me some time ago, and it has stuck into my mind, is that, "Linters should be for developers, not the other way around." And... Yeah, avoid lint-driven development, when we're taking them too seriously to be practical. And the summary. This is a bit of a cycle, it ends up as a cycle. It's a paraphrase of one of the beginning slides, yeah, code linters are under-appreciated. They can do a lot. Getting rid of simple problems with code, the low effort way, they are way for, the lazy way to just get rid of all these simple things that can sneak into our code. And it lets us focus on actually developing our application, which is a key part. That's it. That's the link to the presentation, the very same one, it's a Google doc, so feel free to just visit it and take a look around yourself. Thanks.