2016-12-04 3 views
1

Сегодня я (еще раз) разыменовал свойство неопределенного объекта, вызывающее впечатляющий сбой нашего сервера. Решение проблемы: писать одну из моих самых нелюбимых частей шаблонного кода, превращаяПочему разыменование не предназначено для безопасности?

if (foo.bar.baz.id) {...

в

if (foo && foo.bar && foo.bar.baz && foo.bar.baz.id) {...

потому что baz оказался в краевом случае null и это вызывает исключение ,

Так что мой вопрос: почему разыменовывает null/undefined такую ​​проблему? Почему не foo.bar.baz.something просто безопасно вернуть undefined, когда foo/bar/baz не определены? Я понимаю технические почему, и меня интересует язык Почему? Существуют ли языки, которые имеют безопасное разыменование? Есть ли реальная причина CS, почему нет, или это просто традиция (унаследованная форма C и ее старые друзья)?

Я могу придумать одну причину, которая заключается в том, что с большей логикой «проверки типов» в действии, которое так же часто выполняется как разыменование, может немного замедлить язык. Но потом я также думаю, что большую часть проблемы можно решить, имея правильную обработку исключений в операторах присваивания/if/итак, так что разыменование может просто продолжаться равно, а операторы «более высокого уровня» позаботятся о случайных "oopises".

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

Я был бы очень признателен, если бы кто-нибудь из CS не пролил свет на эту проблему.

+1

Первое, что приходит в голову - проблемы с производительностью: если доступ к полю элемента неявно подтвержден, что все содержащие объекты действительны, тогда ООП будет по своей сути медленнее по сравнению с программированием, отличным от OO (если значение одного поля вычисляется из двух других полей, то действительность всего объекта будет проверяться минимум три раза). Хотя это может быть оптимизировано (только проверяя действительность объекта один раз за операцию, если, например, не используется «volatile» или эквивалент языка, не все компиляторы одинаково квалифицированы для оптимизации. –

+0

* «Существуют ли языки с безопасным разыменованием?» * - Да, [Цель-C] (http://stackoverflow.com/a/2696909/1402846). – Pang

ответ

1

То, что вы описываете не разумность/безопасность в deferencing, это то, что я называю null monadic behavior это означает, что если операция T принимать нулевое значение п в качестве входных данных, его результат п без каких-либо вычислений сделанный.

Возможно, вы больше всего знакомы с термином null propagation с сайта C# или Objective-C equivalent.
Даже SQL NULL ведет себя монадически по отношению к операциям.

Языки, подобные C, не имеют нулевого распространения по соображениям производительности, добавляя ветку до того, как любое уважение сильно замедлит работу.
Другие языки определяются по-разному, потому что они имеют различную цель (например, SQL работает с данными и отмечен NULL) или другой историей (Objective-C происходит от SmallTalk, где объекты не откладываются, а сигнализируются, поэтому отправка сообщения не производится -объект действителен и ничего не делает).


Бремя нулевой проверки не смягчается пустым распространением, хотя это еще хуже.
Иногда удобно, но в основном это нарушает правило «сбой быстро».

Признано, что null was a big mistake in CS.
Решение - это использование так называемого monads в Haskell или Optional в Java или nullable types в C# или boost::optional в C++.
Null не является значением, не имеет типа, тогда как все вышеприведенные решения являются значениями и имеют типы.
В сочетании с сопоставлением с образцом или их приближением они очень плавны в использовании и отлично подходят для самостоятельного документирования кода.
Они также безопасны в использовании (для чего позволяет система типов языка)

Смежные вопросы