Переходя нуль к методу

голоса
16

Я нахожусь в середине чтения отличный чистый код

Одна дискуссия о прохождении аннулирует в метод.

public class MetricsCalculator {
    public double xProjection(Point p1, Point p2) {
        return (p2.x - p1.x) * 1.5;
    }
}
...
calculator.xProjection(null, new Point(12,13));

Она представляет собой различные способы обработки:

public double xProjection(Point p1, Point p2) {
    if (p1 == null || p2 == null) {
        throw new IllegalArgumentException(Invalid argument for xProjection);
    }
    return (p2.x - p1.x) * 1.5;
}

public double xProjection(Point p1, Point p2) {
    assert p1 != null : p1 should not be null;
    assert p2 != null : p2 should not be null;
    return (p2.x - p1.x) * 1.5;
}

Я предпочитаю утверждения подхода, но мне не нравится тот факт , что утверждения по умолчанию выключены.

Книга, наконец, гласит:

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

Это на самом деле не вдаваться в том, как вы бы применять это ограничение?

У кого из вас есть сильные мнения так или иначе.

Задан 28/08/2008 в 14:34
источник пользователем
На других языках...                            


16 ответов

голоса
8

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

Также читайте статью о оборонительном программировании

Ответил 28/08/2008 в 14:45
источник пользователем

голоса
4

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

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

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

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

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

Ответил 28/08/2008 в 23:26
источник пользователем

голоса
4

Также не немедленного использования, но связаны с упоминанием Spec # ... Там предложение добавить «неопределенные безопасные типы» в будущей версии Java: «Enhanced нулевой обработки - Null-безопасные типы» .

Согласно этому предложению, ваш метод станет

public class MetricsCalculator {
    public double xProjection(#Point p1, #Point p2) {
        return (p2.x - p1.x) * 1.5;
    }
}

где #Pointэто тип непредставленных nullссылок на объекты типа Point.

Ответил 28/08/2008 в 17:20
источник пользователем

голоса
3

Это на самом деле не вдаваться в том, как вы бы применять это ограничение?

Вы поддерживаете его, бросая ArgumentExcexception , если они проходят в нуле.

if (p1 == null || p2 == null) {
    throw new IllegalArgumentException("Invalid argument for xProjection");
}
Ответил 28/08/2008 в 14:42
источник пользователем

голоса
2

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

Я нашел JetBrains ' @Nullableи @NotNullподход аннотаций для борьбы с этим самым гениальным, до сих пор. Это IDE конкретно, к сожалению, но на самом деле чистое и мощное, ИМО.

http://www.jetbrains.com/idea/documentation/howto.html

Имея это (или нечто подобное) в качестве стандарта Java будет очень приятно.

Ответил 28/08/2008 в 18:51
источник пользователем

голоса
2

Spec # выглядит очень интересно!

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

/**
 * Checks to see if an object is null, and if so 
 * generates an IllegalArgumentException with a fitting message.
 * 
 * @param o The object to check against null.
 * @param name The name of the object, used to format the exception message
 *
 * @throws IllegalArgumentException if o is null.
 */
public static void checkNull(Object o, String name) 
    throws IllegalArgumentException {
   if (null == o)
      throw new IllegalArgumentException(name + " must not be null");
}

public static void checkNull(Object o) throws IllegalArgumentException {
   checkNull(o, "object");
} 

// untested:
public static void checkNull(Object... os) throws IllegalArgumentException {
   for(Object o in os) checkNull(o);  
}

Тогда проверка превращается в:

public void someFun(String val1, String val2) throws IllegalArgumentException {
   ExceptionUtilities.checkNull(val1, "val1");
   ExceptionUtilities.checkNull(val2, "val2");

   /** alternatively:
   ExceptionUtilities.checkNull(val1, val2);
   **/

   /** ... **/
} 

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

Ответил 28/08/2008 в 17:05
источник пользователем

голоса
2

Я предпочитаю использовать утверждение.

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

Ответил 28/08/2008 в 14:45
источник пользователем

голоса
1

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

//  allocate null
var name : Option[String]
name = None

//  allocate a value
name = Any["Hello"]

//  print the value if we can
name match {
  Any[x] => print x
  _ => print "Nothing at all"
}
Ответил 29/10/2008 в 23:43
источник пользователем

голоса
1

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

Использование статического анализа кода, FindBugs может затем указать на места, где этот метод вызывается с потенциально нулевым значением.

Это имеет два преимущества:

  1. Аннотацию описывает свое намерение о том, как метод должен быть вызван, помогающее документации
  2. FindBugs может указывать на потенциальные проблемы абонентов метода, что позволяет отследить возможные ошибки.

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

Ответил 28/08/2008 в 23:34
источник пользователем

голоса
1

Хотя это не является строго связаны вы можете взглянуть на Spec # .

Я думаю, что все еще находится в разработке (по Microsoft), но некоторые CTP доступны, и это выглядит многообещающе. В основном это позволяет сделать это:

  public static int Divide(int x, int y)
    requires y != 0 otherwise ArgumentException; 
  {
  }

или

  public static int Subtract(int x, int y)
    requires x > y;
    ensures result > y;
  {
    return x - y;
  } 

Он также предоставляет другие функции, такие как типы NotNull. Это построить на вершине .NET Framework 2.0 и она полностью совместима. Syntaxt, как вы можете видеть, это C #.

Ответил 28/08/2008 в 15:22
источник пользователем

голоса
1

@ Крис Karcher я бы сказал абсолютно правильно. Единственное, что я бы сказал, проверить Params отдельно и иметь отчет Exeption Парам, который был нулевым также, как это делает отслеживание где нуль происходит из гораздо проще.

@wvdschel ничего себе! Если писать код слишком много усилий для вас, вы должны смотреть на что - то вроде PostSharp (или эквивалент Java , если таковой имеется) , который может постобработку ваших сборок и вставки из параметров проверки для вас.

Ответил 28/08/2008 в 14:45
источник пользователем

голоса
1

Я согласен или не согласен с постом wvdschel в , это зависит от того, что он конкретно говорил.

В этом случае, конечно, этот метод будет врезаться на nullтак явную проверку здесь, вероятно , не требуется.

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

Ответил 28/08/2008 в 14:43
источник пользователем

голоса
1

Я вообще предпочитаю не делать либо, так как это только замедляет работу. NullPointerExceptions выбрасываются позже в любом случае, который быстро приведет пользователя к открытию они проходя нуль методу. Я использовал, чтобы проверить, но 40% мой код заканчивал тем, проверочный код, в какой момент я решил, что это просто не стоит приятных Утверждающих сообщений.

Ответил 28/08/2008 в 14:38
источник пользователем

голоса
0

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

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

Ответил 29/08/2008 в 00:55
источник пользователем

голоса
0

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

Ответил 28/08/2008 в 17:59
источник пользователем

голоса
0

Thwrowing C # ArgumentExceptionили Java IllegalArgumentExceptionв самом начале методы смотрит на меня , как ярчайшие решениях.

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

Ответил 28/08/2008 в 17:53
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more