LINUX.ORG.RU

[C++][stackoverflow] Как вы отноститесь к использованию префиксов в названии переменных?

 ,


0

2

В этом треде я прочитал сообщение, которое мне показалось настолько простым и изящным, что я решил последовать опыту его автора.

Полная цитата:
====== НАЧАЛО =====
I think (System) Hungarian notation is responsible for most of the «bad rap» that prefixes get.

This notaton is largely pointless in strongly typed languages e.g. «lpsz» to tell you that your string is a long pointer to a nul terminated string, when: segmented architecture is ancient history, C++ strings are pointers to nul-terminated char arrays, and it's not really all that difficult to know that «Name» is a string!

However, I do use prefixes to specify the usage of a variable (essentially «Apps Hungarian», although I prefer to avoid the term Hungarian due to it having a bad and unfair association with System Hungarian), and this is a very handy timesaving and bug-reducing approach.

I use:

  • m for members
  • c for constants/readonlys
  • p for pointer (and pp for pointer to pointer)
  • v for volatile
  • s for static
  • i for indexes and iterators
  • e for events

Where I wish to make the type clear, I use standard suffixes (e.g. List, ComboBox, etc).

This makes the programmer aware of the usage of the variable whenever they see/use it. The most important case is «p» for pointer (because the usage changes from var. to var-> and you have to be much more careful with pointers - checking for NULL etc), but all the others are very handy.

For example, you can use the same variable name in multiple ways in a single function: (here a C++ example, but it applies equally to many languages)

MyClass::MyClass(int numItems)
{
    mNumItems = numItems;
    for (int iItem = 0; iItem < mNumItems; iItem++)
    {
        Item *pItem = new Item();
        itemList[iItem] = pItem;
    }
}

You can see here:

  • No confusion between member and parameter
  • No confusion between index/iterator and items
  • Use of a set of clearly related variables (item list, pointer, and index)

Another great point of «iName» iterators is that I never index an array with the wrong index, and if I copy a loop inside another loop I don't have to refactor one of the loop index variables.

Compare this unrealistically simple example:

for (int i = 0; i < 100; i++)
    for (int j = 0; j < 5; j++)
        list[i].score += other[j].score;
(which is hard to read and often leads to use of «i» where «j» was intended)

with:

for (int iCompany = 0; iCompany < 100; iCompany++)
    for (int iUser = 0; iUser < 5; iUser++)
       companyList[iCompany].score += userList[iUser].score;
(which is much more readable, and removes all confusion over indexing. With auto-complete in modern IDEs, this is also quick and easy to type)

The next benefit is that code snippets do not require any context to be understood. I can copy two lines of code into an email or a document, and anyone reading that snippet can tell the difference between all the members, constants, pointers, indexes, etc. I don't have to add «oh, and be careful because 'data' is a pointer to a pointer», because it's called 'ppData'.

And for the same reason, I can read a line of code, and I don't have to move my eyes out of the line of code in order to understand it. I don't have to search through the code to find if 'data' is a local, parameter, member, or constant. So programmers can read and understand the code significantly faster, because they don't waste time searching up and down.

The 'm' prefix also avoids the (IMHO) hideous and wordy «this->» notation, and the inconsistency that it guarantees (even if you are careful you'll usually end up with a mixture of 'this->data' and 'data' in the same class, because nothing enforces a consistent spelling of the name).

The last major benefit is with Intellisense and auto-completion. Try using Intellisense on a Windows Form to find an event - you have to scroll through hundreds of mysterious base class methods that you will never need to call to find the events. But if every event had an «e» prefix, they would automatically be listed in a group under «e». Thus, prefixing works to group the members, consts, events, etc in the intellisense list, making it much quicker and easier to find the names you want. (Usually, a method might have around 20-50 values (locals, params, members, consts, events) that are accessible in its scope. But after typing the prefix (I want to use an index now, so I type 'i...'), I am presented with only 2-5 auto-complete options. The 'extra typing' people attribute to prefixes and meaningful names drastically reduces the search space and measurably accelerates development speed)

I'm a lazy programmer, and the above convention saves me a lot of work. I can code faster and I make far fewer mistakes because I know how every variable should be used.
==== КОНЕЦ ЦИТАТЫ =====

Какие ещё плюсы и минусы этого подхода? Пока я вижу только плюсы. Хотелось бы конструктивного обсуждения.

Я использую «m_» для private членов класса и «g_» для глобальных, если в них возникает потребность. Потому как доступ будет через геттеры и сеттеры, а глобальные - такая редкая диковина, что если появляется - следует выделить.

На мой взгляд, все префиксы имеют право существовать лишь в пределах класса. Так, чтобы при использовании самого класса всё было гладко и читалось как предложение. Не pRope->sShoot(mFoot), а rope->shoot(foot).

stolz
()
Ответ на: комментарий от anonymous

Ужос, разработчикам Qt надо срочно раскаяться перед вами за допущенный непрофессионализм.

вообще там местами дикий салат и быдлокод, так что - да, надо

shty ★★★★★
()
Ответ на: комментарий от Chaser_Andrey

а трёхмерное пространство как описывать?

aptyp ★★★★
()

Венгерская нотация хороша, но в меру (как впрочем и многие другие вещи).
p, я считаю, надо использовать всегда и обязательно... остальное при необходимости.
Ещё в названиях интерфейсов префикс I лишним не будет.
В циклах лучше называть переменные тем, что они означают. Тип coordPlane[x][y] ...

invy ★★★★★
()
Ответ на: комментарий от Reset

от макроса вообще ничего не спасёт, макрос - это как Чак Норрис, но макросы обычно пишут заглавными буквами, не?

PS сам пишу подчёркивание в конце, так что это я не в качестве возражения, просто занудствую

shty ★★★★★
()

Использую m_ для полей класса. Нравится.

cattail
()

использую m_ для private members

najar
()

Как и многие идиотские идеи, венгерская нотация (а предложенное - именно венгерская нотация) бессмертна. Желаю автору цитаты быстрой смерти, а автору хедпоста - прочищения мозгов. Хотя... если приведенного в цитате примера для прочищения мозга не хватило, то прогноз неутешительный.

tailgunner ★★★★★
()

пишу приватные поля с m_ ибо использую геттеры в стиле value() (геттеры в стиле Java - getValue почему-то жутко не нравятся)

Kosyak ★★★★
()

> I think (System) Hungarian notation is responsible for most of the «bad rap» that prefixes get.

However, I do use prefixes to specify the usage of a variable

I use:

Where I wish to make the type clear, I use standard suffixes

Указание типа переменной с помощью префикса/суффикса - это и есть та самая «венгерская нотация».

«usage of a variable» должен быть выражен кодом, а значение - именем.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

Спольски был лично знаком с автором венгерской нотации. И показал как её правильно (в смысле, как изначально задумывалось) использовать.

Небесспорно, но не имеет никакого отношения к тому бреду, которым наполнены 2 страницы комментариев.

anonymous
()
Ответ на: комментарий от anonymous

> Спольски был лично знаком с автором венгерской нотации.

Лень лезть к нему на сайт, но по памяти - не был же.

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

Цитата в ОПе - наглядное доказательство расхожести идеи.

Так что никакого «правильного» или «изначально задуманного» способа использования у неё нет. Как хочешь - так и используй. Или не используй.

Ну и приведенный Спольски пример с санизированными строками вс. не санизированными не сильно отличается по смыслу от префикса к указателю на нуль-терминированную строку вс. его отсутствие для указателя на произвольные данные.

LamerOk ★★★★★
()
Ответ на: комментарий от tailgunner

венгерская нотация - хорошая идея, но микрософт с ихним m_lpszName её исковеркало до безобразия, когда префикс становился длинее «корня»...
потом они(микрософт) сами же стали её пытаться изживать в C#...

invy ★★★★★
()
Ответ на: комментарий от invy

> венгерская нотация - хорошая идея, но микрософт с ихним m_lpszName её исковеркало до безобразия

Умеют же люди рассуждать взаимоисключающими параграфами.

tailgunner ★★★★★
()

Не читал, но не согласен.

pevzi ★★★★★
()

> The last major benefit is with Intellisense and auto-completion. Try using Intellisense on a Windows Form to find an event

Вот так всегда, нет бы доделать инструмент, вычистить баги, сделать его юзабельным - так виндузятники начинают писать такой код, который красиво парсится и отображается IntellSense

lmao

anonymous
()

Прочитал весь пост - да, автор явная жертва автокомплита.

Вот такие люди, как автор, занимаются auto-complete-driven разработкой.

Неужели есть люди, для которых скорость разработки упирается в скорость набора текста?

anonymous
()
Ответ на: комментарий от Chaser_Andrey

> Безусловно. Но набирать один раз, а читать - много. Что легче понять - i, j, k или iPeople, iGroup, iPhone? Хотя в простейших случаях это излишне, конечно же.

легче не добавлять шум в код в виде ненужных префиксов

anonymous
()

Не понимаю я, чем volatile отличается от int? И то и другое - атрибуты переменной, почему для volatile нотацию надо использовать, а для int - не надо?

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

> Не понимаю я, чем volatile отличается от int?

первое - модификатор (modifier) типа, второе - спецификатор (specifier) типа.

anonymous
()
Ответ на: комментарий от LamerOk

> > Where I wish to make the type clear, I use standard suffixes

Указание типа переменной с помощью префикса/суффикса - это и есть та самая «венгерская нотация».

«usage of a variable» должен быть выражен кодом, а значение - именем.

Молодец, ровно в яблочко.

anonymous
()

Не нужно однозначно.
Ссам использую только m_ для мемберов, чтобы писать геттеры в стиле qt ( point.x(), а не point.getX() ) и быстро отличать в теле метода параметры от полей класса.
Остальное д.б. выражено именами и кодом, в исключительно тяжелых случаях комментариями.

gaga
()
Ответ на: комментарий от Reset

>так как имена с подчеркиванием вначале зарезервированы для стандартной библиотеки и есть шанс нарваться на конфликт

Если внимательно почитать т.н. Стандарт, то можно обнаружить что зарезервированы __двойные подчеркивания и подчеркивания после которых идет _Заглавная буква. Простые _подчеркивания не зарезервированы.

Absurd ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.