Coding Standards
Short URL: https://bevry.me/coding-standards/
All languages
Scaffolding and maintenance of our projects is automated thanks to our boundation
utility.
Semantic Versioning
Bevry abides by semantic versioning principles, that is to say:
- Major releases
v1
, contain breaking changes for everyone - Minor releases
v1.1
, contain breaking changes for some people - Patch releases
v1.1.1
, contain no breaking changes
When specifying dependencies, we will use the ~
operator at the start of the version number to allow upgrades to new patch releases only within the same minor release. E.g., ~1.3.2
allows versions from 1.3.2
up to, but not including, 1.4.0
.
We don’t allow new minor versions to be automatically installed because doing so could mean that things break when the project is re-installed. Re-installs often happen when doing a production deployment, a new person installs your project, or simply when you come back to you project after a period of inactivity.
Though minor relases are supposed to be backwards compatible with previous minor releases in the major release, we found through experience that this is frequently not actually the case. See npm issue #4587 for further discussion of this.
Packaging
Bevry publishes module to the npm registry with either the import
or require
module syntaxes.
We no longer support the component and Bower package managers. The reasons for this are:
- Bower and Component introduce extra complexity by not having any stance on which module loader you should use.
- Extra support (such as UMD header definitions) was required for the module loaders AMD, Require.js, and Global Namespacing (aka none).
- The testing and support load was increased significantly for Bower and Component, and in particular it is inconvenient to write automated tests to ensure that the library loads properly in each different package management system and load environment.
- Bower and Component both use Git repositories as their registry, meaning that you must bundle the production distribution of your package with your source files in your Git repository. This makes your Git repository get quite large and pollutes the change history.
For those who want the ultimate simplicity, tools like unpkg.com and jspm.io allow you to easily just create CDN ready distros of npm published modules right away, for instant inclusion in your application. Awesome.
So for all those reasons, we feel the utility belt surrounding npm is the ultimate solution. Whereas solutions like AMD, Require.js, Bower, and Component, just cause headaches.
Spelling
US English should be used within your code. This is because the majority of modules are written in US English and it would cause needless inconsistencies in your code if in some places you used color
and others colour
.
Formatting
Overall we use stock Prettier with our own Adaptive ESLint Configuration for formatting.
Indentation
Tabs should be used for indentation. This is because:
- Tabs allow everyone who uses your code to view it with their ideal indentation size.
- Tabs help prevent incorrect indentation that can cause unsightly code as well as errors in indentation based languages. (A missing space is very difficult to notice.)
Naming Convention
Class names should be CamelCase, while everything else should be camelCase. Acronyms and initialisims should be capitalized.
class JSONHandler {
toJSON () { /* ... */ }
}
jsonHandler = new JSONHandler()
jsonHandler.toJSON()
Sections
Sections are used to indicate when the context of the code has changed, for instance grouping of particular functions or logic. Sections have two main advantages, they increase the speed of noticing and understanding context changes, as well as increasing the speed of cognition - without having to actually read any code.
The main sections and sub sections utilise a horizontal rule. The last part of the horizontal rule should always lay on the 40th column. The headings should be concise (only a few words max)
The structure is like so:
# =====================================
# Main Section
# -------------------------------------
# Sub Section
CoffeeScript
Information specific to CoffeeScript is as follows:
Parentheses
Use parentheses as much as possible, especially when:
- when the function call accepts only a few arguments, e.g.
complete(err)
- when the function call is before another statement, e.g.
return fatal(err) if err
- when the function call utilises the
?
operator, e.g.next?(err)
Occasionally it is okay to not use them, such as when:
- the function call utilises a single inline callback which is the last argument:
path.exists __filename, (exists) ->
- the function call accepts unlimited arguments:
console.log "Hello"
Returning Values from Functions
Each function should have an explicit return. If there’s no obvious return value, and the function is an OO method, return this
or self
to be used for chaining method calls. If you wish to utilise CoffeeScripts automatic return ability, then a comment stating you are using this should be used each time.