Skip to content

Latest commit

 

History

History
152 lines (108 loc) · 5.53 KB

CODING_STANDARDS.md

File metadata and controls

152 lines (108 loc) · 5.53 KB

Coding standards

This document describes our coding standards. These are based on the TypeScript coding guidelines.

We use the latest ECMAScript features of JavaScript as much as possible. Typescript is primarly used for type checking.

Names

  1. Use PascalCase for type names.
  2. Do not use I as a prefix for interface names.
  3. Use PascalCase for enum values.
  4. Use camelCase for function names.
  5. Use camelCase for property names and local variables.
  6. Use JavaScript private (#) for private properties and functions.
  7. Use whole words in names when possible.

Components

  1. 1 file per logical component (e.g. parser, scanner, emitter, checker).

Types

  1. Do not export types/functions unless you need to share it across multiple components.
  2. Do not introduce new types/values to the global namespace.
  3. Shared types should be defined in a types folder.
  4. Getters never define their return types.
  5. Functions always define their return type.

Imports

  1. External dependencies should be defined first.
  2. Core dependencies should be defined second.
  3. Runtime dependencies should be defined third.
  4. Types should be imported last.
  5. Imports per import block are sorted alphabetically.

null and undefined

  1. Use undefined. Do not use null unless the external library requires it.

General Assumptions

  1. Consider objects like Nodes, Symbols, etc. as immutable outside the component that created them. Do not change them.
  2. Consider arrays as immutable by default after creation.
  3. Use encapsulation as much as possible.

Flags

  1. More than 2 related Boolean properties on a type should be turned into a flag.

Comments

  1. Only use // for comments.
  2. Use comments sparsely.
  3. Do not use comments to explain the code (the what), but can be used to explain the why.

Strings

  1. Use single quotes for strings.
  2. Use backticks with variables instead of string concatenation.
  3. All strings visible to the user need to be localized (make an entry in diagnosticMessages.json).

Error Messages

  1. Use indefinite articles for indefinite entities.
  2. Definite entities should be named (this is for a variable name, type name, etc..).
  3. When stating a rule, the subject should be in the singular (e.g. "An external module cannot..." instead of "External modules cannot...").
  4. Use present tense.

General Constructs

For a variety of reasons, we avoid certain constructs, and use some of our own. Among them:

  1. Do not use ts.forEach, ts.forEachKey and ts.forEachValue.
  2. Try to use .forEach, .map, and .filter instead of loops when it is not strongly inconvenient.
  3. Do not nest loops, but create new functions for inner loops.

Style

Readability is the most important part of coding. Below are some of the ground rules to keep the code readable.

Code may contain a lot of empty rows, as we prefer to group logical steps together and seperate them from other steps in the function.

  1. Always use brackets for if statements, even if there is just one line of code within.
  2. Use brackets for else statements, except when the only statement is an if.
  3. When using the ternary operators, the ? and the : begin on a new line with indentation, if the result would be a very long statement otherwise.
  4. Use arrow functions over anonymous function expressions.
  5. Only surround arrow function parameters when necessary.
  6. Always surround loop and conditional bodies with curly braces.
  7. Open curly braces always go on the next line as whatever necessitates them.
  8. Parenthesized constructs should have no surrounding whitespace.
  9. A single space follows commas, colons, and semicolons in those constructs.
  10. Use a single declaration per variable statement.
  11. else goes on a separate line from the closing curly brace.
  12. Use 4 spaces per indentation.

Code formatter

A large portion of the formatting can be done by the tools we use. Below are additions to the default settings of Visual Studio Code.

The settings can be edited via Preference > Settings.

{
    "[typescript]": {
        "editor.defaultFormatter": "vscode.typescript-language-features",
        "editor.formatOnSave": true
    },
    "[json]": {
        "editor.defaultFormatter": "vscode.json-language-features",
        "editor.formatOnSave": true
    },
    "typescript.updateImportsOnFileMove.enabled": "always",
    "typescript.format.placeOpenBraceOnNewLineForFunctions": true,
    "typescript.format.placeOpenBraceOnNewLineForControlBlocks": true,
    "typescript.format.insertSpaceAfterOpeningAndBeforeClosingEmptyBraces": false,
    "typescript.format.insertSpaceAfterTypeAssertion": true
}

Code examples

Statements are grouped together based on logic separation. The example below puts the steps related to reading the proxy object together.

constructor(app: express.Application, proxy: Proxy, logger: Logger)
{
    this.#logger = logger;

    this.#repositoryUrl = proxy.repository.url ?? '';
    this.#runnerUrl = proxy.runner.url ?? '';

    app.use('/', expressProxy((message: IncomingMessage): string => this.#selectProxy(message)));
}

Examples of ternary operator use with long and short statement.

const segmentNames = configuration.segments.length === 0
    ? await this.#getSegmentNames(configuration.cache)
    : configuration.segments;

const message = error instanceof Error ? error.message : String(error);

The preferred way to concatenate strings together.

const url = `${this.#url}/nodes`;