1053_60_cpp_antipatterns_ru/image2.png


Перед вами обновлённая коллекция вредных советов для C++ программистов, которая превратилась в целую электронную книгу. Всего их 60, и каждый сопровождается пояснением, почему на самом деле ему не стоит следовать. Всё будет одновременно и в шутку, и серьёзно. Как бы глупо ни смотрелся вредный совет, он не выдуман, а подсмотрен в реальном мире программирования.


Я буду публиковать советы по 5 штук, чтобы не утомить вас, так как мини-книга содержит много интересных отсылок на другие статьи, видео и т. д. Однако, если вам не терпится, здесь вы можете сразу перейти к её полному варианту: "60 антипаттернов для С++ программиста". В любом случае желаю приятного чтения.


Вредный совет N41. const — лишняя сущность


Слово const только место в коде занимает. Если вы не хотите менять переменную, то просто не будете её менять.


Действительно, не хочешь – не меняй. Вот только беда в том, что человеку свойственно ошибаться. Квалификатор const позволяет писать более надёжный код. Он защищает от опечаток и других недоразумений, которые могут возникнуть в процессе написания или рефакторинга кода.


Пример ошибки, найденной нами в проекте Miranda NG:


CBaseTreeItem* CMsgTree::GetNextItem(....)
{
  ....
  int Order = TreeCtrl->hItemToOrder(TreeView_GetNextItem(....));
  if (Order =- -1)
    return NULL;
  ....
}

Рука программиста дрогнула, и в условии вместо проверки, чему равна переменная, ей присваивается новое значение. Предположим, что было бы использовано ключевое слово const:


const int Order = TreeCtrl->hItemToOrder(TreeView_GetNextItem(....));
if (Order =- -1)
  return NULL;

Тогда такой код просто бы не скомпилировался.


А вот с точки зрения оптимизации кода от const мало пользы. В некоторых статьях можно встретить рассуждение: делая переменные константами, вы помогаете компилятору и он сможет генерировать более оптимизированный код. Это завышенные ожидания. См. статью "Почему const не ускоряет код на С/C++?". Другое дело – constexpr. Это ключевое слово открывает интересные возможности для проведения многих вычислений ещё на этапе компиляции кода: "Дизайн и эволюция constexpr в C++". Почитайте эту статью, не пожалеете.


Вредный совет N42. Винтаж — это прикольно


А вы знаете, что вместо фигурных скобок можно использовать <% и %>? Диграфы и триграфы могут придать вашему коду визуальную свежесть и необычность, что выделит его на фоне кода коллег. И при этом ничего незаконного, они же есть в стандарте.


На самом деле, этот антисовет про винтажность сам является винтажным. Дело в том, что в стандарте C++17 триграфы отменены.


Однако вы по-прежнему можете использовать в C++ диграфы. А в программах на языке C остались и триграфы. Плюс для истинных поклонников старины компилятор Visual C++ позволяет продолжить использовать триграфы, если указать ключ /Zc:trigraphs.


Вредный совет N43. Не инициализируй


Зачем инициализировать переменные, если там и так нули? Я вот недавно не инициализировал, и там ноль был. Всё работало.


Никто не воспримет совет использовать неинициализированные переменные всерьёз. Эта ошибка новичков в программировании. Конечно, профессиональные разработчики тоже допускают такие ошибки, но это не массовое явление. По крайней мере, это более редкая ошибка, чем, например, разыменование нулевого указателя.


Почему эту ошибку допускают новички? Мне кажется, есть две причины, которые сбивают их с толку.


Во-первых, значение неинициализированной переменной может случайно оказаться равно нулю. Поскольку обычно именно нулём и нужно было инициализировать переменную, то создаётся впечатление, что программа работает правильно. Естественно, это просто везение, а, строго говоря, использование неинициализированной переменной приводит к неопределённому поведению. Просто в данном случае получается, что неопределённое поведение программы совпадает с ожидаемым правильным поведением :).


Во-вторых, в C++ есть разница между локальными и глобальными переменными. Локальные переменные не инициализируются значением по умолчанию. А вот глобальные — инициализируются автоматически. Всё это дополнительно вносит путаницу, когда вы ещё только учитесь программировать.


На десерт предлагаю статью: "Инициализация в С++ действительно безумна. Лучше начинать с Си".


Аннотация. Недавно мне напомнили, почему я считаю плохой идеей давать новичкам C++. Это плохая идея, потому что в C++ реальный бардак — хотя и красивый, но извращённый, трагический и удивительный бардак. Несмотря на нынешнее состояние сообщества, эта статья не направлена против современного C++. Скорее, она частично продолжает статью Саймона Брэнда "Инициализация в C++ безумна", а частично — это послание каждому студенту, который хочет начать своё образование, глядя в бездну.

Вредный совет N44. Доверяй всем


Модификаторы доступа private и protected для параноиков. Кому они нужны, эти поля класса?


Новичку в программировании может показаться, что удобно, когда все члены класса являются публичными. Ведь тогда имеется возможность поменять любую переменную в классе или вызвать любую функцию класса.


Платой за такой подход является сложность сопровождения, модификации и отладки кода. Поскольку данные в классах изменяются в разных частях программы, очень сложно потом разобраться, как всё это работает, а уж тем более вносить какие-то изменения в логику программы. В результате начальная простота быстрого написания кода в дальнейшем оборачивается большим количеством ошибок и сложностями развития программы.


Фактически, нарушается один из базовых принципов ООП — инкапсуляция. Тема инкапсуляции и её пользы выходит за рамки этого текста. Поэтому опытные программисты со словами: "И так всё понятно", — могут продолжить чтение :). А новичков я отсылаю к великолепной фундаментальной книге Гради Буча "Объектно-ориентированный анализ и проектирование с примерами приложений на С++".


Вредный совет N45. Не парься над именованием переменных


Заведите как можно больше переменных, которые будут отличаться в названиях только числами: index1, index2.


1053_60_cpp_antipatterns_ru/image23.png


Этот антисовет – отсылка к статье "Ноль, один, два, Фредди заберёт тебя", где рассказывается, как легко допустить опечатку при использовании таких имён, как A0, A1, A2.


Об этой мини-книге


Автор: Карпов Андрей Николаевич. E-Mail: karpov [@] viva64.com.


Более 15 лет занимается темой статического анализа кода и качества программного обеспечения. Автор большого количества статей, посвящённых написанию качественного кода на языке C++. С 2011 по 2021 год удостаивался награды Microsoft MVP в номинации Developer Technologies. Один из основателей проекта PVS-Studio. Долгое время являлся CTO компании и занимался разработкой С++ ядра анализатора. Основная деятельность на данный момент — управление командами, обучение сотрудников и DevRel активность.


Ссылки на полный текст:



Подписывайтесь на ежемесячную рассылку, чтобы не пропустить другие публикации автора и его коллег.

Комментарии (2)


  1. WinPooh73
    24.06.2023 05:20
    +2

    Сегодня затупил на Хабре,
    а завтра наступил на грабли.

    Сегодня кодишь понемногу,
    а завтра как прострелишь ногу!

    Сегодня не проверил код возврата,
    а завтра встал на скользкий путь разврата.

    Сегодня не закрыл кавычку,
    а завтра - пять гигов вам в личку.

    Сегодня пишешь go to,
    а завтра код - под хвост коту.

    Сегодня переполнил буфер,
    а завтра пришёл железный робот с лампочкой в носу, и тебя заменил.


  1. ap1973
    24.06.2023 05:20

    За исключением триграфоф всё тоже самое относится к большинству ЯП. Т.ч. наименование книги можно обобщить: типовые ошибки новичков.