Как показать, что метод может вернуть ноль - PullRequest
43 голосов
/ 04 января 2009

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

Я пишу метод и уже знаю, хочу ли я вернуть ноль или выдать исключение, как лучше всего выразить мое решение, другими словами, документировать мой контракт?

Некоторые способы, которыми я могу придумать:

  • Запишите это в спецификации / документации (кто-нибудь прочитает?)
  • Сделать его частью имени метода (как я и предлагал здесь )
  • Предположим, что каждый метод, который выдает исключение, не возвращает ноль, а каждый метод, который не 'throw' может возвращать ноль.

Я в основном говорю о java, но это может относиться и к другим языкам: почему существует формальный способ выражения, если генерируются исключения (ключевые слова throws), но нет формального способа выражения, если ноль может быть возвращенным?

Почему нет чего-то подобного:

public notnull Object methodWhichCannotReturnNull(int i) throws Exception
{
    return null; // this would lead to a compiler error!
}

Сводка и заключение

Есть много способов выразить договор:

  • Если ваша IDE поддерживает его (например, IntelliJ), лучше использовать аннотацию, например @NotNull, потому что она видна программисту и может использоваться для автоматической проверки времени компиляции. Для Eclipse есть плагин для добавления поддержки, но он не работает для меня.
  • Если это не вариант, используйте пользовательские типы, такие как Option<T> или NotNull<T>, которые добавляют ясность и, по крайней мере, проверку во время выполнения.
  • В любом случае, документирование контракта в JavaDoc никогда не повредит, а иногда даже помогает.
  • Использование имен методов для документирования обнуляемости возвращаемого значения не было предложено никем, кроме меня, и хотя оно может быть очень многословным и не всегда полезным, я все же считаю, что иногда оно тоже имеет свои преимущества .

Ответы [ 11 ]

35 голосов
/ 04 января 2009

Очень хороший дополнительный вопрос. Я считаю null действительно особым значением, и если метод может возвращать null, он должен четко документировать в Javadoc, когда это происходит (@return some value ..., or null if ...). При кодировании я защищаюсь и предполагаю, что метод может вернуть null, если я не уверен, что это невозможно (например, потому что Javadoc сказал так).

Люди поняли, что это проблема, и предлагаемое решение состоит в том, чтобы использовать аннотации для указания намерения таким образом, чтобы его можно было проверить автоматически. См. JSR 305: аннотации для обнаружения дефектов программного обеспечения , JSR 308: аннотации для типов Java и в JetBrain с указанием типа .

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

@NotNull
public Object methodWhichCannotReturnNull(int i) throws Exception
{
    return null; // this would lead to a compiler error!
}
8 голосов
/ 04 января 2009

Вы можете использовать тип Option, который очень похож на список с нулем или одним элементом. Тип возврата Option<Object> указывает, что метод может возвращать Object или может возвращать специальное значение типа None. Этот тип заменяет использование null с улучшенными проверками типов.

Пример:

public Option<Integer> parseInt(String s) {
   try {
      return Option.some(Integer.parseInt(s));
   }
   catch (Exception e) {
      return Option.none();
   }
}

Если вы используете это последовательно, вы можете включить IDE NULL-предупреждения или просто использовать grep для null, который вообще не должен появляться в вашем коде, если вы используете Option.none() везде, где вы обычно используете null буквальный.

Option входит в стандартную комплектацию Scala и в Haskell называется Maybe. Ссылка выше на библиотеку под названием Functional Java , которая включает ее. Эта версия реализует интерфейс Iterable и имеет монадические методы, которые позволяют вам красиво сочинять. Например, чтобы предоставить значение по умолчанию 0 в случае None:

int x = optionalInt.orSome(0);

И вы можете заменить это ...

if (myString != null && !"".equals(myString))

... с этим, если у вас есть Option<String> ...

for (String s : myOptionString)
2 голосов
/ 04 января 2009

Для Java можно использовать описание метода Javadoc для документирования значения возвращаемого значения, в том числе того, может ли оно быть нулевым. Как уже упоминалось, аннотации могут также помочь здесь.

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

Несомненно, попытка вызова метода с нулевым значением вызовет исключение. Но так будет и попытка делить на ноль. Это не значит, что нам нужно идти в поход, чтобы устранить нули! Это просто означает, что нам нужно понять контракт по методу и правильно поступить со значениями, которые он возвращает.

2 голосов
/ 04 января 2009

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

Я вижу три варианта:

  1. дождитесь языковой поддержки, чтобы выразить это (например, C #?! вещь)
  2. используйте Aspect Orientation для создания собственных языковых расширений, чтобы выразить это
  3. использовать пользовательский тип, чтобы выразить его
  4. (но основывается на сотрудничестве с разработчиками), чтобы обозначить его, используйте схему именования
1 голос
/ 04 января 2009

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

1 голос
/ 04 января 2009

Может быть, вы могли бы определить универсальный класс с именем "NotNull", чтобы ваш метод мог выглядеть так:

public NotNull<Object> methodWhichCannotReturnNull(int i) throws Exception
{
   // the following would lead to a run-time error thown by the
   // NotNull constructor, if it's constructed with a null value
   return new NotNull<Object>(null);
}

Это все еще проверка во время выполнения (не во время компиляции), но:

  • Он добавляется в реализацию метода (это не ошибка в вызывающем коде)
  • Самодокументируется (вызывающий знает, что получает NotNull<T> в качестве типа возврата)
1 голос
/ 04 января 2009

Существует некоторая поддержка аннотаций @ Nullable и @NotNull в IntelliJ IDEA . Также есть разговоры о добавлении этих аннотаций (или аналогичной функции) в Java 7. К сожалению, я не знаю, как далеко они продвинулись или все еще на пути.

1 голос
/ 04 января 2009

Вы можете написать собственную аннотацию (Java) или атрибут (C #), чтобы указать, что возвращаемое значение может быть нулевым. Ничто не будет автоматически проверять это (хотя .NET 4.0 будет иметь кодовые контракты для такого рода вещей), но это по крайней мере будет действовать как документация.

1 голос
/ 04 января 2009

Вы смотрели на Spec # ?

0 голосов
/ 04 января 2009

Вообще говоря, я бы предположил, что нулевое возвращаемое значение не соответствует контракту API по умолчанию. Почти всегда возможно спроектировать ваш код так, чтобы нулевое значение никогда не возвращалось из ваших API во время «нормального» потока выполнения. (Например, проверьте foo.contains (obj), а не вызывайте foo.get (obj) и используйте отдельную ветвь для нуля. Или используйте шаблон объекта Null .

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...