Clean Code на C++: принципы и примеры на практике

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Clean Code на C++: принципы и примеры на практике

Каждый разработчик C++ рано или поздно сталкивается с проблемой поддержки собственного или чужого кода. Сложные шаблоны, перегруженные функции и бесконечные макросы превращают проект в кошмар. Концепция Clean Code (чистого кода), популяризированная Робертом Мартином, предлагает простые, но эффективные правила, которые делают код понятным, безопасным и лёгким для модификации. В этой статье мы разберём ключевые принципы Clean Code применительно к C++ и покажем, как применить их на практике.

1. Имена переменных и функций: говорите, что делаете

Первое правило чистого кода — имя должно раскрывать намерение разработчика. В C++ это особенно важно из-за обилия указателей, ссылок и перегрузок.

Плохой пример:

int d; // elapsed time in days
void f(int* a, int n); // ???

Хороший пример:

int daysSinceLastLogin;
void processUserData(const std::vector<int>& userIds);

Используйте полные слова, избегайте однобуквенных переменных (кроме индексов в коротких циклах). Для булевых переменных применяйте префиксы is, has, should:

bool isValidInput;
bool hasPermissions;

Классы и структуры называйте существительными, а функции — глаголами или глагольными сочетаниями: class UserAccount, void calculateSalary().

2. Функции: маленькие, с одной ответственностью

Функция должна делать только одно дело и делать его хорошо. Максимальная длина — 20-30 строк. Если функция занимает больше, разбейте её на вспомогательные.

Плохой пример (монолитная функция):

void processOrder(Order& order) {
    // проверка платежа
    // обновление склада
    // отправка email
    // логирование
    // генерация чека
}

Хороший пример (декомпозиция):

void processOrder(Order& order) {
    if (!validatePayment(order)) return;
    updateInventory(order);
    sendConfirmationEmail(order);
    logTransaction(order);
    generateReceipt(order);
}

Старайтесь избегать побочных эффектов. Функция не должна изменять глобальные переменные или переданные по ссылке аргументы без явного указания в имени (resetData, fillBuffer).

3. Работа с памятью и ресурсами: RAII и умные указатели

C++ даёт полный контроль над памятью, но это ведёт к утечкам. Clean Code предлагает использовать идиому RAII (Resource Acquisition Is Initialization) и умные указатели вместо сырых new/delete.

Плохой пример (ручное управление):

void process() {
    int* data = new int[100];
    // ... много кода ...
    if (error) {
        delete[] data;
        return;
    }
    delete[] data;
}

Хороший пример (RAII):

void process() {
    std::unique_ptr<int[]> data = std::make_unique<int[]>(100);
    // ... код ...
    // delete вызывается автоматически при выходе из области видимости
}

Для разделяемого владения используйте std::shared_ptr, для слабых ссылок — std::weak_ptr. Никогда не возвращайте сырые указатели на внутренние данные — используйте ссылки или умные указатели.

4. Обработка ошибок: исключения и коды возврата

Чистый код требует явной и предсказуемой обработки ошибок. В C++ есть два основных подхода: исключения и коды возврата. Выбирайте один стиль в рамках проекта.

Плохой пример (игнорирование ошибок):

int divide(int a, int b) {
    return a / b; // деление на ноль!
}

Хороший пример (исключения):

int divide(int a, int b) {
    if (b == 0) {
        throw std::invalid_argument("Division by zero");
    }
    return a / b;
}

Если вы используете коды возврата, делайте их понятными:

enum class ErrorCode { SUCCESS, INVALID_INPUT, NOT_FOUND, TIMEOUT };

ErrorCode loadConfig(const std::string& path, Config& out);

Избегайте пустых блоков catch — это скрывает ошибки. Ловите исключения по константной ссылке (const std::exception&).

5. Комментарии: только "почему", не "что"

Чистый код самодокументируем. Комментарии нужны для объяснения бизнес-логики, сложных алгоритмов или причин выбора конкретного решения. Не комментируйте очевидное.

Плохо:

// Увеличиваем счетчик на 1
counter = counter + 1;

Хорошо:

// Используем 64-битный тип из-за возможного переполнения
int64_t totalBytes = calculateSize();

Избегайте закомментированного кода — используйте системы контроля версий (Git). Если комментарий устарел, удалите его.

Заключение

Принципы Clean Code на C++ — это не догма, а набор практик, которые экономят время разработчиков и снижают количество багов. Начните с малого: давайте осмысленные имена, разбивайте большие функции на маленькие, используйте умные указатели и пишите комментарии только по делу. Помните: код читается гораздо чаще, чем пишется. Инвестируйте в чистоту — и ваша кодовая база скажет вам спасибо.

Блоги

Рекомендаций по книгам