... | ... | @@ -115,7 +115,7 @@ Prefer to build software when you really need it, otherwise it is a waste. Avoi |
|
|
But at the same time, provisioning certain things towards the future is okay. For example, the TCP/IP stack provisioned for some reserved bytes and although the standard is largely unchanged, it did provide the roadway towards IPv6. Another example is that if you are developing a communication standard, it is okay to provision for an extra byte for a `version` that allows you to amend the standard in the future.
|
|
|
|
|
|
## Modularize Code
|
|
|
Modularize code, and do not create `God Objects`. When you are dealing with a large problem, split the problem into smaller code modules and make the code only do one thing.
|
|
|
Modularize code, and do not create `God Objects`. When you are dealing with a large problem, split the problem into smaller code modules and make the code only do one thing. This allows for the module to be implemented with simple logic thus improving the overall code readability as well as making it easier to test.
|
|
|
|
|
|
If we are creating an HTTP client, do not put all the code into a single module. Instead, consider splitting this problem into small code blocks, such as:
|
|
|
|
... | ... | @@ -486,10 +486,11 @@ In the first example, we expect that the code integrator (customer) has resolved |
|
|
|
|
|
* **Use the verb-noun method for naming** routines that perform some operation on a given object, such as:
|
|
|
- `app_battery__calculate_soc()`
|
|
|
- This allows for the reader of the code to be able to easily understand the action that the function is taking.
|
|
|
|
|
|
|
|
|
## Variable Names
|
|
|
* Use standard capitalization rules for measurement variables even if it breaks acronym and abbreviation naming rules.
|
|
|
* Use standard capitalization rules for measurement variables even if it breaks acronym and abbreviation naming rules. This is done to reduce confusion of someone reading the code and expecting certain standard capitalization for measurement variables (i.e. meter = m, watt = W, pascal = Pa).
|
|
|
- `speed_mph`
|
|
|
- `time_left_ms`
|
|
|
* **Variables should be singular, and arrays should be plural.**
|
... | ... | @@ -765,6 +766,7 @@ Better alternatives to `#defines` are discussed below: |
|
|
* **Do not use more than 5 brace levels in your code**
|
|
|
* Refactor code into smaller functions
|
|
|
* Re-structure the branch statements to reduce the curly brace nesting
|
|
|
* This improves the overall readability of the code
|
|
|
|
|
|
* **No recursive functions**
|
|
|
- In Embedded Systems, the stack memory is precious, as there is usually not very much.
|
... | ... | @@ -776,7 +778,7 @@ Better alternatives to `#defines` are discussed below: |
|
|
* **Prefer at most 10 meaningful lines per function**
|
|
|
- This forces you to make the code more modular
|
|
|
- This helps during unit-testing
|
|
|
- Avoid using more than 4 `{}` brace levels in your code
|
|
|
- Avoid using more than 5 `{}` brace levels in your code
|
|
|
* Use **Yoda notation** in equality checks but not anywhere else.
|
|
|
* Example: `if (5 == value)` instead of `if (value == 5)`
|
|
|
* Because we don't want to accidentally assign the variable in the condition check.
|
... | ... | @@ -866,7 +868,7 @@ The reasons to use `sl_utils__memset_zero()` is that: |
|
|
* `memset()` may be used but it creates possibility of bugs because the parameters of this function may be swapped easily
|
|
|
* Note that `bzero()` is not recommended since it has been deprecated
|
|
|
|
|
|
Do not confuse the struct initialization with array initializtion which can use `= {0}`
|
|
|
Do not confuse the struct initialization with array initialization which can use `= {0}`
|
|
|
|
|
|
* `char array[2] = {0}`
|
|
|
|
... | ... | @@ -876,7 +878,8 @@ Do not confuse the struct initialization with array initializtion which can use |
|
|
TODO: Add more guidelines from MISRA
|
|
|
|
|
|
* **No recursive functions**
|
|
|
* **No dynamic memory allocation (MISRA C:2004, 20.4)** i.e. you are not allowed to use malloc and free
|
|
|
In Embedded Systems, the stack memory is precious, as there is usually not very much.
|
|
|
* **No dynamic memory allocation (MISRA C:2004, 20.4)** i.e. you are not allowed to use malloc and free as it can cause unintended issues when functions such as malloc are unable to provide a valid memory location.
|
|
|
* **No continue or goto statements (MISRA C:2012, 15.1)**
|
|
|
Because even the compiler itself cannot prevent stack corruption for this code:
|
|
|
```c
|
... | ... | @@ -937,7 +940,8 @@ TODO: Add more guidelines from MISRA |
|
|
```
|
|
|
* There should be no commented out code in the code base.
|
|
|
* No `#if 0` blocks
|
|
|
* No block comments that disable code (source control is your friend)
|
|
|
* No block comments that disable code (source control is your friend)
|
|
|
* This improves the readability of you code and reduces the amount of unnecessary code in the code base.
|
|
|
* Unsigned numbers should have `U` at the end. Example: `42U`
|
|
|
* Unsigned long numbers should have `UL` at the end. Example: `56UL`
|
|
|
* Do not write obfuscated 'smart' code - saving on the microseconds of processor time (or not even that) is not worth the headache of trying to understand someone else's tricky code which can take a long time and also be error prone.
|
... | ... | |