# Code of Conduct
For this project to succeed and stay maintainable the following code of conduct must be held at all times.
# Follow established standards (ES)
Following established standards will keep maintainability at a high level because everyone in the project sets things
the same way and use the same structure for their code. Use your editors format code feature to format the code
using the supplied .editorconfig file settings.
# Strict Typing and Type Hinting
Even when type hinting is not necessary, please type hint your code. There is only 1 exception to this rule. Controller arguments do not have to be type hinted since GraphQL makes sure that the type is respected.
Please refrain from using any on variables when you could easily define a type for your object.
Keep all type definitions in the types.ts file in the core directory.
# Async/Await
Always use async/await when you are dealing with promises, never use Method(..).then().
# Code Formatting
We use 4 spaces for tabs in this project. Please adjust your IDE to that standard. We also follow a strict format of code like the following examples
class MyClass
{
/**
*
* What this method does explained here
*
* @param name
* @return Promise<string>
*
*/
public async myMethod(): Promise<string>
{
let myVar = true;
switch (value)
{
case '1':
break;
case '2':
break;
}
array.forEach((item) =>
{
// sync stuff
});
// For loop (before 2.2.0)
for (let i = 0; i < items.length; i++) {
// Async stuff
}
// For Loop (starting a v2.2.0)
for (let item of items) {
// Async stuff
}
if (itemA !== itemB) {
return 'A';
} else {
return 'B';
}
}
}
# Separation of Concern (SoC)
When creating a class, please refrain from addressing many different subjects (concerns) within the same class. For example,
if you create a class for Animal, don't handle Dog and Cat related things. Instead, create a Dog class and a Cat class that
extend or implement the Animal class.
A good example of this, the Provider / Writer structure in the project. A provider never writes to the database. A writer can read as long as it writes something in the end. If you look into the code, you will often see a provider call another provider to get something from the database. This is best practice, that means that you are not loading an instance of the required collection yourself and having unrelated code all over your class.
Here is an example of what that means:
Let's say you have a you have a class named Dog and you want to get a list of the dog's cat friends. A bad way to do it
would be something like this
public async doSomethingThatGetsADogAndItsFriends(dog_id: string): Promise<Dog|null>
{
let cat = model<Cat.CatModel>('cats', Cat.CatSchema);
dog.friends = await cat.find({...}).exec();
return dog;
}
A good way would be to ask the provider to handle it
public async doSomethingThatGetsADogAndItsFriends(dog_id: string): Promise<Dog|null>
{
let cat = new CatProvider();
dog.friends = await cat.getFriendsOf(dog_id);
return dog;
}
They both work, but the first example will load Model from mongoose, the Cat schema and have traces of Cat related things in your class. If you ever want to change the name of the registered model name, you are going to have to change it everywhere you have used it. Painful!
The second one loads the provider only and will return the data, you do not have to do anything else.
# File naming (SoC part 2)
If you take a look at most of the code, files are named with their type before the .ts part. Out of the box, this is
ridiculous because it's already in a folder named that type. But the reason is for code legibility and knowing without
deciphering the path what the file does. For example in the code a controller looks like this:
import { WhateverController } from "../../controllers/whatever.controller";
Since we do not put the .ts in the import, the last thing we see is .controller. This is true for most of the system's
classes. Containers, Controllers, Schemas, Providers, Writers, etc.
So this is why it's important to name your files appropriately. We also name our files in all lowercase and with the name of the class that it exports.
# Meaningful variable names and method names
In this project we use the Objective-C/Swift way of naming methods. Like getBookingsForCustomer instead of something like
getBookings which is not explicit enough in the case of getting bookings for a specific customer. The name getBookings
would make more sense for a method that would allow getting for a customer, skier or all.
Please also use meaningful variable names so the code is always readable.
# Use SonarLint for code quality
Since version 2.3, we use SonarLint to clean up the code, this is an ongoing effort and all new code should follow it's recommendations to write less code, have less to no dead code (unused code) and have a tighter api.
# Git
Do not create a dev/your-name branch, please use GitFlow for your development. Each big feature should have its own
branch. For example, ASSQ's SGR (Système de Gestion de la Relève) has its own branch since it's a big feature. For smaller
changes/fixes you can put them all in a more global feature branch (eg: feature-bugfixes or feature-misc).
# Changelog maintenance
It is also important to keep the changelog file up to date with what has changed between versions
This is the format to use:
Version major.minor.revision
Section Affected
- Whatever was done here keep it as short as possible (your firstname)
For example:
Version 2.1.4
General
- Added landing page detection after login and loginWithToken (marc)
- Various bug fixes (marc)
- Cleaned up some imports (marc)
# Final Note
Following this code of conduct is mandatory. Any developer not respecting it will be kicked off the project. It's a project too big to write poor/dirty/unsafe code. No exceptions.