Coding Style
Každá firma má svůj vlastní coding style.
Můj coding style vychází ze standardů používaných v automobilovém průmyslu — vylepšených pro vývoj embedded systémů — protože je z mého pohledu nejčitelnější a nejlépe udržovatelný.
Níže je zdůvodnění každého pravidla a toho, jak přispívá k přehlednosti a dlouhodobé udržovatelnosti.
🔡 Proměnné
Proměnné musí používat pojmenování lower camelCase.
Název proměnné musí obsahovat alespoň tři znaky.
❌ Nesprávně
int x, y, z;
for(int i = 0; i < 10; i++) { ... }
✅ Správně
int loopIndex;
float temperatureCelsius;
uint8_t sensorCount;
📘 Proč: Každá proměnná musí mít smysluplný název.
Krátké, záhadné názvy ničí čitelnost a ztěžují údržbu kódu.
⚠️ Externí proměnné
Existence proměnných extern je přísně zakázána.
Pokud takovou proměnnou někdo najde, měl by být její tvůrce veřejně lynčován (obrazně 😉).
💡 Důvod:
Externí proměnné se téměř nedají vysledovat — nelze snadno zjistit, kdo je zapisuje nebo čte.
Data vždy zapouzdřete za gettery a settery.
🧱 Datové typy
Názvy typů se řídí vzorem lowerCamelCase, ale musí končit na _t,
podle standardního pojmenování používaného v <stdint.h> (např. uint8_t, uint16_t atd.).
✅ Příklad
typedef uint16_t temperature_t;
typedef float voltage_t;
typedef uint8_t humidity_t;
🧩 Důvod:
Okamžitě poznáte, zda identifikátor představuje typ, nebo proměnnou.
🚫 Vyhněte se obecným vestavěným typům
Nepoužívejte přímo ve svém projektu holé uint8_t, uint16_t atd.
Místo toho definujte vlastní, sémanticky smysluplné typedefy.
✅ Tím zabráníte míchání nekompatibilních proměnných:
nemůžete omylem přiřadittemperature_tdohumidity_t.
temperature_t temp = 25;
humidity_t humidity = 40;
temp = humidity; // ❌ Compilation error
Tím se vynucuje typová bezpečnost a zkracuje se doba ladění.
🧭 Názvy funkcí
Názvy funkcí musí používat styl UpperCamelCase.
Každá funkce by měla obsahovat prefix modulu, který objasňuje, komu patří.
✅ Příklad
rcc_InitSystemClock();
rcc_GetClockFrequency();
gpio_SetPinState(GPIOA, PIN_5, true);
📘 Proč:
Je okamžitě jasné, zda je identifikátor proměnná, funkce, nebo typ.
Prefix modulu umožňuje snadno najít funkci v hierarchii projektu.
⚙️ Direktivy preprocesoru
Direktivy preprocesoru a makra musí používat UPPER_CASE_WITH_UNDERSCORES.
✅ Příklad
#define MAX_SENSOR_COUNT 8
#define ENABLE_DEBUG_MODE 1
📘 Proč:
Velkými písmeny je okamžitě zřejmé, že jde o symbol času překladu, nikoli o proměnnou za běhu.
📄 Názvy souborů
Názvy souborů používají styl UpperCamelCase.
Každý název souboru musí začínat názvem modulu, následovaným podtržítkem a popisem funkcionality.
✅ Příklad
Rcc_Config.c
Gpio_Handler.c
Modbus_Transport.c
🧩 Kompletní struktura organizace souborů je popsána na samostatné wiki stránce:
File Organization
🗂️ Výčtové typy (enumy)
Výčtové typy používají UpperCamelCase pro typ a UPPER_CASE pro enumerátory.
✅ Příklad
typedef enum
{
STATE_IDLE,
STATE_RUNNING,
STATE_ERROR
} systemState_t;
📘 Proč:
Hodnoty psané velkými písmeny odlišují konstanty výčtu od proměnných, zatímco přípona_tjasně označuje typ.
🧮 Konstanty
Konstanty definované v kódu (nikoli makra) musí používat názvy v UpperCamelCase.
✅ Příklad
const uint32_t SystemTimeoutMs = 5000;
const float PiValue = 3.14159f;
💡 Kdykoli je to možné, preferujte
constpřed#define— poskytuje kontrolu typů a řízení rozsahu platnosti.
🧰 Struktury a unie
Názvy struktur používají UpperCamelCase,
zatímco jejich členy používají lowerCamelCase.
✅ Příklad
typedef struct
{
uint8_t deviceId;
uint16_t firmwareVersion;
float batteryVoltage;
} DeviceInfo_t;
📘 Proč:
Konzistentní velikost písmen jasně odlišuje typ struktury od jejích polí.
🔣 Makra a inline funkce
- Makra (
#define) → UPPER_CASE_WITH_UNDERSCORES - Inline pomocné funkce → UpperCamelCase (stejně jako běžné funkce)
✅ Příklad
#define ENABLE_INTERRUPTS() __enable_irq()
#define DISABLE_INTERRUPTS() __disable_irq()
static inline void DelayMs(uint32_t ms) { ... }
💬 Komentáře a dokumentace
Pro všechny veřejné funkce, typy a makra používejte komentáře ve stylu Doxygen.
✅ Příklad
/**
* @brief Initializes system clocks.
* @param None
* @retval None
*/
void Rcc_InitSystemClock(void);
💡 Komentáře udržujte krátké, přesné a psané anglicky.
Popisujte, proč se něco dělá, ne co se dělá — to by mělo být zřejmé z kódu samotného.
🧾 Pravidla formátování
| Pravidlo | Popis |
|---|---|
| Odsazení | 4 mezery, nikdy tabulátory |
| Složené závorky | Styl K&R ({ na stejném řádku) |
| Maximální délka řádku | 120 znaků |
| Mezery | Vždy mezera za čárkou a kolem operátorů |
| Prázdné řádky | Používejte k vizuálnímu oddělení logických částí |
| Include guardy | Formát #ifndef MODULE_FILENAME_H |
| Pořadí includů | <system> → "project" → "module" |
✅ Příklad
#include <stdint.h>
#include "Rcc_Config.h"
#include "Gpio_Handler.h"
void Gpio_Init(void)
{
gpioState_t state = GPIO_LOW;
if (state == GPIO_LOW)
{
gpio_SetPinState(GPIOA, PIN_5, true);
}
}
🧩 Jmenné prostory a prefixy
Každý modul musí mít jedinečný prefix (např. rcc_, gpio_, adc_).
Tím se zajistí, že se názvy funkcí a typů v systému nebudou kolidovat.
📘 Pravidlo pro zapamatování:
- Prefix = název modulu
- CamelCase = funkce
- _t = typ
- lowerCamelCase = proměnná
Příklad konzistence:
rcc_Init()
rcc_Config_t
rccState_t
rcc_GetClock()
✅ Shrnutí
| Prvek | Styl | Příklad |
|---|---|---|
| Proměnná | lowerCamelCase | loopIndex, sensorCount |
| Typ | lowerCamelCase + _t | temperature_t, systemState_t |
| Funkce | UpperCamelCase | Rcc_InitSystemClock() |
| Makro / Define | UPPER_CASE_WITH_UNDERSCORES | MAX_BUFFER_SIZE |
| Konstanta | UpperCamelCase | PiValue |
| Název struktury | UpperCamelCase | DeviceInfo_t |
| Člen struktury | lowerCamelCase | deviceId |
| Hodnota enumu | UPPER_CASE | STATE_IDLE |
| Název souboru | UpperCamelCase + podtržítko | Gpio_Handler.c |