Почему мне не следует использовать «Венгерскую нотацию»?


122

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

См. Также: Используют ли люди венгерские соглашения об именах в реальном мире?


Ответы:


174

Большинство людей неправильно используют венгерскую нотацию и получают неверные результаты.

Прочтите эту отличную статью Джоэла Спольски: Как сделать неправильный код неправильным .

Короче говоря, венгерская нотация, в которой к именам переменных добавляются их type (строка) (Венгерская система), плохая, потому что бесполезна.

Венгерская нотация, как она была задумана ее автором, где вы префикс имени переменной с ее kind(используя пример Джоэла: безопасная строка или небезопасная строка), так называемые приложения Hungarian имеют свое применение и все еще ценны.


5
Хорошая ссылка, хорошее резюме того, что стоит за ссылкой, и никакого фанатизма. Превосходно.
Dustman

12
Обратите внимание, что пример Джоэлса написан на VBScript, языке, который давно не имеет пользовательских классов. В объектно-ориентированном языке вы просто создаете тип HtmlEncodedString, а метод Write принимает только это. «Венгерские приложения» полезны только для языков без определяемых пользователем типов.
JacquesB,

4
Microsoft известна своим прошлым неправильным использованием венгерской нотации. Добавление информации о типе к идентификаторам не только бесполезно, но и может навредить. Во-первых, читаемость хуже. Во-вторых, в языках, поддерживающих полиморфизм или утиный ввод, передается неверная информация.
Wilhelmtell

9
Мне все еще нравится использовать венгерскую нотацию, если я занимаюсь прямой разработкой на C со старой IDE ... таким образом я знаю, что нет проблем с приведением типов.
Beep beep

3
@Krumia: Обычно этого можно избежать, задав в первую очередь описательные имена переменных. Но если вы хотите быть уверенным, было бы намного безопаснее создать отдельные типы (например, структуры) для длины, веса и т. Д. И использовать перегрузку операторов, чтобы гарантировать, что возможны только допустимые операции.
JacquesB

277

vИспользование прилегающей венгерской нотации v затрудняет чтение ncode.


101
Хорошая аналогия, хотя и немного несправедливая. Сравните: vИспользование adjHungarian nNotation v делает nReading nCode adjDifficult.
Крис Ноэ,

27
В этом предложении «Использование» и «Чтение» означают герундий. Но я понимаю, о чем вы говорили ...
шимпанзе

28
@chimp: это делает вещи еще более очевидными. Теперь, когда вы обнаружили ошибку в типе, собираетесь ли вы переименовать все ссылки или оставить их как есть, предоставляя дезинформацию? вы проиграете в любом случае. но, конечно, это НЕПРАВИЛЬНЫЙ способ применения венгерской нотации.
Вильгельмтелл

1
@Chris Noe: для определенных стилей чтения (проанализируйте префикс и суффикс, взглянув на середину), ваш пример только ухудшает ситуацию. Я вижу «vUsing» и слышу «voosing» в голове.
Боб Кросс

3
@Jon: если у вас есть имя переменной, которое не полностью раскрывает то, что она представляет, тогда, безусловно, следует сосредоточиться на том, чтобы переименовать ее в нечто более информативное (и венгерская нотация не является улучшением, в самом, очень в лучшем случае это устранение симптома, а не решение проблемы).
hlovdal

104

Джоэл ошибается, и вот почему.

Та "прикладная" информация, о которой он говорит, должна быть закодирована в системе типов . Вы не должны зависеть от переворачивания имен переменных, чтобы убедиться, что вы не передаете небезопасные данные функциям, требующим безопасных данных. Вы должны сделать это типовой ошибкой, чтобы это было невозможно . Любые небезопасные данные должны иметь тип, помеченный как небезопасные, чтобы их просто нельзя было передать безопасной функции. Чтобы преобразовать из небезопасного в безопасный, потребуется обработка с какой-то функцией очистки.

Многие вещи, о которых Джоэл говорит как о «видах», не являются видами; они, по сути, типы.

