# Principles
# Inspiration
We take a lot of inspiration from the work conducted by "uncle bob". We strongly suggest to watch the following video series to give you some insights:
https://www.youtube.com/watch?v=7EmboKQH8lM (opens new window)
https://www.youtube.com/watch?v=2a_ytyt9sf8 (opens new window)
https://www.youtube.com/watch?v=Qjywrq2gM8o (opens new window)
Keep the code clean
Strongly inspired by Uncle Bob we aim to apply the following clean code principles:
Stealing from this summary: http://www.inf.fu-berlin.de/inst/ag-se/teaching/K-CCD-2014/Clean-Code-summary.pdf (opens new window)
Naming
- Use meaningful, intention-revealing, pronounceable names
- Example of method name: addValueToSum or validateRequesterAccess or filterInspirationByCategories
- Avoid disinformation (accidental similarities with something else entirely or too-subtle name differences) and puns.
- Larger scopes require longer names (for successful searching)
- Use the same word for a concept consistently
- Use problem domain names for solution domain concepts and technical terms for solution domain concepts.
- Don't be afraid to globally change bad names (but watch out for breaking changes in other repos)
Functions
- Functions (methods) should be small and do only one thing.
- Example of how NOT to do it: getFromApiAndPersist instead this should be two methods: getFromApi and persist
- All statements should be exactly one level of abstraction below the concept represented by the function, that is, should be worth mentioning in a summary of the implementation. This implies avoiding nested control structures, switch statements, and most if-else-if chains.
- Order the functions thus broken down in depth-first order, so that the overall code can be read top-to-bottom.
- It is hard to overestimate the importance of descriptive and consistent names and of the absence of surprising side-effects.
- Parameters make functions harder to grasp and often are on a lower level of abstraction, so avoid them as best you can, e.g. by introducing conceptual helper classes or turning arguments into member variables.
- Avoid duplication. All this describes a good end result. Initially, you may well have long, ill-named, complex, parameter-rich functions that do many things. This is no problem, as long as you then go and refactor, refactor, refactor.
Comments
- "The proper use of comments is to compensate for our failure to express ourself in code." Comments do not make up for bad code, rather, we should express ourselves in the code.
- In Short: only write comments when they are critical for understanding the code
Formatting
- Adequate and uniform is required if you intend to communicate orderliness to your code's readers and to provide readability.
- Use a formatting tool
- We use StyleCi to fix the formatting issues after the code has been committed (see styleci.io)
- We use ESlint for auto formatting the JS+Vue code (each repo has a settings file)
- The length of the files is not essential - the key is that concepts and logic is contained in a meaningful way within the file
- For the backend: Good files are like newspaper articles, with a heading, the important stuff first, and details later
- Example: The class name is the title, the handle() method is the heading and the methods are the details
- Use blank lines to separate different code/logic and no blank lines to group related logic/code
- Keep somewhat-related stuff nearby in the file; functions below their calls.
- Use horizontal whitespace to indicate relatedness and separateness (but aligning columns emphasizes the wrong things).
# Dryness
As default we always attempt to write DRY code.
This is especially true when it comes to back-end code. Approaches we take in order to avoid repeating ourselves:
- Use dedicated "UseCase" classes instead of writing extensive code in the controller (more on this later)
- Use traits to give access to private methods across use cases or controllers (Laravel does this all the time by default e.g. "use AuthenticateUsers")
Note: we don't use parent classes and inheritance as default, but instead aim to use traits / mixins instead.
# Simplicity – make it easy to come back
Do not try to impress anyone by making "fancy" one-line methods that handle 3-4 responsibilities.
Instead we write simple and easy to read code that make it easier to come back to in 1-2 years from now.
The exception for this:
- When the shorter code results in less database load e.g. resulting in more calls
- The shorter code runs faster than the simpler version
- Laravel provides intelligent wrappers that speed up the code process e.g. "create", various collection methods etc.
# Protecting the database
Since all of the platform is run on a single database – and we expect to keep it that way for a long time – we need to not overburden the database.
As a result:
- Limit the calls to the database
- Use caching frequently
- Do not create unnecessary indexes
- Only add database tables and records when they add value
# Continuously clean up – follow the "boy scout rule"
The code base is far from perfect and often do not comply with our internal best practices.
In order to continuously add value to the business, we cannot stop all other development and "just" clean up for a meaningful period of time. Instead we "clean-up" on an ongoing basis as we come across areas of the code base that could benefit from refactoring, clean up, documentation etc.
Most frequently such clean up is conducted as part feature improvements, or feature expansions.
Typical clean up efforts:
- Refactor controller method to reusable use cases
- Remove non-value adding comments
- Refactor methods into smaller sub-methods
- Rename methods to comply with naming logic
- Implement "modules" in the Vuex store to share code across specialists and admins
In general we suggest to follow the boy scout rule of "always leave the code cleaner then when you found it" and never think that just because you didn't write the initial version you don't have to keep it cleaned and your updates.
# Incremental, frequent shipping
To fulfil the purpose of the tech team we need to deploy, working code into production with a high frequency.
Code does not add value on github – it needs to be in production.
We aim to split up new features, improvements into small code releases rather than massive PRs.
# Tests are important
We aim to add back-end tests for all new APIs
We add tests when fixing bugs
We make sure tests always pass
See test section
← Start here Changes →