0 added
0 removed
Original
2026-01-01
Modified
2026-03-10
1
<p>Правильность названия функций очень важна, особенно когда вы разрабатываете пользовательский API. Имя может понятно описывать действие функции, а может быть попросту бесполезным. И с такой ситуацией вы столкнетесь даже при использовании стандартных библиотек. Давайте посмотрим парочку примеров на C++20.</p>
1
<p>Правильность названия функций очень важна, особенно когда вы разрабатываете пользовательский API. Имя может понятно описывать действие функции, а может быть попросту бесполезным. И с такой ситуацией вы столкнетесь даже при использовании стандартных библиотек. Давайте посмотрим парочку примеров на C++20.</p>
2
<h2>Функция № 1: std::log2p1()</h2>
2
<h2>Функция № 1: std::log2p1()</h2>
3
<p>Первая наша функция - std::log2p1(). Код выглядит следующим образом:</p>
3
<p>Первая наша функция - std::log2p1(). Код выглядит следующим образом:</p>
4
<p>В нашем случае функция попросту возвращает двоичный логарифм числа + 1, что, в принципе, можно понять и из её названия.</p>
4
<p>В нашем случае функция попросту возвращает двоичный логарифм числа + 1, что, в принципе, можно понять и из её названия.</p>
5
<h4>Но какова же польза?</h4>
5
<h4>Но какова же польза?</h4>
6
<p>В реальности std::log2p1(x) возвращает число битов, нужных для хранения x. Да, это нужная функция, однако проблема заключается в том, что<strong>ее название не отражает в действительности сути выполняемой операции</strong>.</p>
6
<p>В реальности std::log2p1(x) возвращает число битов, нужных для хранения x. Да, это нужная функция, однако проблема заключается в том, что<strong>ее название не отражает в действительности сути выполняемой операции</strong>.</p>
7
<h2>Функция № 2: std::bless()</h2>
7
<h2>Функция № 2: std::bless()</h2>
8
<p>Как известно, в С++ предусмотрены<strong>указатели</strong>. Указатель - это, по сути, переменная, в которую записывают адрес другого объекта в памяти. Над указателем вы можете выполнять арифметические действия, но лишь в том случае, если он элемент массива. Почему? Потому что невозможно вычитать либо прибавлять что-либо к произвольному указателю - в этом отсутствует смысл, ведь расположение объектов в памяти нам неизвестно.</p>
8
<p>Как известно, в С++ предусмотрены<strong>указатели</strong>. Указатель - это, по сути, переменная, в которую записывают адрес другого объекта в памяти. Над указателем вы можете выполнять арифметические действия, но лишь в том случае, если он элемент массива. Почему? Потому что невозможно вычитать либо прибавлять что-либо к произвольному указателю - в этом отсутствует смысл, ведь расположение объектов в памяти нам неизвестно.</p>
9
<p>Но данное действие не будет явной ошибкой. Оно просто становится причиной неопределенного поведения (то есть результата, зависящего от состояния памяти, компилятора, лунной фазы, вашего настроения и прочих случайностей).</p>
9
<p>Но данное действие не будет явной ошибкой. Оно просто становится причиной неопределенного поведения (то есть результата, зависящего от состояния памяти, компилятора, лунной фазы, вашего настроения и прочих случайностей).</p>
10
<p>Но вообще, проблема сводится не к недостаточно прозорливым разработчикам, которые почему-то складывают указатели (это же ведь не запрещено), а непосредственно к языку программирования С++. Именно поэтому Ричард Смит, специалист из компании Google, предложил добавить в стандарт следующую функцию:</p>
10
<p>Но вообще, проблема сводится не к недостаточно прозорливым разработчикам, которые почему-то складывают указатели (это же ведь не запрещено), а непосредственно к языку программирования С++. Именно поэтому Ричард Смит, специалист из компании Google, предложил добавить в стандарт следующую функцию:</p>
11
std::bless(void* ptr, std::size_t n)<p>Для чего это было сделано? Да чтобы в случае надобности автоматически выделить массив памяти, разрешив тем самым арифметический вопрос для указателей. При этом, разумеется, имя bless никоим образом не сообщает об этих нововведениях.</p>
11
std::bless(void* ptr, std::size_t n)<p>Для чего это было сделано? Да чтобы в случае надобности автоматически выделить массив памяти, разрешив тем самым арифметический вопрос для указателей. При этом, разумеется, имя bless никоим образом не сообщает об этих нововведениях.</p>
12
<p>Следовательно, решили придумать иное название для функции. Тут уже за дело взялся комитет развития языка C++, а в качестве кандидатов они выдвинули версии implicitly_create_objects() и implicitly_create_objects_as_needed(), которые можно перевести, как "неявное создание объектов" и "неявное создание объектов при необходимости".</p>
12
<p>Следовательно, решили придумать иное название для функции. Тут уже за дело взялся комитет развития языка C++, а в качестве кандидатов они выдвинули версии implicitly_create_objects() и implicitly_create_objects_as_needed(), которые можно перевести, как "неявное создание объектов" и "неявное создание объектов при необходимости".</p>
13
<p>Эти имена вполне логичны, ведь функция выполняет как раз то, что в них сказано. Однако согласитесь, если не знать предысторию, совершенно непонятно, а зачем вообще надо создавать какие-нибудь объекты.</p>
13
<p>Эти имена вполне логичны, ведь функция выполняет как раз то, что в них сказано. Однако согласитесь, если не знать предысторию, совершенно непонятно, а зачем вообще надо создавать какие-нибудь объекты.</p>
14
<h2>Функция № 3: std::popcount()</h2>
14
<h2>Функция № 3: std::popcount()</h2>
15
<p>Очередная стандартная функция C++ 20. Глядя на имя, попробуйте угадать, что конкретно она делает. Что-то считает? А может, это как-то связано со стековыми операциями push и pop?</p>
15
<p>Очередная стандартная функция C++ 20. Глядя на имя, попробуйте угадать, что конкретно она делает. Что-то считает? А может, это как-то связано со стековыми операциями push и pop?</p>
16
<p>В большинстве случаев вы даже не догадаетесь, если не знаете о низкоуровневой инструкции с аналогичным названием. Функция popcount (сокращение от "population count") считает число установленных в машинном слове битов.</p>
16
<p>В большинстве случаев вы даже не догадаетесь, если не знаете о низкоуровневой инструкции с аналогичным названием. Функция popcount (сокращение от "population count") считает число установленных в машинном слове битов.</p>
17
<p>Вроде бы, это неплохое имя, но только если все разработчики знают имена битовых ассемблерных операций. Но будет ли это очевидно новичку, который не знает тонкостей?</p>
17
<p>Вроде бы, это неплохое имя, но только если все разработчики знают имена битовых ассемблерных операций. Но будет ли это очевидно новичку, который не знает тонкостей?</p>
18
<h2>Как же называть функции?</h2>
18
<h2>Как же называть функции?</h2>
19
<p>Собственно говоря, ни одно из имен выше нельзя назвать откровенно плохим: названия вроде как описывают действия функций. Однако для вас, как для пользователей, такие имена, по сути, бесполезны, ведь они содержат не ту информацию, которая действительно необходима.</p>
19
<p>Собственно говоря, ни одно из имен выше нельзя назвать откровенно плохим: названия вроде как описывают действия функций. Однако для вас, как для пользователей, такие имена, по сути, бесполезны, ведь они содержат не ту информацию, которая действительно необходима.</p>
20
<p>Да, имена, описывающие реализацию функций, будут понятны для программистов, но будут зачастую бессмысленны для пользователей. При этом такими пользователями могут являться<strong>другие</strong><strong>разработчики</strong>, которые пожелают подключить к своему проекту кем-либо созданную библиотеку. А вот в этом случае важно то, что конкретно делают функции, а не то, каким образом они реализованы.</p>
20
<p>Да, имена, описывающие реализацию функций, будут понятны для программистов, но будут зачастую бессмысленны для пользователей. При этом такими пользователями могут являться<strong>другие</strong><strong>разработчики</strong>, которые пожелают подключить к своему проекту кем-либо созданную библиотеку. А вот в этом случае важно то, что конкретно делают функции, а не то, каким образом они реализованы.</p>
21
<p>Однако проблема имен касается не только стандартных библиотек. Именно поэтому, если в проекте предполагается, что кодом кто-то будет пользоваться далее, выбирайте говорящие названия и смотрите на эти функции с точки зрения пользователей.</p>
21
<p>Однако проблема имен касается не только стандартных библиотек. Именно поэтому, если в проекте предполагается, что кодом кто-то будет пользоваться далее, выбирайте говорящие названия и смотрите на эти функции с точки зрения пользователей.</p>
22
<p><em>По материалам статьи "Naming Things: Implementer vs. User Names" - https://foonathan.net/2019/11/implementer-vs-user-names/.</em></p>
22
<p><em>По материалам статьи "Naming Things: Implementer vs. User Names" - https://foonathan.net/2019/11/implementer-vs-user-names/.</em></p>
23
23