HipSquare Collaboration Guidelines and Coding Conventions #

The guidelines and conventions outlined in this document are focused on collaborating on code. Please also see our Code of Conduct for our general collaboration in HipSquare.

Versioning #

Semantic Versioning #

If Continuous Integration/Deployment isn’t possible, we follow the principles of semantic versioning.

<major>.<minor>.<patch>

Breaking changes result in a major version update.
Features (with or without Bugfixes) result in a minor version update.
Hotfixes result in a patch.

Examples:

Branching #

Git Flow is a nice (but not mandatory) framework, which follows the principles of semver.

If a ticketing tool is in use (Gitlab issues, Jira, …), it’s desirable to have a reference to the ticket or story in the branch name.

New branches should always be started from the latest base branch (main or develop).
The branch name should contain the type of ticket, the project abbreviation and the ticket number:

<type>/<project>-<number>

Valid types would be:

To avoid merge request being too large to review it’s reasonable to have a base branch to work on. Further outcoming branches will be merged back into the base branch.
An additional descriptive suffix is advised.

Examples:

No code gets merged into main without a Merge Request. No Merge Request gets merged without review. No Merge Request gets self-approved.

Commit Messages #

Commitlint

A format, such as described in the provided link is desirable.

Commit messages would then follow the format:

<type>(<?scope>): <subject> #scope is optional

Valid types would be:

In a monorepo the scope can be one of the packages.

In a larger application it can be a certain module, such as auth or user or product or the name of the app.

The message itself should be starting with a descriptive verb in the present tense.

Examples:

Hooks #

Given that a tool such as Husky is being used:

Merge requests #

The only way code reaches the main branch of a repository is via merge requests. We require at least one approving review for any merge requests.

Our attitude towards merge requests #

Merge requests play an important role for several reasons:

To get the most out of the merge request process, we approach merge requests with a positive mindset:

Writing good merge requests #

We work with merge request templates wherever possible. As a merge request author, I will at least describe:

Merge request titles #

We use merge request titles that comply with our commit message format.

Coding Conventions #

Common rules: #

Use descriptive names for functions and variables.

Add comments and documents where necessary.

Add tests.

Add proper typings for arguments and return values.

Function names should be descriptive and start with a verb, such as getUsers or convertImage.

The usage of a prettier and/or a linter is required.

This keeps the format consistent, while shifting the task of formatting to the IDE.

Formatting #

Names #

Rules to be discussed: #

Clean and Working Code #

When setting up new projects, let’s make sure that at least two quality gates are in place:

Code documentation #

Code documentation is a helpful practice that can improve the experience of everyone working on the project - other developers, non-developers (e.g. through storybook), and yourself. IDEs like VSCode natively use code documentation for tooltips, quickly informing developers about what a function or component is supposed to do.

JSDoc #

We use JSDoc for code documentation.

Style and scale #

Documentation should be short and to the point. Usually a sentence or sentence fragment will suffice. If additional information is available online, use the @see tag followed by a link. You can use markdown to style the link (example: @see [Google](https://www.google.com) for any further questions).

Maintanance #

Be aware that documentation needs to be maintained. Over time code may change, and there is no way to automatically verify that old documentation is still correct and useful. Check if documentation needs to be updated before you make a merge request.

React components #

Every react component should have a JSDoc description. Every prop should have a description as well.

Example:

export interface StatusCardProps {
  /** (optional) Decider function for the overall status */
  overallStatusDecider?: (statusModels: StatusModel[]) => StatusType;
  /** Data of the substatuses */
  subStatuses: StatusModel[];
  /** Card title */
  title: string;
}

/** Card for displaying sub-statuses and a computed overall status */
const StatusCard: FC<StatusCardProps> = ({
Storybook #

The Storybook docs plugin automatically makes the component documentation available in the Storybook UI.

If necessary use argTypes to fine-tune how props are displayed in Storybook. You can also hide technical props from the storybook display which would be confusing or distracting from the core functionality of the component. Do use your best judgement though, oversimplification might be misleading.

See Document for stakeholders for further information on documenting in Storybook.

Function, classes and members #

Write documentation at least for every class and function, which is exported and as such reusable.

Write documentation at least for each public method of (exported) classes.

For functions and members: Use @param tags to describe parameters and the @returns tag for the return value.

DRY #

Don’t repeat yourself.

Common and repetitive patterns should be abstracted and extracted into helper functions or components.

KISS #

Keep it stupid simple.
Lengthy and complex methods and functions should be avoided.

Exit early. Error cases should be managed early in a function to avoid unnecessary computation.

Try to avoid chained promises.

Use async/await instead.

Try to avoid else and/or nested if/else statements.
Use only a single if if applicable.

Try to avoid any at all. Use proper types.

Typings #

Types increase code quality and readability tremendously. It always an easier introduction to unknown or unfamiliar codebases, while also serving as a primitive documentation.

When creating a new project the languages and tools using types should always be favored over untyped equivalents.

Languages with dynamic typing, but support for strong/static typing should be used with their respective option. For instance, TypeScript should always be preferred over JavaScript.

Projects should always have and derive types.

Tests #

Try to follow Test-driven development(TDD).

A test suite should test everything that could possibly break.

Try using a coverage tool.

Test boundary conditions. (We often get the middle of a logic right but misjudge the boundaries)

The test cases should be extended if a bug gets fixed which was caused due to a flaw in the logical parts of our codebase.

CI, CI and Repositories #

We aim to keep all CI-/CD-related things close to our source code and hence use GitLab CI for our projects. This includes:

All CI jobs need to be described in files inside GitLab (either the project repository or, if it makes sense, some overarching repository). Let’s try to avoid using any other CI/CD tooling (no Jenkins anymore 🥳).