Однако большинству языков не хватает системы типов, достаточно выразительной, чтобы обеспечить такого рода различия. Например, если бы в C был своего рода «строгий typedef» (где имя typedef имело все операции базового типа, но не могло быть преобразовано в него), то многие из этих проблем исчезли бы. Например, если бы вы могли сказать, strong typedef std::string unsafe_string;чтобы ввести новый типunsafe_string который не может быть преобразован в std :: string (и, следовательно, может участвовать в разрешении перегрузки и т.д. и т.д.), тогда нам не понадобятся глупые префиксы.

Итак, центральное утверждение, что венгерский предназначен для вещей, которые не являются типами, неверно. Он используется для информации о типе. Разумеется, более обширная информация о типах, чем традиционная информация о типах C; это информация о типе, которая кодирует какие-то семантические детали, чтобы указать назначение объектов. Но это все еще информация о типе, и правильным решением всегда было закодировать ее в систему типов. Кодирование его в систему типов - безусловно, лучший способ получить надлежащую проверку и соблюдение правил. Имена переменных просто не режут горчицу.

Другими словами, цель не должна состоять в том, чтобы «заставить неправильный код выглядеть неправильно для разработчика». Это должно быть «заставить неправильный код выглядеть неправильно для компилятора ».


30
Намерение переменной должно быть закодировано в типе переменной, а не оставлено на усмотрение чего-то столь хрупкого, как чертова схема именования.
DrPizza

3
Я бы также хотел сделать его задачей компилятора / интерпретатора, но это повлечет за собой огромные накладные расходы для динамических языков (Python, Ruby, PHP или Javascript).
слишком много php

22
«Чего, однако, не хватает большинству языков, так это системы типов, достаточно выразительной, чтобы проводить такие различия». И в этом проблема. AppsHungarian - это прагматичный метод выявления проблем при использовании этих языков очевидными способами для программистов, просматривающих код, а не исследующих отчеты об ошибках.
Нил Тродден,

6
@DrPizza: Я считаю, что вы упустили один из очень важных моментов, который делает Джоэл, защищая Apps Hungarian: эта нотация - просто очень прагматичный компромисс . Сделать компилятор способным видеть «неправильный код» - великая цель, но всегда ли это стоит своих затрат?
Ярик

4
@DrPizza: Joel is wrongи What most languages lack, however, is a type system that's expressive enough to enforce these kind of distinctions.так, поскольку большинство языков этого не хватает выразительности достаточно для обеспечения соблюдения такого рода различий, Джоэл является правильным. Правильно?
sampathsris

46

Я думаю, что это сильно загромождает исходный код.

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


Вот это да. 90 повторений за 15 минут. Хороший звонок.
Dustman

2
Если использовать его для набора текста, то да, бесполезно. Полезно поделиться другой информацией.
Лу Франко

12
@Lou, именно так - лично я храню историю изменений в своих именах переменных: string firstName_wasName_wasNameID_wasSweetCupinCakes
Shog9

@nsanders: попробуйте использовать компилятор, чтобы проверить, использовали ли вы одни и те же единицы измерения, когда оба типа переменных являются целыми числами.
Игорь Левицки 05

1
@ Shog9: Я думаю, вы не поняли венгерскую нотацию приложений. Он больше о sFirstName vs unFirstName (безопасный vs небезопасный, не подвергнутый дезинфекции), так что вы узнаете об этом больше. Тем не менее, я думаю, что в статических языках лучше использовать подтип String, чтобы сделать UnsafeString и SafeString и разрешить вывод только SafeString. Соглашение - это нормально, но (чаще) компиляция лучше.
kgadek

28

Венгерская нотация имеет смысл только на языках без определяемых пользователем типов . В современном функциональном или объектно-ориентированном языке вы должны кодировать информацию о «типе» значения в типе данных или классе, а не в имени переменной.

Несколько ответов ссылаются на статью Джоэлса . Обратите внимание, однако, что его пример написан на VBScript, который не поддерживал пользовательские классы (по крайней мере, долгое время). На языке с пользовательскими типами вы бы решили ту же проблему, создав тип HtmlEncodedString и позволив методу Write принимать только это. В языке со статической типизацией компилятор обнаружит любые ошибки кодирования, в языке с динамической типизацией вы получите исключение времени выполнения, но в любом случае вы защищены от записи незакодированных строк. Венгерская нотация просто превращает программиста в человека, проверяющего шрифты, и с такой работой обычно лучше справляется программное обеспечение.

Джоэл различает «венгерские системы» и «венгерские приложения», где «венгерские системы» кодируют встроенные типы, такие как int, float и т. Д., А «приложения венгерские» кодируют «типы», что является метаинформацией более высокого уровня. о переменной за пределами типа машины. В объектно-ориентированном или современном функциональном языке вы можете создавать определяемые пользователем типы, поэтому в этом смысле нет различия между типом и "видом" - оба могут быть представлены системой типов - и "приложениями" Венгерский столь же избыточен, как и "системы" венгерского.

Итак, чтобы ответить на ваш вопрос: Системный венгерский язык будет полезен только в небезопасном, слабо типизированном языке, где, например, присвоение значения float переменной int приведет к сбою системы. Венгерская нотация была специально изобретена в шестидесятых годах для использования в BCPL , довольно низкоуровневом языке, который вообще не выполнял никакой проверки типов. Я не думаю, что какой-либо язык, широко используемый сегодня, имеет эту проблему, но нотация сохранилась как своего рода культовое программирование .

Приложения на венгерском языке будут иметь смысл, если вы работаете с языком без определяемых пользователем типов, например устаревшим VBScript или ранними версиями VB. Возможно также ранние версии Perl и PHP. Опять же, использовать его в современном языке - это чистый культ карго.

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

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


Языки с пользовательскими типами не всегда делают практичным использование типов вместо «видов». Рассмотрим префиксы «c», «d», «ix» из приложения Joel's Apps Hungarian. Используете ли вы для них специальные целочисленные типы на всех современных языках? Я так не думаю. Поскольку в современных языках до сих пор нет встроенных пользовательских целочисленных типов для индексов, счетчиков и различий между двумя числами. Пока мы по-прежнему используем ванильные вставки, Apps Hungarian не будут лишними и полезными.
Eldritch Conundrum

27

Я всегда использую венгерскую нотацию для всех своих проектов. Мне это очень помогает, когда я имею дело с сотнями разных имен идентификаторов.

Например, когда я вызываю функцию, для которой требуется строка, я могу ввести «s» и нажать на контрольное пространство, и моя IDE покажет мне именно имена переменных с префиксом «s».

Еще одно преимущество: когда я префикс u для unsigned и i для подписанных int, я сразу вижу, где я смешиваю подписанный и неподписанный потенциально опасными способами.

Я не могу вспомнить, сколько раз в огромной кодовой базе из 75000 строк ошибки были вызваны (мной и другими) из-за того, что локальные переменные назывались такими же, как существующие переменные-члены этого класса. С тех пор я всегда добавляю к членам префикс 'm_'

Это вопрос вкуса и опыта. Не стучите, пока не попробуете.


1
Кодирование подписи в имена переменных прекрасно, когда часть кода действительно имеет дело со подписью. Использование этого как предлога для обеспечения соблюдения соглашения для всех переменных - это просто доматизм, ИМХО.
Plumenator

Однако у вас есть хорошая точка зрения на переменные-члены. Но в таких языках , как Python , где вы вынуждены квалифицироваться членами самости / этот объект , это спорный вопрос.
Plumenator

Это просто уловка для повышения производительности. Так же, как автозаполнение IDE. В этом нет ничего принципиально злого. Я считаю, что опытным программистам нужно позволить использовать свой собственный стиль. Заставлять кого-либо выбирать определенный стиль - плохо. Сейчас я работаю как один разработчик, но я не стал бы навязывать стиль никому, с кем работал, если бы у них изначально не было единого стиля.
rep_movsd

Итак, вы используете соглашение об именах для фильтрации переменных, а? Я должен согласиться, что это довольно умно . :-) Однако то, как я подключен, точка привязки (или критерий фильтра, если хотите) всегда является для меня семантикой. Редко тип (если он не семантический). Надеюсь, это имело смысл. TL; DR: Я бы по-прежнему придерживался именования переменных в соответствии с тем, что они представляют, а не тем, как они представлены.
Plumenator

1
Я поддержал это тогда, так как я был за венгерский язык. Теперь я сожалею об этом и больше никогда не вернусь к префиксу чего-то в переменной ..
nawfal

22

Вы забываете причину номер один, чтобы включить эту информацию. Это не имеет никакого отношения к тебе, программист. Это связано с тем, что через 2 или 3 года после вашего ухода из компании приходит человек, который должен это прочитать.

Да, IDE быстро определит для вас типы. Однако, когда вы читаете несколько длинных пакетов кода «бизнес-правил», приятно не останавливаться на каждой переменной, чтобы узнать, что это за тип. Когда я вижу такие вещи, как strUserID, intProduct или guiProductID, это значительно упрощает «наращивание» времени.

Я согласен с тем, что MS зашла слишком далеко с некоторыми из своих соглашений об именах - я относю это к стопке «слишком много хорошего».

Соглашения об именах - это хорошо, если вы их придерживаетесь. Я прошел через достаточно старый код, который заставлял меня постоянно возвращаться к определениям для стольких одноименных переменных, что я нажимаю «верблюжья оболочка» (как это было вызвано в предыдущей работе). Прямо сейчас я нахожусь на работе, в которой есть много тысяч строк полностью раскомментированного классического кода ASP с VBScript, и пытаться во всем разобраться - это кошмар.


Как пользователь VIM (без IDE, без выделения, без наведения указателя на тип) я вообще не понимаю этот аргумент. Я естественно понимаю, что переменная с именем name - это строка, а переменная с именем i или count - это int. Действительно ли нужны sName и iCount? Как это действительно помогает? Я бы сказал, что ваш пример идентификатора продукта - особый случай, и, возможно, там все будет хорошо. Но даже тогда быть последовательным и представлять идентификаторы продуктов с помощью целых чисел или строк повсюду было бы гораздо лучшим решением, не так ли? Вся эта история с именами кажется отговоркой.
MrFox

6
Это для последовательности. Да, «имя» по своей сути подразумевает строку. Но что, по вашему мнению, означает «идентификатор пользователя»? GUID? Строка? Integer? Даже что-то вроде acctno может иметь значение 42 или 23X. Документация по большей части кода достаточно скудна. Этот стандарт немного помогает программисту по обслуживанию.
Дэвид

1
@David Я полностью согласен с вашим ответом - зная с первого взгляда назначение переменной, я также предпочитаю использовать префикс, особенно на динамическом языке, таком как JS.
Даниэль Соколовски

10

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

Также существует ситуация, когда во время обслуживания необходимо изменить тип переменной. Пример: если переменная, объявленная как "uint_16 u16foo", должна стать 64-битной беззнаковой, произойдет одно из двух:

  1. Вы просмотрите и измените имя каждой переменной (убедитесь, что не залиты никакие несвязанные переменные с тем же именем), или
  2. Просто измените тип и не меняйте имя, это только вызовет путаницу.

9

Джоэл Спольски написал об этом хороший пост в блоге. http://www.joelonsoftware.com/articles/Wrong.html В основном это сводится к тому, чтобы не усложнять чтение кода, когда приличная среда IDE сообщит вам, что вы хотите ввести переменную, если вы не можете вспомнить. Кроме того, если вы сделаете свой код достаточно разделенным, вам не нужно будет помнить, какая переменная была объявлена ​​на три страницы вверх.


9

Разве в наши дни объем более важен, чем тип, например

* l for local
* a for argument
* m for member
* g for global
* etc

При использовании современных методов рефакторинга старого кода поиск и замена символа из-за того, что вы изменили его тип, утомительны, компилятор улавливает изменения типа, но часто не улавливает неправильное использование области видимости, здесь помогают разумные соглашения об именах.


Опять же, код, вероятно, не должен сильно зависеть от области видимости. :-)
Plumenator

8

Нет причин, по которым вы не должны правильно использовать венгерскую систему обозначений. Это непопулярность из-за давней негативной реакции на неправильное использование. венгерской нотации, особенно в API Windows.

