Let’s talk about JS code styling, tools like ESLint, Prettier, Code Spell Checker and SonarQube, and project architecture.
JavaScript code styling / JavaScript coding standards
Google and Airbnb developers have two of the most popular style guides on this topic. We’ll share the most interesting points and relevant rules with you.
1. Semicolons
Every ad must end with a semicolon. Don’t rely on automatic insert.
2. Horizontal alignment is bad, although not prohibited
It is a practice when you can add a large number of spaces in your code so that certain characters appear directly below the characters on the previous string. In general, it is considered bad style if you follow Google’s advice, but sometimes it can be acceptable. Just don’t keep using horizontal alignments where they already exist.
3. Do not use var
Declare all local variables with const or let. Use const by default until the variable needs to be reassigned. The word var should not be used.
4. Arrow functions are preferred
Arrow functions give a concise syntax and solve a lot of complexities therewith. Choose arrow functions instead of function word, especially in nested functions.
5. Use template strings instead of combining them
You can designate them by using back quotes ` instead of a complex string combination, especially in case of several lowercase literals. Moreover, they can be on multiple strings.
6. Use single quotes rather than double ones
Regular lowercase literals are enclosed in single quotes. If any string contains a single quote character, consider template strings to avoid quitting the quotation area.
7. Intervals
By using intervals you can also improve the readability of your code. Even if the entire file is included in an enclosed structure (e.g., in a function), the contents of the function should be indented in one tab. Format any indents with tabs.
8. Do not use spaces at the end of the strings or on empty strings
Strings are usually written with 80 characters in length utmost and should not exceed 100 (considering each tab as 4 spaces).
It is not a hard-and-fast rule, but long strings usually indicate unreadable or poorly organized code.
Also:
- unary operators (e.g. ++, —) should not have spaces after their operands;
- there should be no spaces in front of , and ;;
- there should be no spaces in front of : after property name in the object definition;
- characters ? and : in an elvis operator should have spaces on both sides;
- empty structures (e.g., {}, [], fn()) should not have filling spaces;
- a new string should be at the end of each file;
- function body shall be indented in one tab.
9. Equality
Strict equality check (===) should be used instead of a simple check (==). The only exception is when undefined or null check is performed by checking for null equality.
10. Comments
- comments should precede the code they relate to;
- a null string should precede the comment;
- start comment with a capital letter;
- place a full stop at the end if your comment is a complete sentence;
- there should be one space between the comment symbol (//) and the comment text;
- for long comments, use multi-string comments;
- in-line comments are allowed as an exception.
11. Blocks and curly brackets
Blocks if, else, for, while, try should always use curly brackets and be on multiple strings. An opening parenthesis should be on the same string as the function definition, condition, or cycle start. A closing parenthesis should be on the string following the last block statement.
12. Multi-string sentences
- When a sentence is too long for a single string, string breaks should be inserted after statements.
- Strings should be split into logical groups if this improves their readability. For example, each expression of a ternary operator is better placed on its own string, even if both fit on the same string.
- When condition is too long to fit on one string, subsequent strings should be indented one additional level to distinguish them from the core code.13. Method call chain
13. Method call chain
If it is too long to fit on one string, each method call should be on a separate string and the first one shall be located on the next string after the name of the object, which methods are called. If the method changes context, use an additional indent.
Tools: ESLint, Prettier, Code Spell Checker, SonarQube
You don’t have to remember all these rules and manually edit the whole code, you can use special tools for this purpose.
ESLint
First of all, you will need a linter, a static code analysis tool for identifying problematic templates. ESLint is the most popular of them. It’s flexible, easy to extend, and comes with a lot of customizable rules, and the possibility to apply different styles. It has better ES6 support than other linters.
ESLint is very useful in JavaScript, since an interpreted language, JS has no compilation step. Therefore, many errors can only be identified at the run-time.
Many of the rules available in ESLint are disabled, but you can enable them in .eslintrc configuration file, which can be global or local for the project. One of the most popular settings for the linter is Airbnb JavaScript Style. It brings your code to a more or less consistent style, can automatically fix many of the issues found, and integrates well with many development tools.
By the way, like other linters, it doesn’t force you to use a single style. Instead, you can choose from the best practices and fine-tune the style in your sole discretion.
Prettier
Prettier is a formatter. It scans files for style issues and automatically formats code. In such a way the uniform rules are observed for indents, spacing, commas, single vs. double quotes. This is highly recommended to use ESLint support in eslint-plugin-prettier. The task of Prettier is to make the developer not think about formatting. It has minimum settings: you should install Prettier itself and pre-commit-hook.
To work with Prettier in Visual Studio Code, you will need to install an extension. To accomplish this, search for the Prettier — Code Formatter tool in VS Code extension panel. You can convert code with inconsistent indents, parentheses, string breaks, and semicolons into a well-formatted code. To automate this process, you can choose a setting in VS Code to automatically format your files while saving them. This also ensures that your unformatted code will not end up in the version control system.
There is a drawback to VS Code’s built-in settings menu, it doesn’t ensure consistency between developers on your team. If you change the VS Code settings, another developer might have a completely different configuration. You can ensure consistency in formatting in your team by creating a configuration file for the current project.
Code Spell Checker
A significant part of errors developers come across is related to misspellings (or grammatical errors) in variable, function and package names. You can misprint in comments, descriptions, and documentation. This package highlights bugs in your file and takes into account the camelCase code. Blue underlines let you know which words should be corrected. If you want to “dismount” a word as a correct spelling you can right click to add it to the user (global) or folder (local) dictionary.
SonarQube
By choosing the right development methodology and applying proven techniques and tools you can increase the likelihood that the code is written correctly, and the final product meets the required quality standards. SonarQube, an open-source platform, is used for continuous code quality analysis and measurement. It allows evaluating the current state of the code base, the dynamics of this state and possible risks during project implementation.
SonarQube provides the following possibilities:
- it supports Java, C, C++, C#, Objective-C, Swift, PHP, JavaScript, Python, etc. languages;
- it provides reports on code duplication, coding standards compliance, code coverage by unit tests, possible errors in code, comment density in code, technical debt, etc;
- it saves metrics history and plots changes in the metrics over time;
- it provides fully automated analysis: integrating with Maven, Ant, Gradle and common continuous integration systems;
- it allows integrating with such IDEs as Visual Studio, IntelliJ IDEA and Eclipse via SonarLint plugin;
- it provides integration with external tools: JIRA, Mantis, LDAP, Fortify, etc.
You can extend existing functionality with third-party plugins.
Standard Quality Gate SonarQube uses the following metrics values to determine if the code successfully passed its checks:
- 0 new bugs;
- 0 new vulnerabilities;
- technical debt ratio on a new code <= 5%;
- test coverage of a new code is at least 80%.
Technical debt (also known as coding debt) is a software engineering metaphor for accumulated problems in software code or architecture associated with neglecting quality in software development and causing additional labor costs in the future. Technical debt is usually invisible to the end users of a product, but is related to deficiencies in maintainability, testability, understandability, modifiability, portability.
The Sonar team identified seven deadly sins of developers increasing technical debt:
- bugs and potential bugs
- coding standards violation
- code duplication
- insufficient coverage with unit tests
- poor complexity distribution
- spaghetti-design
- insufficient or too many comments
The SonarQube platform is designed precisely to help combat these seven sins.
Project architecture, folders and files naming
Let’s move on to the project structure and component naming in React. Let`s highlight such advantages of a structured project in React:
- Team members should not think about the structure of the project. Instead, they can focus on creating the product.
- Since React has a huge ecosystem, you shall constantly think — redux or mobx? HOC or render prop? react-motion or react-spring? Eliminating one of the problems results in a consistent structure.
- A common project structure helps new team members get up to speed more quickly. Based on a short brief you can guess what is in each folder and what the files are for.
- People with less experience can also create scalable projects.
- Code sharing and reuse.
How to design React components?
- The component file name should be in CamelCase — TabSwitcher, not tabSwitcher, tab-switcher. It is not necessary to name other file types in this notation since CamelCase signals that this file is a React component.
- Avoid export by default. The above is a special case of named exports (e.g. mandatory in Next.js), therefore it should be processed in a special way, which is a common cause for confusion. The component can be imported as follows:
import { TinyButton } from './shared/Button'
- All components should be placed in a components directory. Keep each component in a separate file. If you need a styles file, create a folder and store it there. The main advantage of this approach is that the components are not hidden somewhere deep inside. They are intended for reuse, so they should be stored in plainview.
- The folder and component names should match. Therefore, when you search for files, you obtain not a list of *.js files, but actual component files. To avoid such components import: import { TinyButton } from ‘./TinyButton/TinyButton’, create index.js file in component folder that exports the component named:
// components/TinyButton/index.js export * from './TinyButton'
- Move routing to the pages directory. Follow Next.js’ agreement on project structure, where the routing logic is stored in pages directory. Each page is a React component, and it has some state. Page component uses other components to build a page. The reason the routing logic is not reusable is that the page components cannot be reusable. The advantage of this approach is the possibility to quickly view the routes available, the central location of all routing logic, and the possibility to keep page components separate from others.
Atomic design is one of Brad Frost’s project architecture options
As web design art continues to develop, we recognize the need to develop thoughtful design systems rather than simple collections of web pages. In searching for inspiration and parallels, author kept coming back to chemistry. The idea is that all matter (whether solid, liquid, gas, simple, complex, etc.) is comprised of atoms. These atomic units bond together to form molecules, which in turn combine into more complex organisms to ultimately create all matter in our universe.
Similarly, interfaces are made up of smaller components. This means we can break entire interfaces down into fundamental building blocks and work up from there. That’s the basic gist of atomic design.
Atomic design is methodology for creating design systems. There are five distinct levels in atomic design:
Atoms — Molecules — Organisms — Templates — Pages
And finally, let’s quote the author in software development field, Robert Martin, and his characteristics of a clean code:
- “It should be elegant — Clean code should be pleasant to read. Reading it should make you smile the way a well-crafted music box or well-designed car would.”
- “Clean code is focused — Each function, each class, each module exposes a single-minded attitude that remains entirely undistracted, and unpolluted, by the surrounding details.”
- “Clean code means care. Someone has taken the time to keep it simple and orderly. Such person has paid due attention to details. They did exhibit care.”