NHA Coding Standards
Tags: codequality
Published: 2020-08-24 14:59:07

#INTRODUCTION

This is the National Heritage Academies (NHA) School Applications Development team's coding standards page. Feel free to use these standards for your own reference. As the development team at NHA has grown over the past couple years so has the importance of common coding practices and standards. This article is meant to serve as the agreed upon standards to be followed by the NHA School Applications Development team. These standards are meant to help with:

1. Keeping our code consistent
2. Making our code easy to read and understand
3. Making our code easier to maintain

The following sources were used to compile this list of standards.

https://medium.com/javascript-in-plain-english/19-simple-javascript-coding-standards-to-keep-your-code-clean-7422d6f9bc0

#GENERAL CODING STANDARDS#

###Always use semicolons (;)
Even though the semicolon is optional in JavaScript, we are choosing to end all statements with the semicolon. This is a consistent requirement across JavaScript, TypeScript, C#, and even SQL.

###Always use curly braces around control structures.
Braces are required for all control structures (i.e. *if*, *else*, *for*, *do*, *while*, etc). Do use use single line if statements. The curly brace should start on the same line as the control structure and close on a new line. There should be a space before the opening curly brace.

*Fail:*
```javascript
if (val == 2) doSomething();
if (val == 2)
    doSomething();
if (val == 2)
    doSomething();
else
    doSomethingElse();
```
*Pass:*
```javascript
if (val === 2) {
    doSomething();
}
if (val == 2) {
    doSomething();
} else {
    doSomethingElse();
}
```

###Try to reduce nesting
Nesting *if* statements within *if* statements can lead to messy, unreadable code. Always look for ways to avoid nesting if at all possible. Also try to avoid *else if* statements.

*Fail:*
```javascript
if (myNumber > 0) {
  if (myNumber > 100) {
       if (!hasDiscountAlready) {
           return addDiscountPercent(0);
} else {
           return addDiscountPercent(10);
       }
  } else if (myNumber > 50) {
    if (!hasDiscountAlready) {
       return addDiscountPercent(5);
    }
  } else {
    if (!hasDiscountAlready) {
      return addDiscountPercent(0);
    } else {
      return addDiscountPercent(1);
    }
}
} else {
    error();
}
```
*Pass:*
```javascript
if (myNumber <= 0) {
   return error;
}
if (!hasDiscountAlready) {
    return addDiscountPercent(0);
}
if (myNumber > 100) {
    return addDiscountPercent(10);
}
if (myNumber > 50) {
    return addDiscountPercent(5);
}
return addDiscountPercent(1);
```

###Switch statements should use *break* and have a *default*
Try not to use *switch* statements, but if you must then make sure to each *break* condition and use *default*. Like *if* statements, the curly braces should start on the same line as the *switch* statement and end on a new line. There should be a space before the opening curly brace.

*Fail:*
```javascript
switch (myNumber) {
  case 10:
   addDiscountPercent(0);
  case 20:
   addDiscountPercent(2);
  case 30:
   addDiscountPercent(3);
}
```
*Pass:*
```javascript
switch (myNumber) {
  case 10:
    addDiscountPercent(0);
    break;
  case 20:
    addDiscountPercent(2);
    break;
  case 30:
    addDiscountPercent(3);
    break;
  default:
    addDiscountPercent(0);
    break;
}
```

###Only use one variable per declaration
It is a cleaner and more understandable way to declare your variables.

*Fail:*
```javascript
const a = 2, b = 3;
```
*Pass:*
```javascript
const a = 2;
const b = 3;
```

#TYPESCRIPT
The following rules are based on typescript but should also be followed where applicable to JavaScript.

###When comparing use === instead of ==
Using === matches on both the type and value.

*Fail:*
```typescript
if (val == 2)
```
*Pass:*
```typescript
if (val === 2)
```

###Never use *var*.
Use *const* for values that cannot be reassigned and *let* for anything else. Favor using *const* as much as possible.

*Fail:*
```typescript
var value: number = 100;
```
*Pass:*
```typescript
const value1: number = 100;
let value2: number = 200;
```

###Always set the type for variables and properties.

*Fail:*
```typescript
const value = 100;

class CarModel {
    private _value = 100;
}
```
*Pass:*
```typescript
const value: number = 100;

class CarModel {
    private _value: number = 100;
}
```

###Always set the return type for functions and class methods.

*Fail:*
```typescript
function callback() {
    return 'hello world';
}

class CarModel {
    callback() {
        return 'hello world';
    }
}
```
*Pass:*
```typescript
function callback(): string {
    return 'hello world';
}

class CarModel {
    callback(): string {
        return 'hello world';
    }
}
```

###Always set the argument types for functions and class methods.

*Fail:*
```typescript
function callback(inputStr) {
    return inputStr;
}

class CarModel {
    callback(inputStr) {
        return inputStr;
    }
}
```
*Pass:*
```typescript
function callback(inputStr: string): string {
    return inputStr;
}

class CarModel {
    callback(inputStr: string): string {
        return inputStr;
    }
}
```

