Неправильные названия функций в C++
Правильность названия функций очень важна, особенно когда вы разрабатываете пользовательский API. Имя может понятно описывать действие функции, а может быть попросту бесполезным. И с такой ситуацией вы столкнетесь даже при использовании стандартных библиотек. Давайте посмотрим парочку примеров на C++20.
Функция № 1: std::log2p1()
Первая наша функция —
В нашем случае функция попросту возвращает двоичный логарифм числа + 1, что, в принципе, можно понять и из её названия.
Но какова же польза?
В реальности
Функция № 2: std::bless()
Как известно, в С++ предусмотрены указатели. Указатель — это, по сути, переменная, в которую записывают адрес другого объекта в памяти. Над указателем вы можете выполнять арифметические действия, но лишь в том случае, если он элемент массива. Почему? Потому что невозможно вычитать либо прибавлять что-либо к произвольному указателю — в этом отсутствует смысл, ведь расположение объектов в памяти нам неизвестно.
Но данное действие не будет явной ошибкой. Оно просто становится причиной неопределенного поведения (то есть результата, зависящего от состояния памяти, компилятора, лунной фазы, вашего настроения и прочих случайностей).
Но вообще, проблема сводится не к недостаточно прозорливым разработчикам, которые почему-то складывают указатели (это же ведь не запрещено), а непосредственно к языку программирования С++. Именно поэтому Ричард Смит, специалист из компании Google, предложил добавить в стандарт следующую функцию:
std::bless(void* ptr, std::size_t n)
Для чего это было сделано? Да чтобы в случае надобности автоматически выделить массив памяти, разрешив тем самым арифметический вопрос для указателей. При этом, разумеется, имя bless никоим образом не сообщает об этих нововведениях.
Следовательно, решили придумать иное название для функции. Тут уже за дело взялся комитет развития языка C++, а в качестве кандидатов они выдвинули версии
Эти имена вполне логичны, ведь функция выполняет как раз то, что в них сказано. Однако согласитесь, если не знать предысторию, совершенно непонятно, а зачем вообще надо создавать какие-нибудь объекты.
Функция № 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/.