В старые добрые времена, до того, как существовало что-либо похожее на IDE для DOS (есть вероятность, что у вас не было достаточно свободной памяти для запуска компилятора под Windows, поэтому ваша разработка велась в DOS), вы не получали никакой помощи от навести указатель мыши на имя переменной. (Предполагая, что у вас есть мышь.) То, с чем вам действительно приходилось иметь дело, это функции обратного вызова событий, в которых все передавалось вам как 16-битное int (WORD) или 32-битное int (LONG WORD). Затем вам нужно было привести этот параметр к соответствующим типам для данного типа события. Фактически, большая часть API практически не имела типов.

В результате получился API с такими именами параметров:

LRESULT CALLBACK WindowProc(HWND hwnd,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam);

Обратите внимание, что имена wParam и lParam, хотя и довольно ужасные, на самом деле ничем не хуже, чем назвать их param1 и param2.

Что еще хуже, в Window 3.0 / 3.1 было два типа указателей: ближний и дальний. Так, например, возвращаемое значение из функции управления памятью LocalLock было PVOID, но возвращаемое значение из GlobalLock было LPVOID (с длинной буквой «L»). Это ужасно нотация тогда расширились , так что L Ong р ointer строки был приставка LP , чтобы отличить его от строки, были просто malloc'd.

Неудивительно, что это вызвало негативную реакцию.


6

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

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

С другой стороны, могут быть случаи, когда даже языки проверки типов во время компиляции выиграют от венгерской нотации - недействительных указателей или HANDLE в Win32 API. Они запутывают фактический тип данных, и, возможно, есть смысл использовать там венгерскую нотацию. Тем не менее, если можно знать тип данных во время сборки, почему бы не использовать соответствующий тип данных.

В общем, нет веских причин не использовать венгерскую нотацию. Это вопрос лайков, политик и стиля кодирования.


6

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

Например, предположим, что у нас есть целое число foo, 12

foo = 12

Венгерская нотация говорит нам, что мы должны называть это iFoo или что-то в этом роде, чтобы обозначить его целым числом, чтобы позже мы знали, что это такое. За исключением Python, это не работает или, скорее, не имеет смысла. В Python я решаю, какой тип мне нужен, когда я его использую. Мне нужна веревка? хорошо, если я сделаю что-то вроде этого:

print "The current value of foo is %s" % foo

Обратите внимание на %sстроку -. Foo не является строкой, но %оператор вызовет foo.___str___()и использует результат (при условии, что он существует). fooпо-прежнему является целым числом, но мы рассматриваем его как строку, если нам нужна строка. Если нам нужен поплавок, мы рассматриваем его как поплавок. В языках с динамической типизацией, таких как Python, венгерская нотация бессмысленна, потому что не имеет значения, какого типа что-то, пока вы его не используете, а если вам нужен конкретный тип, просто обязательно приведите его к этому типу (например float(foo)), когда вы используй это.

Обратите внимание, что динамические языки, такие как PHP, не имеют этого преимущества - PHP пытается делать «правильные вещи» в фоновом режиме, основываясь на непонятном наборе правил, которые почти никто не запомнил, что часто неожиданно приводит к катастрофическим беспорядкам. В этом случае может пригодиться какой-то механизм именования, например $files_countили $file_name.

На мой взгляд, венгерская нотация похожа на пиявок. Может быть, в прошлом они были полезны, или, по крайней мере, они казались полезными, но сегодня это просто лишний набор текста, а не большая польза.


Интересно, что ваш пример с .str () в Python не является результатом динамического языка. Java, определенно не динамический язык, делает то же самое.
мусорщик

C # также делает то же самое, каждый класс на языке реализует .ToString()так, чтобы все это можно было распечатать.
Electric Coffee

5

IDE должна передавать эту полезную информацию. Венгерский мог иметь какой-то (не большой, но какой-то) смысл, когда IDE были намного менее продвинутыми.


4
Опять же, вам не следует полагаться на то, что IDE сообщит вам больше. В конце концов, код можно просмотреть вне среды IDE ...
TraumaPony,

5

Приложения Венгерский для меня греческий - в хорошем смысле слова

Как инженер, а не программист, я сразу же обратил внимание на статью Джоэла о достоинствах Apps Hungarian: «Сделать неправильный код неправильным» . Мне нравится Apps Hungarian, потому что он имитирует то, как инженерия, наука и математика представляют уравнения и формулы с помощью дополнительных и дополнительных символов (например, греческих букв, математических операторов и т. Д.). Рассмотрим конкретный пример закона всемирного тяготения Ньютона : сначала в стандартной математической нотации, а затем в венгерском псевдокоде Apps:

Универсальный закон всемирного тяготения Ньютона для Земли и Марса

frcGravityEarthMars = G * massEarth * massMars / norm(posEarth - posMars)

В математической системе обозначений наиболее заметными являются символы, представляющие вид информации, хранящейся в переменной: сила, масса, вектор положения и т. Д. Нижние индексы играют второстепенную роль, чтобы прояснить: положение чего? Это именно то, что делает Apps Hungarian; он сначала сообщает вам, что именно хранится в переменной, а затем переходит к конкретным деталям - о том, какой код наиболее близок к математической нотации.

Ясно, что строгая типизация может разрешить пример безопасных и небезопасных строк из эссе Джоэла, но вы не стали бы определять отдельные типы для векторов положения и скорости; оба являются двойными массивами размера три, и все, что вы, вероятно, сделаете с одним, может быть применено к другому. Кроме того, имеет смысл объединить положение и скорость (чтобы создать вектор состояния) или взять их скалярное произведение, но, вероятно, не складывать их. Как печатание разрешит первые два и запретит второе, и как такая система будет распространяться на все возможные операции, которые вы, возможно, захотите защитить? Если только вы не захотели закодировать всю математику и физику в своей системе набора текста.

Вдобавок ко всему, большая часть разработки выполняется на слабо типизированных языках высокого уровня, таких как Matlab, или старых, таких как Fortran 77 или Ada.

Так что, если у вас навороченный язык, а IDE и приложения на венгерском языке вам не помогают, забудьте об этом - по-видимому, многие люди это сделали. Но для меня, хуже, чем начинающий программист, который работает со слабо или динамически типизированными языками, я могу писать лучший код быстрее с Apps Hungarian, чем без него.


4

Это невероятно избыточно и бесполезно в большинстве современных IDE, где они хорошо делают видимость типа.

Плюс - меня - просто раздражает видеть intI, strUserName и т. Д. :)


3
Как TraumaPony сказал Полу Батуму, не все видят код в IDE.
Крис Чарабарук,

4

Если я чувствую, что передается полезная информация, почему бы мне не поместить ее прямо там, где она доступна?

Тогда кого волнует, что думают другие? Если вы сочтете это полезным, то используйте обозначения.


Потому что есть только один из меня и миллиард других людей, которые могут поддерживать мой код позже. Поскольку все эти люди входят в команду (но они еще не знают об этом), я хотел бы иметь представление, перевесили ли они меня.
Dustman

4

По моему опыту, это плохо, потому что:

1 - тогда вы нарушаете весь код, если вам нужно изменить тип переменной (например, если вам нужно расширить 32-битное целое число до 64-битного целого числа);

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

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


4

В книге Джоэла Спольски «Сделать неправильный код неправильным» он объясняет, что то, что все считают венгерской нотацией (которую он называет системной венгерской), не является тем, для чего она была задумана (то, что он называет венгерскими приложениями). Прокрутите вниз до заголовка Я Венгрия, чтобы увидеть это обсуждение.

По сути, венгерские системы бесполезны. Он просто говорит вам то же самое, что и ваш компилятор и / или IDE.

Apps Hungarian сообщает вам, что эта переменная должна означать, и может действительно быть полезной.


4

Я всегда думал, что пара-тройка приставок в нужном месте не помешает. Я думаю, что если я могу сказать что-то полезное, например: «Эй, это интерфейс, не рассчитывайте на конкретное поведение», как в IEnumerable, я должен это сделать. Комментарий может загромождать гораздо больше, чем просто одно или двухсимвольный символ.


1
Я никогда не получал ISomethingable. Если это параметр -able, это в любом случае подразумевает интерфейс. (По крайней мере, в java)
tunaranch

4