###Avoid the use of _any_ as a type as much as possible
Using _any_ can allow for too many unknowns in what type of data you are dealing with. While it can't be avoided entirely, it should be very limited in its use.

*Fail:*
```typescript
const value: any = 1;
```
*Pass:*
```typescript
const value: number = 1;
```

###Class Names should be in PascalCase format

*Fail:*
```typescript
class carModel { }
```
*Pass:*
```typescript
class CarModel { }
```

###Class Property Definitions
Class properties should be listed before the constructor. Each property should be properly labeled _private_, _protected_, or _public_ and listed in that order. _Private_ properties should begin with an underscore and be camelCased. _Protected_ and _Public_ should simply be camelCased. It is preferrable to label _public_ properties as such, but is not exactly required. It's preferred because by default non-labeled properties are considered public. However in C#, non-labeled properties are considered private. I think consistency across our two most used languages would be a good thing to pursue.

*Fail:*
```typescript
class CarModel {
    constructor() { }
    
    TestPrivateProperty = 1;
    TestProtectedProperty = true;
    TestPublicProperty = 'I am public';
    TestPublicProperty2 = 'So am I';
}
```
*Pass:*
```typescript
class CarModel {
    private _testPrivateProperty: number = 1;
    protected testProtectedProperty: boolean = true;
    public testPublicProperty: string = 'I am public';
    testPublicProperty2: string = 'So am I';

    constructor() { }
}
```

###Class Method Definitions
Class methods should be camelCased. Each method should be properly labeled _private_, _protected_, or _public_ with the exception of the constructor. It is preferrable to label _public_ methods as such, but is not exactly required. It's preferred because by default non-labeled methods are considered public. However in C#, non-labeled methods are considered private. I think consistency across our two most used languages would be a good thing to pursue.

Also opening brackets are on the same line as the method name, and the closing bracket is on a new line.

*Fail:*
```typescript
class CarModel {
    TestPrivateMethod(): number {
        return 1;
    }
    TestProtectedMethod(): boolean {
        return true;
    }
    TestPublicMethod(): string {
        return 'I am public';
    }
    TestPublicMethod2() {
        return 'So am I';
    }
}
```
*Pass:*
```typescript
class CarModel {
    private testPrivateMethod(): number {
        return 1;
    }
    protected testProtectedMethod(): boolean {
        return true;
    }
    public testPublicMethod(): string {
        return 'I am public';
    }
    testPublicMethod2(): string {
        return 'So am I';
    }
}
```

#C#
The following rules are based on C#.

###Class Names should be in PascalCase format

*Fail:*
```typescript
class carModel { }
```
*Pass:*
```typescript
class CarModel { }
```

###Class Property Definitions
Class properties should be listed before the constructor. Each property should be properly labeled _private_, _protected_, or _public_ and listed in that order. _Private_ properties should begin with an underscore and be camelCased. _Protected_ and _Public_ should simply be PascalCased. It is preferrable to label _private_ properties as such, but is not exactly required. It's preferred because by default non-labeled properties are considered private. However in TypeScript, non-labeled properties are considered public. I think consistency across our two most used languages would be a good thing to pursue.

*Fail:*
```typescript
class CarModel {
    CarModel() { }
    
    int TestPrivateProperty = 1;
    bool TestProtectedProperty = true;
    string TestPublicProperty = 'I am public';
    string TestPublicProperty2 = 'So am I';
}
```
*Pass:*
```typescript
class CarModel {
    private int _testPrivateProperty = 1;
    protected bool TestProtectedProperty = true;
    public string TestPublicProperty = 'I am public';
    public string TestPublicProperty2 = 'So am I';

    CarModel() { }
}
```

###Class Method Definitions
Class methods should be PascalCased. Each method should be properly labeled _private_, _protected_, or _public_. It is preferrable to label _private_ methods as such, but is not exactly required. It's preferred because by default non-labeled methods are considered private. However in TypeScript, non-labeled methods are considered public. I think consistency across our two most used languages would be a good thing to pursue.

Also, opening and closing brackets are on new lines.

*Fail:*
```typescript
class CarModel {
    int TestPrivateMethod() {
        return 1;
    }
    bool TestProtectedMethod() {
        return true;
    }
    string TestPublicMethod()
    {
        return 'I am public';
    }
    string TestPublicMethod2()
    {
        return 'So am I';
    }
}
```
*Pass:*
```typescript
class CarModel {
    private int TestPrivateMethod()
    {
        return 1;
    }
    protected bool TestProtectedMethod()
    {
        return true;
    }
    public string TestPublicMethod()
    {
        return 'I am public';
    }
    public string TestPublicMethod2()
    {
        return 'So am I';
    }
}
```

#Conclusion
This is a work in process document. These standards and guidelines will change and evolve over time.