Венге́рская нота́ция в программировании — соглашение об именовании переменных, констант и прочих идентификаторов в коде программ. Своё название венгерская нотация получила благодаря программисту компании Microsoft венгерского происхождения Чарльзу Симони, Шимоньи Карой), предложившему её ещё во времена разработки первых версий MS-DOS. Эта система стала внутренним стандартом «Майкрософт»[1].
История
правитьИзобретение нотации приписывают программисту венгерского происхождения Чарльзу Шимоньи (венг. Simonyi Károly, Ши́моньи Ка́рой), который в 1972—1981 годах работал в Xerox PARC года, а позднее — в Microsoft, где руководил, в частности, разработкой Microsoft Word. Венгерской нотацию стали называть из-за страны происхождения Шимоньи, а также потому, что код «выглядел, как будто он написан на нечитаемом иностранном языке», со слов Энди Хетцфельда.[2] Венгерский язык и в самом деле непривычен для англоговорящих, потому что относится к финно-угорским языкам, далёким от привычных индоевропейских.
Правила
правитьВ венгерской нотации имена идентификаторов предваряются заранее оговоренными префиксами, состоящими из одного или нескольких символов. При этом, как правило, ни само наличие префиксов, ни их написание не являются требованием языков программирования, и у каждого программиста (или коллектива программистов) они могут быть своими.
Применяемая система префиксов зависит от многих факторов:
- языка программирования (чем более «либеральный» синтаксис, тем больше контроля требуется со стороны программиста, а значит, тем более развита система префиксов. К тому же использование в каждом из языков программирования своей терминологии также вносит особенности в выбор префиксов);
- стиля программирования (объектно-ориентированный код может вообще не требовать префиксов, в то время как в «монолитном» для разборчивости они зачастую нужны);
- предметной области (например, префиксы могут применяться для записи единиц измерения);
- доступных средств автоматизации (генератор документации, навигация по коду, предиктивный ввод текста, автоматизированный рефакторинг и т. д.).
Префиксы, задающие тип
правитьПрефикс | Сокращение от | Смысл | Пример |
---|---|---|---|
s | string | строка | sClientName
|
sz | zero-terminated string | строка, ограниченная нулевым символом | szClientName
|
n, i | int | целочисленная переменная | nSize, iSize
|
f | float | число с плавающей запятой | fValue
|
l | long | длинное целое | lAmount
|
b | boolean | булева переменная | bIsEmpty
|
a | array | массив | aDimensions
|
t, dt | time, datetime | время, дата и время | tDelivery , dtDelivery
|
p | pointer | указатель | pBox
|
lp | long pointer | двойной (дальний) указатель | lpBox
|
r | reference | ссылка | rBoxes
|
h | handle | дескриптор | hWindow
|
m_ | member | переменная-член | m_sAddress
|
g_ | global | глобальная переменная | g_nSpeed
|
C | class | класс | CString
|
T | type | тип | TObject
|
I | interface | интерфейс | IDispatch
|
v | void | отсутствие типа | vReserved
|
Как видно в приведённом примере, префикс может быть и составным. Например, для именования строковой переменной-члена класса использована комбинация префиксов «m_» и «s» (m_sAddress
).
Семантические префиксы
правитьВенгерская нотация для приложений[источник не указан 3037 дней]:
Префикс | Сокращение от | Смысл | Пример |
---|---|---|---|
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) {}
|
I | interface | Интерфейс (в имени типа) | interface IFactory {}
|
За и против
правитьВ разделе не хватает ссылок на источники (см. рекомендации по поиску). |
Среди программистов есть как сторонники, так и противники использования венгерской нотации. Противники утверждают, что она громоздка и лишь ухудшает понимание кода. Сторонники утверждают, что слишком многие неверно понимают основную идею и неправильно пользуются нотацией.
Преимущества
править- Если встроенного механизма типизации не хватает, венгерская нотация позволяет записывать подтип[англ.] переменной — например,
int cPrice
может означать, что переменная имеет не просто целый тип, а валютный (currency). Именно такое применение префиксов было предложено Симони[3]. Это может пригодиться:- В низкоуровневом программировании (когда набор доступных типов настолько узок, что, например, целый тип не отличается от булевого).
- В языках с динамической типизацией, например PHP, где одна и та же переменная может хранить значения любого типа.
- В инженерных расчётах (для записи единиц измерения). Это позволяет избавиться от немалого количества ошибок простым подсчётом размерностей.
- В других местах, где переменные одного и того же типа предназначены для хранения разнородных данных — например, в коде защиты от компьютерных взломщиков префикс может указывать на «необработанные» и «экранированные» данные (SQL-инъекция, XSS).
- Венгерская нотация удобна для написания больших программ в неполнофункциональных (по современным меркам) редакторах без автоматизированной навигации по тексту. Скорее всего, именно поэтому она стала стандартным стилем кода в WinAPI.
- Венгерскую нотацию можно рассматривать как стандартную систему сокращений. Например, поле ввода для поиска и кнопка «Поиск» могут именоваться как
txtSearch
иbtnSearch
; количество людей можно записать какmanCount
илиnMen
. Такая практика позволяет делать названия переменных короткими и в то же время осмысленными. - Решает конфликты идентификаторов:
Point::Point(int aX, int aY) : x(aX), y(aY) {}
.
Этот стиль выбора имён называется «венгерской» записью по названию родины руководителя отдела программирования Microsoft Чарльза Симони, который его изобрёл. (А не потому, что его использование придаёт программам такой вид, будто они написаны на венгерском языке[4])
Недостатки
править- Некоторые программисты считают, что использование префиксов делает имена переменных менее понятными и, таким образом, ухудшает читаемость кода.[5]
- Если неизвестно имя переменной без префиксов, подчас трудно восстановить её префиксы.
- Система автодокументации, если она не понимает системы префиксов, отсортирует алфавитный список по префиксу, что может отрицательно сказаться на качестве документации. Впрочем, имена функций обычно префиксами не снабжают.
- Запись нескольких префиксов из-за частого использования заглавных букв и знаков подчёркивания может стать «пляской на кнопке ⇧ Shift».
- Средства навигации, которые включены в современные редакторы кода, и так позволяют видеть тип любой переменной и быстро переходить к точке, где она определена — то есть, использование префиксов может быть избыточным.
- При изменении типа потребуется изменять имя переменной (не все редакторы кода могут делать это автоматически).[5]
- Существуют и другие средства задания типа переменной в её имени: например, слова is, has и т. д. для булевского типа (
IsLoggedIn
), count для счётчика (RefCount
), множественное число для массива (UserIds
). В языках, в которых заглавные буквы не эквивалентны строчным, регистр букв также может кодировать что-либо.
Известный противник венгерской нотации — Линус Торвальдс: «Вписывание типа переменной в её имя (так называемая венгерская нотация) ущербно — компилятор и так знает типы и может проверить их, и это запутывает программиста»[6].
См. также
правитьПримечания
править- ↑ Charles Simonyi. Hungarian Notation .
- ↑ Anything You Can Do, I Can Do Meta MIT Technology Review
- ↑ Джоэл Спольски. Making Wrong Code Look Wrong
- ↑ Венгерский язык, хоть и имеет латинский алфавит, считается крайне неудобочитаемым для неосведомлённых.
- ↑ 1 2 Необходимо задать параметр
url=
в шаблоне {{cite web}}. [ Inside C++ — Венгерская нотация] . Дата обращения: 12 ноября 2008. Архивировано 30 октября 2008 года. - ↑ «Linux kernel coding style» Архивировано 23 сентября 2005 года.. Документация по ядру Linux (на английском).