Это полезное соглашение для именования элементов управления в форме (btnOK, txtLastName и т. Д.), Если список элементов управления отображается в выпадающем списке в вашей среде IDE в алфавитном порядке.


4

Я предпочитаю использовать венгерскую нотацию с ASP.NET управления сервером только , в противном случае я считаю , это слишком сложно , чтобы выяснить , что элементы управления , что на форме.

Возьмите этот фрагмент кода:

<asp:Label ID="lblFirstName" runat="server" Text="First Name" />
<asp:TextBox ID="txtFirstName" runat="server" />
<asp:RequiredFieldValidator ID="rfvFirstName" runat="server" ... />

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


4

Статья Джоэла великолепна, но, похоже, в ней отсутствует один важный момент:

Венгерский делает конкретную «идею» (вид + имя идентификатора) уникальной или почти уникальной для всей кодовой базы - даже для очень большой кодовой базы.

Это очень важно для обслуживания кода. Это означает, что вы можете использовать старый добрый однострочный текстовый поиск (grep, findstr, «найти во всех файлах»), чтобы найти КАЖДОЕ упоминание этой «идеи».

Почему это важно, когда у нас есть IDE, умеющие читать код? Потому что они еще не очень хороши в этом. Это трудно увидеть в небольшой базе кода, но очевидно в большой - когда «идея» может быть упомянута в комментариях, файлах XML, сценариях Perl, а также в местах вне системы контроля версий (документы, вики, базы данных ошибок).

Вы должны быть немного осторожны даже здесь - например, вставка токена в макросах C / C ++ может скрыть упоминания идентификатора. В таких случаях можно использовать соглашения о кодировании, и в любом случае они, как правило, влияют только на меньшую часть идентификаторов в базе кода.

PS Что касается использования системы типов по сравнению с венгерской - лучше использовать обе. Вам нужен только неправильный код, чтобы он выглядел неправильно, если компилятор не поймает его за вас. Во многих случаях невозможно заставить компилятор отловить это. Но там, где это возможно - да, сделайте это вместо этого!

Однако при рассмотрении осуществимости следует учитывать негативные последствия разделения типов. например, в C # обертывание int с помощью не встроенного типа имеет огромные последствия. Так что в некоторых ситуациях это имеет смысл, но не во всех.


4

Разоблачение преимуществ венгерской нотации

  • Это дает возможность различать переменные.

Если тип - это все, что отличает одно значение от другого, то он может использоваться только для преобразования одного типа в другой. Если у вас есть одно и то же значение, которое преобразуется между типами, скорее всего, вам следует делать это в функции, предназначенной для преобразования. (Я видел, как венгерские остатки VB6 использовали строки во всех параметрах своих методов просто потому, что не могли понять, как десериализовать объект JSON, или правильно понять, как объявлять или использовать типы, допускающие значение NULL. ) Если у вас есть две переменные, которые различаются только Венгерский префикс, и они не являются преобразованием одного в другой, тогда вам нужно подробно рассказать о своем намерении с ними.

  • Это делает код более читабельным.

Я обнаружил, что венгерская нотация заставляет людей лениться с именами переменных. У них есть чем отличить его, и они не чувствуют необходимости уточнять его цель. Это то, что вы обычно найдете в венгерском нотном коде по сравнению с современным: sSQL против groupSelectSql ( или, как правило, без sSQL, потому что они должны использовать ORM, который был введен более ранними разработчиками. ), SValue против formCollectionValue ( или обычно нет sValue, потому что они находятся в MVC и должны использовать свои функции привязки модели ), sType vs. publishSource и т. д.

Не может быть читабельности. Я вижу больше sTemp1, sTemp2 ... sTempN из любого оставшегося венгерского VB6, чем все остальные вместе взятые.

  • Это предотвращает ошибки.

Это было бы из-за числа 2, которое неверно.


3

По словам мастера:

http://www.joelonsoftware.com/articles/Wrong.html

Как всегда, интересное чтение.

Экстракты:

«Кто-то где-то прочитал статью Симони, где он использовал слово« тип », и подумал, что он имел в виду тип, как класс, как в системе типов, как проверка типов, которую выполняет компилятор. Он этого не сделал. Он объяснил очень осторожно. именно то, что он имел в виду под словом «тип», но это не помогло. Ущерб был нанесен ».

«Но Apps Hungarian по-прежнему имеет огромное значение, поскольку увеличивает коллокацию в коде, что упрощает чтение, запись, отладку и поддержку кода, и, что наиболее важно, делает неправильный код неправильным».

Убедитесь, что у вас есть время, прежде чем читать Joel On Software. :)


Сейчас нет времени, когда у меня есть Stackoverflow. Я думаю, что простая связь Спольски с проектом должна сделать это. :)
Dustman

3

Некоторые причины:

  • Любая современная IDE предоставит вам тип переменной, просто наведя указатель мыши на переменную.
  • Большинство имен типов слишком длинные (подумайте о HttpClientRequestProvider ), чтобы их можно было разумно использовать в качестве префикса.
  • Информация о типе не несет правильной информации, она просто перефразирует объявление переменной, вместо того, чтобы обрисовывать в общих чертах назначение переменной (подумайте, myInteger vs. pageSize ).

2

Не думаю, что все яростно против этого. В языках без статических типов это очень полезно. Я определенно предпочитаю, когда он используется для предоставления информации, которой еще нет в типе. Как и в C, char * szName говорит, что переменная будет ссылаться на строку с завершающим нулем - это не подразумевается в char * - конечно, typedef также может помочь.

У Джоэла была отличная статья об использовании венгерского языка, чтобы узнать, была ли переменная закодирована в HTML или нет:

http://www.joelonsoftware.com/articles/Wrong.html

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


Я думаю, что это первое предложение может опровергнуть ответы на этой странице.
Dustman

@Dustman Ну, не вы уже знаете , что строки C являются нулем? Я действительно понимаю, как это было бы полезно, когда строка может не быть, но это редко, и поэтому я думаю, что использование соглашения должно быть ограничено этими случаями.
Plumenator

Не каждый символ * является строкой c с завершающим нулем. Смысл венгерского языка в том, чтобы использовать его для всех переменных, даже тех, которые относятся к общему случаю. В конечном счете, я чувствую то же, что и вы - и поэтому я не использую его в C.
Лу Франко

2

Конечно, когда 99% программистов с чем-то соглашаются, что-то не так. Причина, по которой они согласны здесь, заключается в том, что большинство из них никогда не использовали правильно венгерскую нотацию.

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

http://codingthriller.blogspot.com/2007/11/rediscovering-hungarian-notation.html


2

Я начал программировать примерно в то время, когда была изобретена венгерская нотация, и когда меня впервые заставили использовать ее в проекте, я ее возненавидел.

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

Но, как и все хорошее, это нужно выучить и понять, а чтобы сделать это правильно, нужно время.


1

Венгерская нотация использовалась неправильно, особенно со стороны Microsoft, что привело к префиксу длиннее имени переменной и показало, что оно довольно жесткое, особенно когда вы меняете типы (печально известный lparam / wparam, другого типа / размера в Win16, идентичный в Win32 ).

Таким образом, как из-за этого злоупотребления, так и из-за его использования M $ он был признан бесполезным.

В моей работе мы кодируем на Java, но основатель пришел из мира MFC, поэтому используйте аналогичный стиль кода (выровненные фигурные скобки, мне это нравится !, заглавные буквы для имен методов, я привык к этому, префикс, например m_, для членов класса (поля ), s_ к статическим членам и т. д.).

И они сказали, что все переменные должны иметь префикс, показывающий их тип (например, BufferedReader называется brData). Это показалось плохой идеей, поскольку типы могут меняться, но имена не следуют, или кодеры не единообразны в использовании этих префиксов (я даже вижу aBuffer, theProxy и т. Д.!).

Лично я выбрал несколько префиксов, которые считаю полезными, наиболее важным из которых является префикс b для логических переменных, поскольку это единственные префиксы, для которых я разрешаю синтаксис типа if (bVar)(без использования автоприведения некоторых значений в true или false). Когда я кодировал на C, я использовал префикс для переменных, выделенных с помощью malloc, как напоминание, что его нужно освободить позже. И т.п.

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.