Является ли венгерская запись обходным решением для языков с недостаточно выразительной статической типизацией? [закрыто]

28

В статье Эрика Липперта Что случилось с венгерской нотацией? Он заявляет, что цель Венгерской нотации (хороший вид) состоит в том, чтобы

расширить понятие «тип», чтобы охватить семантическую информацию в дополнение к информации представления представления.

Простым примером будет префикс переменной, представляющей X-координату с «x», и переменной, представляющей Y-координату с «y», независимо от того, являются ли эти переменные целыми числами или числами с плавающей запятой или чем-то еще, так что при случайной записи xFoo + yBarкод явно выглядит неправильно.

Но я также читал о системе типов Haskell, и кажется, что в Haskell можно сделать то же самое (то есть «расширить концепцию типа, чтобы охватить семантическую информацию»), используя фактические типы, которые компилятор проверит для вас. Таким образом, в приведенном выше примере xFoo + yBarв Haskell будет невозможно выполнить компиляцию, если вы правильно разработали свою программу, поскольку они будут объявлены как несовместимые типы. Другими словами, похоже, что система типов Haskell эффективно поддерживает проверку во время компиляции, эквивалентную венгерской нотации

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

(Конечно, я использую Haskell в качестве примера. Я уверен, что есть другие языки с аналогично выразительными (rich? Strong?) Системами типов, хотя я не сталкивался ни с какими.)


Чтобы было ясно, я говорю не о том, чтобы аннотировать имена переменных с типом данных , а скорее о информации о значении переменной в контексте программы. Например, переменная может быть целым числом или числом с плавающей запятой, двойным или длинным или любым другим, но, возможно, значение переменной заключается в том, что это относительная x-координата, измеренная в дюймах. Это та информация, о которой я говорю, о кодировании через венгерскую нотацию (и через типы Haskell).

Райан К. Томпсон
источник
Pascal - хотя если вы попытаетесь добавить тип XCood и YCoord, который вы определили в Pascal, вы просто получите предупреждение компилятора IIRC
mcottle
1
blog.moertel.com/articles/2006/10/18/… - это статья о том, как сделать что-то очень похожее на «приложения венгерские» в системе типов в Haskell.
Логан Капальдо
1
F # также имеет эту стилевую особенность.
Rangoric
Это действительно хорошая ссылка на статью (Moertel.com), показывающая именно то, о чем я думал: использование системы типов для превращения уязвимостей безопасности при интерполяции строк и тому подобного в ошибки во время компиляции. Спасибо за ссылку.
Райан К. Томпсон
Я думаю, что ОО догнал венгерскую нотацию для семантики, потому что сегодня вы, вероятно, напишите: Foo.Position.X + Bar.Position.Y.
Питер Б

Ответы:

27

Я бы сказал "Да".

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

  1. Эта информация важна.
  2. Эта информация не важна.

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

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

Что возвращает нас к цитате Эрика Липперта:

расширить понятие «тип», чтобы охватить семантическую информацию в дополнение к информации представления представления.

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

Йорг Миттаг
источник
C, где венгерская нотация была наиболее используемой AFAIK, не является языком OO.
Петер Тёрёк
4
@ PéterTörök: ОО - это шаблон проектирования, а не особенность языка, хотя современные языки разработаны так, чтобы облегчить его, а С - нет.
Ян Худек
3
@ PéterTörök: я написал довольно много объектно-ориентированного кода на простом C. Я знаю, о чем говорю.
Ян Худек
1
Хотя может быть верно, что важная информация должна быть встроена в тип переменной, а не в ее имя, есть много важных вещей, которые следует сказать, но которые системы типов не могут выразить. Например, если S1это единственная ссылка где-либо в юниверсе на пользователя char[], владелец которого может и будет изменять его всякий раз, когда это необходимо, но никогда не должен подвергаться внешнему коду, и S2является ссылкой на объект, char[]который никто никогда не должен изменять, но который может использоваться совместно. с объектами, которые обещают не изменять его, следует ли S1и следует S2ли рассматривать семантически как одну и ту же «вещь»?
Суперкат
1
@supercat - вы описываете уникальные типы.
Джек
9

Все назначение типов (как инструмента проектирования) - это кодирование семантической информации

Мне понравился этот ответ, и я хотел продолжить этот ответ ...

Я ничего не знаю о Haskell, но вы можете выполнить что-то вроде примера xFoo + yBarна любом языке, который поддерживает некоторую форму безопасности типов, такую ​​как C, C ++ или Java. В C ++ вы можете определять классы XDir и YDir с перегруженными операторами «+», которые принимают только объекты своего собственного типа. В C или Java вам нужно будет выполнить добавление, используя функцию / метод add () вместо оператора «+».

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

BHS
источник
Быть объектно-ориентированным не является ни необходимым, ни достаточным для того, чтобы язык допускал xFoo + yBarопределяемые пользователем типы, а также аспект OO C ++, необходимый для работы этого примера.
Люк Дантон
Вы правы, это не OO, это безопасность типов. Я отредактировал свой ответ.
BHS
Хм. Хорошо, что вы можете сделать xFoo + yBarошибку компиляции (или, по крайней мере, ошибку времени выполнения) практически на любом языке. Однако будет ли математика с классами XDir и YDir, скажем, в Java или C ++ медленнее математики с необработанными числами? Насколько я понимаю, в Haskell типы проверяются во время компиляции, а затем во время выполнения это будет просто математика без проверки типов и, следовательно, не медленнее, чем добавление обычных чисел.
Райан К. Томпсон
В C ++ проверка типов также будет выполняться во время компиляции, и преобразование и тому подобное будут оптимизированы в большинстве случаев. Java не делает этого также, потому что не допускает перегрузки операторов и тому подобного - так что вы не можете рассматривать XCoordinate, например, как обычное int.
Цао
5

