Неправильные названия функций в C++ | OTUS
⚡ Подписка на курсы OTUS!
Интенсивная прокачка навыков для IT-специалистов!
Подробнее

Курсы

Программирование
Backend-разработчик на PHP
-9%
Алгоритмы и структуры данных
-9%
Team Lead
-6%
Архитектура и шаблоны проектирования Разработчик IoT
-13%
C# Developer. Professional
-9%
HTML/CSS
-11%
C# ASP.NET Core разработчик
-5%
Kotlin Backend Developer
-8%
iOS Developer. Professional
-8%
Symfony Framework C++ Developer. Professional Java Developer. Basic JavaScript Developer. Professional Базы данных Android Developer. Professional Framework Laravel Cloud Solution Architecture Highload Architect Reverse-Engineering. Professional Vue.js разработчик Agile Project Manager Интенсив «Оптимизация в Java» Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Супер-интенсив «СУБД в высоконагруженных системах» Супер-интенсив "Tarantool" PHP Developer. Basic
Инфраструктура
Administrator Linux.Basic
-10%
Мониторинг и логирование: Zabbix, Prometheus, ELK
-10%
Экспресс-курс «CI/CD или Непрерывная поставка с Docker и Kubernetes»
-30%
Administrator Linux. Professional
-6%
Дизайн сетей ЦОД
-13%
Разработчик IoT
-13%
Экспресс-курс по управлению миграциями (DBVC)
-10%
Основы Windows Server MS SQL Server Developer Разработчик программных роботов (RPA) на базе UiPath и PIX Microservice Architecture Reverse-Engineering. Professional Внедрение и работа в DevSecOps Супер-практикум по работе с протоколом BGP Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Экспресс-курс «IaC Ansible» Network engineer. Basic
Корпоративные курсы
Безопасность веб-приложений Пентест. Практика тестирования на проникновение Экспресс-курс «CI/CD или Непрерывная поставка с Docker и Kubernetes»
-30%
IT-Recruiter
-15%
Дизайн сетей ЦОД
-13%
Компьютерное зрение
-13%
Enterprise Architect
-6%
Экосистема Hadoop, Spark, Hive
-8%
Экспресс-курс по управлению миграциями (DBVC)
-10%
Основы Windows Server SRE практики и инструменты Cloud Solution Architecture Разработчик голосовых ассистентов и чат-ботов Agile Project Manager Супер-практикум по работе с протоколом BGP Infrastructure as a code in Ansible Супер-практикум по использованию и настройке GIT Промышленный ML на больших данных Супер-интенсив Azure Системный аналитик. Advanced
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Неправильные названия функций в C++

Правильность названия функций очень важна, особенно когда вы разрабатываете пользовательский API. Имя может понятно описывать действие функции, а может быть попросту бесполезным. И с такой ситуацией вы столкнетесь даже при использовании стандартных библиотек. Давайте посмотрим парочку примеров на C++20.

Функция № 1: std::log2p1()

Первая наша функция — std::log2p1(). Код выглядит следующим образом:

Screenshot_1-1801-85d4a1.png

В нашем случае функция попросту возвращает двоичный логарифм числа + 1, что, в принципе, можно понять и из её названия.

Но какова же польза?

В реальности std::log2p1(x) возвращает число битов, нужных для хранения x. Да, это нужная функция, однако проблема заключается в том, что ее название не отражает в действительности сути выполняемой операции.

Функция № 2: std::bless()

Как известно, в С++ предусмотрены указатели. Указатель — это, по сути, переменная, в которую записывают адрес другого объекта в памяти. Над указателем вы можете выполнять арифметические действия, но лишь в том случае, если он элемент массива. Почему? Потому что невозможно вычитать либо прибавлять что-либо к произвольному указателю — в этом отсутствует смысл, ведь расположение объектов в памяти нам неизвестно.

Screenshot_2-1801-d7c456.png

Но данное действие не будет явной ошибкой. Оно просто становится причиной неопределенного поведения (то есть результата, зависящего от состояния памяти, компилятора, лунной фазы, вашего настроения и прочих случайностей).

Но вообще, проблема сводится не к недостаточно прозорливым разработчикам, которые почему-то складывают указатели (это же ведь не запрещено), а непосредственно к языку программирования С++. Именно поэтому Ричард Смит, специалист из компании Google, предложил добавить в стандарт следующую функцию:

std::bless(void* ptr, std::size_t n)

Для чего это было сделано? Да чтобы в случае надобности автоматически выделить массив памяти, разрешив тем самым арифметический вопрос для указателей. При этом, разумеется, имя bless никоим образом не сообщает об этих нововведениях.

Следовательно, решили придумать иное название для функции. Тут уже за дело взялся комитет развития языка C++, а в качестве кандидатов они выдвинули версии implicitly_create_objects() и implicitly_create_objects_as_needed(), которые можно перевести, как «неявное создание объектов» и «неявное создание объектов при необходимости».

Эти имена вполне логичны, ведь функция выполняет как раз то, что в них сказано. Однако согласитесь, если не знать предысторию, совершенно непонятно, а зачем вообще надо создавать какие-нибудь объекты.

Функция № 3: std::popcount()

Очередная стандартная функция C++ 20. Глядя на имя, попробуйте угадать, что конкретно она делает. Что-то считает? А может, это как-то связано со стековыми операциями push и pop?

В большинстве случаев вы даже не догадаетесь, если не знаете о низкоуровневой инструкции с аналогичным названием. Функция popcount (сокращение от «population count») считает число установленных в машинном слове битов.

Вроде бы, это неплохое имя, но только если все разработчики знают имена битовых ассемблерных операций. Но будет ли это очевидно новичку, который не знает тонкостей?

Как же называть функции?

Собственно говоря, ни одно из имен выше нельзя назвать откровенно плохим: названия вроде как описывают действия функций. Однако для вас, как для пользователей, такие имена, по сути, бесполезны, ведь они содержат не ту информацию, которая действительно необходима.

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

Однако проблема имен касается не только стандартных библиотек. Именно поэтому, если в проекте предполагается, что кодом кто-то будет пользоваться далее, выбирайте говорящие названия и смотрите на эти функции с точки зрения пользователей.

По материалам статьи «Naming Things: Implementer vs. User Names» — https://foonathan.net/2019/11/implementer-vs-user-names/.

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться