Как сейчас поживает венгерская нотация?

148
08 июля 2019, 08:40

Помнится в начале существования Windows компания Микрософт сильно продвигала так называемую венгерскую нотацию. Также многие программистские фирмы педалировали это средство как панацею от всех проблем разработки.

Вопрос - что у нас сейчас с венгерской нотацией? Умерла, не умерла? Как к ней относится сама компания Микрософт? Есть какие-нибудь официальные/неофициальные рекомендации?

UPD1:

Тут коллеги все сводят к тому, что венгерская нотация позволяет в имени переменной иметь тип переменной. Но это не совсем так. Если кому-то надо иметь в имени переменной тип этой переменной, то это решается очень просто. Надо просто в имя переменной включать тип переменной. Не просто "a", а "a_int". Венгерская же нотация претендовала на некое описание функционала вызова. Особенно это касается функций WinAPI и MFC. Вот и получалось GetDataFromPromDromStrem и это только самое приличное. Забор из строчных и прописных букв, который якобы облегчал сопровождение программы. Прошло не так много лет и кажется, что даже микрософт не вспоминает об этой поделке.

UPD2:

Тут я озадачился и пошел в русскую википедию. Нет, там про это ничего не слышали.

Тут уже я озадачился и пошел в русскую википедию. Да, и там про это что-то слышали.

Префиксы, задающие смысл
Венгерская нотация для приложений:

Префикс Сокращение от   Смысл                    Пример   
i       index           Индекс                   int ix; Array[ix] = 10;     
d       delta           Разница между значениями int a, b; ... dba = b - a;  
n       number          Количество               size_t nFound = 0;  
a       argument        Аргумент                 SomeClass::SomeClass(int aX) : x(aX) {}

Вот тут слишком умный форматер на сайте SO удаляет пробелы в строке, поэтому таблицу перенести не удается. Но можно поглядеть в русской википедии.

Вобщем никто не скажет, что delta или number это тип переменной. Это как раз не тип, а функционал переменной. Далее этот подход был перенесен на вызовы в WinAPI и там в каждом имени вызова пытались всунуть функционал этого вызова.

Answer 1

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

Так вот, венгерская нотация это замечательная вещь. Она действительно улучшает сопровождаемость программы. Понимание того, что представляет из себя переменная, очень помогает разобраться в программе. Но если для C ее безусловно можно советовать, в случае C++ дело обстоит сложнее. При активном применении библиотек классов и шаблонов (и стандартной библиотеки в частности) венгерской нотации начинает не хватать. Как нужно называть shared_ptr<unordered_map<unsigned, string>>? Загадка.

Даже с обычными строками нотация чрезмерно разрастается. Обычная строка это sz. Широкая пусть wsz. Как быть с указателями на строки? Ну давайте назовем их psz и pwsz. А как быть с массивами символов без завершающего нуля? Чувствуется, что ситуация уже начинает выходить из под контроля. Потом вдруг оказывается, что нам еще нужны char32_t строки и все окончательно валится под откос.

В результате оказывается, что в программе на C++ тривиальных переменных не так уж много, и они большей частью не стоят того, чтобы именовать их с префиксами. Лично я использую временами эту нотацию в простейших случаях вроде nItems, hFile, или szMessage, но в целом эта нотация для C++ малополезна.

UPDATE

Услышал я удивительную вещь, что венгерская нотация это, оказывается, не префикс типа, а просто осмысленное именование в кэмел формате. То есть названия вроде OpenClipboard или CreateNamedPipe это как раз венгерская нотация и есть. Но начинающие программисты не понимают глубокую идею и сводят все к префиксу типа.

Тут я озадачился и пошел в русскую википедию. Нет, там про это ничего не слышали. Наверное, начинающие программисты статью писали. Пошел в английскую - то же самое. Открыл гугл, набрал "hungarian notation" - везде про типы. Microsoft, как выяснилось, тоже все неправильно пишет. Беда...

UPDATE 2

На тему того, что Правильная Венгерская Нотация относится к назначению переменной, а не к ее типу. Да, первоначально была попытка использовать ее именно в такой форме, но выглядело это откровенно жалко. Слишком много вещей обозначаются переменными, и трудно выделить часто используемые. Ну разве что переменные цикла, да и то они i, j, k еще со времен Фортрана 66.

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

Да, разность координат естественно назвать dx или dy, но для этого не надо изобретать специальный префикс. Это естественное имя, как и переменная цикла i. То же самое для rowFirst и colName - похоже на венгерскую, но формализовать это явно нет смысла.

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

loaded_scripts loadedGlobalScripts;
loaded_scripts loadedFileScripts;
loaded_scripts loadedUserScripts;

это так называемая Camel нотация. Но вот если бы таких переменных было бы много разных, и они много где использовались, то я бы давал имена в форме scriptCurrent, scriptLastLoaded, scriptSpawned и т.п. Похоже на венгерскую нотацию, но формализовать это невозможно, потому что список таких префиксов просто невозможно было бы выучить.

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

P.S. Насчет статьи из комментариев. Джоэль много чего пишет, но не надо относиться к нему как светочу абсолютной истины. Сомнительных утверждений у него хватает, и эта статья хороший пример.

READ ALSO
работа с enum class

работа с enum class

у меня есть два enum class

149
Удаление на промежутке в multiset

Удаление на промежутке в multiset

Как в multiset удалять элементы на промежутке [first, last] (рамки промежутка вводятся с консоли)? first и last - условные позиции элементов, если бы они имели...

161
Аллокаторы памяти

Аллокаторы памяти

Не так давно услышал о том, что существует способ управлять памятью самому, а не использовать, например, new и deleteМожет кто-нибудь сможет осветить...

138