7 steps to better JavaScript

Den Odell presents his seven-step plan for writing flawless code, and rounds up the most useful tools for streamlining the process.

Screencast created by Tuts+Premium in association with net magazine and Creative Bloq.

With browser performance improving, along with the steady adoption of new HTML5 APIs, the volume of JavaScript on the web is growing. Yet a single poorly written line of code has the potential to break an entire website, frustrating users and driving away potential customers.

Developers must use all the tools and techniques at their disposal to improve the quality of their code to be confident that it can be trusted to execute predictably every time. This is a topic close to my heart and I've been working over many years to find a set of steps to follow during development to ensure only the highest-quality code gets released.

Follow these seven steps to dramatically improve the quality of your JavaScript projects. With this workflow, fewer errors will occur and any that do will be handled gracefully, leaving users to browse without frustration.

01. Code

Start by invoking ECMAScript 5's strict mode in your functions with a "use strict" statement, and use the module design pattern, minimising the use of global variables by sandboxing separate code modules within self-executing function closures, passing in any external dependencies to keep modules clear and concise. Only use established and well-tested third-party libraries and frameworks, and keep your functions small, separating any business logic or data from your DOM manipulation and other view-layer code.

Using libaries like RequireJS can help improve the quality of your code

Larger projects with multiple developers should follow an established set of coding guidelines, such as Google's JavaScript Style Guide, and will need stronger code management rules, including stricter dependency management using the Asynchronous Module Definition (AMD) through a library such as RequireJS, package management using Bower or Jam to reference specific versions of your dependency files, and the use of structural design patterns, such as the Observer pattern, to facilitate loosely-coupled communication between your different code modules. It's also a wise idea to use a code storage repository system such as Git or Subversion via services such as GitHub or Beanstalk to keep your code backed up in the cloud, provide the ability to revert to previous versions, and, for more advanced projects, to create branches of code for implementing different features before merging them back together once complete.

02. Document

Use a structured block comment format such as YUIDoc or JSDoc to document functions so any developer can understand its purpose without needing to study its code, reducing misunderstanding. Use Markdown syntax for richer, long-form comments and descriptions. Use associated command-line tools to auto-generate a documentation website based on these structured comments that keeps up to date with any changes made in your code.

03. Analyse

Run a static code-analysis tool, such as JSHint or JSLint against your code regularly. These check for known coding pitfalls and potential errors, such as forgetting to use strict mode or referencing undeclared variables, and spot missing braces or semicolons. Correct any issues the tool flags up to improve your code quality. Try setting default options for your project team to enforce coding standards, such as the number of spaces by which to indent each line, where to place curly braces, and the use of single or double quotes throughout your code files.

04. Test

A unit test is a small standalone function that executes one of the functions from your main codebase with specific inputs to confirm it outputs an expected value. To improve your confidence that code will behave as expected, write unit tests using a framework such as Jasmine or QUnit for each of your functions, using both expected and unexpected input parameters. And don't forget those edge cases!

Browserstack makes it easy to do all your cross-browser testing in one place

Run these tests in multiple browsers across multiple operating systems by taking advantage of services such as BrowserStack or Sauce Labs which allow you to spin up virtual machines in the cloud on demand for testing. Both services provide an API allowing your unit tests to be run automatically across a number of browsers simultaneously, with the results fed back to you as they complete. As a bonus, if your code is stored in GitHub, you can take advantage of BrowserSwarm, a tool that automatically runs your unit tests when you commit your code.

05. Measure

Code-coverage tools such as Istanbul measure which lines of code are executed when your unit tests run against your functions, reporting this as a percentage of the total number of lines of code. Run a code-coverage tool against your unit tests, and add extra tests to increase your coverage score to 100 per cent, giving you greater confidence in your code.

Function complexity can be measured using Halstead complexity measures: equations devised by computer scientist Maurice Halstead in the 1970s that quantify the complexity of a function according to the number of loops, branches and function calls it contains. As this complexity score decreases, the easier it becomes to understand and maintain the function, reducing the likelihood of errors. The command-line tool Plato measures and generates visualisations of JavaScript code complexity, helping identify functions that could be improved, while storing previous results, allowing quality progress to be tracked over time.

06. Automate

Use a task runner such as Grunt to automate the processes of documentation, analysis, testing, coverage and complexity-report generation, saving yourself time and effort, and increasing the chance of addressing any quality issues that arise. Most of the tools and testing frameworks highlighted in this article have associated Grunt tasks available to help you improve your workflow and your code quality without you having to lift a finger.

Save yourself some time and effort by automating with Grunt

07. Handle exceptions

Invariably, at some point, your code will throw an error when it's run. Use try…catch statements to handle runtime errors gracefully and limit impact on your site's behaviour. Use a web service to log runtime errors thrown. Use this information to add new unit tests so as to improve your code and eradicate these errors one by one.

Steps to success

These seven steps have helped me produce some of the code I'm most proud of in my career so far. They're a great foundation for the future, too. Commit to using these steps in your own projects to produce high-quality JavaScript code, and let's work together to improve the web, step by step.

Words: Den Odell

This article originally appeared in net magazine issue 249.