Что бы мы делали без NULL? - PullRequest
       74

Что бы мы делали без NULL?

20 голосов
/ 03 августа 2010

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

В любом случае, а что, если по умолчанию такой язык, как C #, использует ненулевые типы? Как бы вы заменили некоторые из распространенных идиом в C # или Ruby или любом другом общем языке, где null является приемлемым значением?

Ответы [ 11 ]

26 голосов
/ 03 августа 2010

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

Например, все не примитивные типы Java (и все ссылочные типы C #) обнуляются. Зачем? Мы можем идти вперед и назад, но в конечном итоге я держу пари, что ответ сводится к «это было легко». Нет ничего присущего языку Java, который требует повсеместного обнуления. Ссылки на C ++ предлагают прекрасный пример того, как изгнать нули на уровне компилятора. Конечно, C ++ имеет гораздо более отвратительный синтаксис, чем Java явно пыталась сократить, поэтому некоторые хорошие функции оказались на переднем крае наряду с плохими.

Типы значений Nullable в C # 2.0 предлагали шаг в правильном направлении - отделение Nullability от несвязанной семантики типов или, что еще хуже, деталей реализации CLR - но все еще отсутствует способ сделать обратное с ссылочными типами. (Контракты кода хороши и все, но они не встроены в систему типов, как мы здесь обсуждаем.)

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

Чтобы ответить на ваш вопрос: запрещать нули на современном языке, оптом, было бы так же глупо, как и так называемая «ошибка в миллиард долларов». Существуют допустимые программные конструкции, в которых хорошо иметь нулевые значения: необязательные параметры, любые виды вычислений по умолчанию / резервные значения, когда оператор объединения приводит к лаконичному коду, взаимодействию с реляционными базами данных и т. Д. Принудительное использование значений часовых, NaN и т. Д «лечение» гораздо хуже, чем болезнь.

Тем не менее, я предварительно согласен с настроением , выраженным в цитате, до тех пор, пока я могу уточнить, чтобы соответствовать моему собственному опыту:

  1. Количество ситуаций, в которых нулевые значения желательны, меньше, чем думает большинство людей
  2. как только вы вводите пустые значения в библиотеку или путь кода, от них намного сложнее избавиться, чем от их добавления. (поэтому не позволяйте младшим программистам делать это по прихоти!)
  3. Шкала ошибок с переменным временем жизни
  4. соответствует # 3: ранний сбой
23 голосов
/ 03 августа 2010

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

7 голосов
/ 14 декабря 2010

Haskell - мощный язык, в котором нет понятия нуль.По сути, каждая переменная должна быть инициализирована ненулевым значением.Если вы хотите представить «необязательную» переменную (переменная может иметь значение, но не может), вы можете использовать специальный тип «Возможно».

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

Кроме того, обратите внимание, что многие из вышеперечисленных людей, похоже, предлагают заменять пустые значения типичными логическими значениями «ничего» (999-999-9999, " NULL " и т. Д.).Эти значения на самом деле ничего не решают, потому что проблема, с которой сталкиваются люди с пустыми значениями, заключается в том, что они являются особым случаем, но люди забывают написать код для особого случая.Со специфическими для типа значениями логического «ничего» люди все равно забывают кодировать для особого случая, но избегают ошибок, которые улавливают эту ошибку, что является плохой вещью.

4 голосов
/ 03 августа 2010

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

По сути, это будет общеязыковая реализация шаблона NullObject: http://en.wikipedia.org/wiki/Null_Object_pattern Так что на самом деле он не избавляется от нулевых объектов, он просто удерживает их от особых случаев, которые должны быть обработаныв качестве таких.

4 голосов
/ 03 августа 2010

Я думаю, что вы имеете в виду этот доклад: " Нулевые ссылки: ошибка в миллиард долларов "

2 голосов
/ 21 сентября 2011

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

Если язык просто потребует проверки любого указателя или преобразования его в не-nullable type сначала, 99% ошибок, связанных с null, исчезнут.Например, в C ++

void fun(foo *f)
{
    f->x;                  // error: possibly null
    if (f)              
    {
        f->x;              // ok
        foo &r = *f;       // ok, convert to non-nullable type
        if (...) f = bar;  // possibly null again
        f->x;              // error
        r.x;               // ok
    }
}

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

2 голосов
/ 03 августа 2010

Tcl - это один из языков, который не только не имеет понятия «ноль», но и в котором само понятие «ноль» противоречит ядру языка. В tcl мы говорим: «все является строкой». На самом деле это означает, что tcl имеет строгую семантику значений (что по умолчанию происходит со строками).

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

  1. В любом случае используйте пустую строку - в большинстве случаев это не имеет значения для конечного пользователя.

  2. Используйте значение, которое, как вы знаете, не существует в потоке данных, например, строку "_NULL_" или число 9999999 или мой любимый байт NUL "\0".

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

  4. Проверка существования переменной - [info exists variable_name].

Интересно отметить, что Tcl - не единственный язык со строгой семантикой значений. C также имеет строгую семантику значений, но семантика значений по умолчанию оказывается целыми, а не строками.

О, почти забыл еще один:

В некоторых библиотеках используется вариант числа 2, который позволяет пользователю указать, что является заполнителем для «нет данных». В основном это позволяет вам указать значение по умолчанию (а если вы этого не сделаете, значением по умолчанию обычно является пустая строка).

1 голос
/ 12 сентября 2011

Что бы мы делали без NULL? Изобретите это! :-) Вам не нужно быть ученым, чтобы использовать 0, если вы ищете значение внутриполосного указателя для выражения на самом деле не указатель .

1 голос
/ 14 декабря 2010

Реально говоря, на любом мощном языке программирования, который в первую очередь допускает указатели или ссылки на объекты, будут ситуации, когда код сможет получить доступ к указателям, на которых не был запущен какой-либо код инициализации. Может быть возможно гарантировать, что такие указатели будут инициализированы к некоторому статическому значению, но это не кажется ужасно полезным. Если у машины есть общие средства захвата доступа к неинициализированным переменным (будь то указатели или что-то еще), это лучше, чем нулевые указатели в специальном корпусе, но в остальном самые большие ошибки, связанные с нулями, встречаются в реализациях, которые допускают арифметику с нулевыми указателями , Добавление 5 к (char *) 0 не должно приводить к символьному указателю на адрес 5; это должно вызвать ошибку (если уместно создавать указатели на абсолютные адреса, должны быть другие способы сделать это).

0 голосов
/ 03 августа 2010

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

  • У шаблона Null Object есть свои недостатки, как я объяснил здесь .
  • Специфичные для домена нули.Это вынуждает вас проверять магические числа, , что плохо .
  • Оболочки коллекции, где пустая коллекция означает «нет значения». Обнуляемые обертки были бы лучше, но это мало чем отличается от проверки на null или использования шаблона Null Object.

Лично я бы написал некоторый препроцессор C #, которыйпозволяет мне использовать null.Затем он будет отображаться на некоторый объект dynamic, который выдает NullReferenceException всякий раз, когда к нему вызывается метод.

В 1965 году нулевые ссылки могли выглядеть как ошибка.Но в настоящее время со всеми видами инструментов анализа кода, которые предупреждают нас о нулевых ссылках, нам не нужно сильно беспокоиться.С точки зрения программирования null является очень ценным ключевым словом.

...