Я понимаю, что фраза «Венгерская нотация» стала означать нечто иное, чем оригинал , но я отвечу «нет» на вопрос. Именование переменных с семантическим или вычислительным типом не делает то же самое, что типизация в стиле SML или Haskell. Это даже не бинт. Взяв C в качестве примера, вы можете назвать переменную gpszTitle, но эта переменная может не иметь глобальной области видимости, она может даже не представлять собой точку для строки с нулевым символом в конце.

Я думаю, что более современные венгерские нотации имеют еще большее отклонение от строгой системы вывода типов, потому что они смешивают «семантическую» информацию (например, «g» для глобального или «f» для флага) с вычислительным типом (указатель «p», « я "целое число, и т. д.). Это просто заканчивается как нечестивый беспорядок, когда имена переменных имеют только смутное сходство с их вычислительным типом (который изменяется со временем), и все они выглядят настолько похожими, что вы не можете использовать" следующее соответствие "для найти переменную в определенной функции - они все одинаковы.

Брюс Эдигер
источник
4

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

C, потомок BCPL, имеет различные типы для целых чисел, указателей, символов и т. Д. Это в некоторой степени лишает базовую венгерскую нотацию (вам не нужно кодировать имя переменной, если это int или указатель), но семантика за пределами этого уровня все еще не может быть выражена как типы. Это привело к различию между тем, что было названо «Системы» и «Приложения» венгерским. Вам не нужно было указывать, что переменная была int, но вы могли использовать кодовые буквы, чтобы указать, является ли int, скажем, координатой x или y или индексом.

Более современные языки допускают определения пользовательских типов, что означает, что вы можете кодировать семантические ограничения в типах, а не в именах переменных. Например, типичный язык ОО будет иметь определенные типы для координатных пар и областей, поэтому вы избегаете добавления координаты x к координате y.

Например, в известной статье Джоэлса, в которой хвалят Apps Hungarian, он использует пример префикса usдля небезопасной строки и sдля безопасной (закодированной в html) строки, чтобы предотвратить HTML-инъекцию. Разработчик может предотвратить ошибки внедрения HTML-кода, просто тщательно проверив код и убедившись, что префиксы переменных совпадают. Его пример в VBScript, ныне устаревшем языке, который изначально не допускал пользовательских классов. В современном языке проблема может быть исправлена ​​с помощью пользовательского типа, и это действительно то, что Asp.net делает с HtmlStringклассом. Таким образом, компилятор автоматически найдет ошибку, что намного безопаснее, чем полагаться на человеческое зрение. Очевидно, что язык с пользовательскими типами исключает необходимость использования «Apps Hungarian» в этом случае.

JacquesB
источник
2

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

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

По сути, нам нужны какие-то строго типизированные typedef для уничтожения полностью венгерской нотации на этих языках (UoM в стиле F # также может это сделать)

JK.
источник
2

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

В те мрачные дни было полезно узнать, какой тип переменной, где она используется. При правильном обслуживании (БОЛЬШОЙ, если из-за отсутствия инструментов рефакторинга) венгерская нотация дала вам это.

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

mcottle
источник
1
Если я не ошибаюсь, это еще один ответ, который касается другого типа венгерской нотации, чем тот, о котором спрашивает ОП.
MatrixFrog
2
Этот ответ описывает то, что называется «Системный венгерский», где префикс обозначает языковой уровень «тип». Вопрос задается о «Apps Hungarian», где слово «тип» не понято неправильно и означает семантический тип. Венгерские системы в наши дни почти повсеместно осуждены (и это справедливо; это подлость настоящей цели венгерской нотации). Apps венгерский, однако, может быть хорошей вещью.
Цао
Редакторы, способные искать sCustomer, не выбирая sCustomerName (vi и emacs - 2 примера), существуют с 70-х годов.
Ларри Коулман
@ Ларри, может быть, но вы не могли заставить их работать на системах, которые я программировал в 80-х
mcottle
@cHAo, Нет, это не так. Моя точка зрения заключалась в том, чтобы объяснить, почему люди обычно помещают дополнительную информацию в имена переменных. Я старательно избегал упоминания любой версии венгерской нотации. Может быть, пример, который я привел в разделе «почему поиск и замена не работают с исходным кодом», выглядит для вас как «Венгерский систем», но это не так. Я удалил ведущие "s", чтобы избежать путаницы.
Маккотл
0

Правильный!

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

Дополнительные "я", "д" и "?" префиксы просто делают код менее читабельным и могут вводить в заблуждение - например, когда «коровник» меняет тип iaSumsItems с Integer на Long, но не беспокоит рефакторинг имени поля.

Джеймс Андерсон
источник
9
Ваш ответ говорит о том, что вы не понимаете разницу между оригинальным, умным венгерским «Apps» и тупой бастардизацией под названием «Systems» венгерский. Читайте joelonsoftware.com/articles/Wrong.html
Райан Калпеппер