Наконец, у меня есть вопрос к переполнению стека! : -)
Основная цель для Java, но я считаю, что это в основном не зависит от языка: если у вас нет нативного утверждения, вы всегда можете смоделировать его.
Я работаю в компании, продающей набор программного обеспечения, написанного на Java. Код устарел, по крайней мере, начиная с Java 1.3, и в некоторых местах он показывает ... Это большая база кода, около 2 миллионов строк, поэтому мы не можем все сразу же реорганизовать.
Недавно мы переключили последние версии с синтаксиса Java 1.4 и JVM на Java 1.6, консервативно используя некоторые новые функции, такие как assert
(раньше мы использовали макрос DEBUG.ASSERT - я знаю, что assert
был представлен в 1.4 но мы не использовали его раньше), дженерики (только типизированные коллекции), цикл foreach, перечисления и т. д.
Я все еще немного зелен в использовании assert, хотя я прочитал несколько статей на эту тему. Тем не менее, некоторые обычаи, которые я вижу, оставляют меня в замешательстве, причиняя боль моему здравому смыслу ... ^ _ ^ Поэтому я подумал, что должен задать несколько вопросов, чтобы понять, правильно ли я хочу исправлять что-либо или противоречит обычной практике. Я многословен, так что я выделил вопросы, для тех, кто любит разбираться с вещами.
Для справки, я искал assert java в SO и нашел несколько интересных тем, но, по-видимому, точных дубликатов нет.
- Как избежать «! = Null» операторов в Java? и Сколько проверки нуля достаточно? весьма актуальны, потому что многие из утверждений, которые мы имеем, просто проверяют, равна ли переменная нулю. В некоторых местах в нашем коде есть использование нулевого объекта (например, возвращающий
new String[0]
), но не всегда. Мы должны жить с этим, по крайней мере, для поддержки устаревшего кода.
- Некоторые хорошие ответы также в недооцененных утверждениях Java .
- Да, и SO указывает на то, что Когда мне следует использовать Debug.Assert ()? Вопрос также связан (хорошая функция для уменьшения дубликатов!).
Во-первых, основной вопрос, который вызвал мой вопрос сегодня:
SubDocument aSubDoc = documents.GetAt( i );
assert( aSubDoc != null );
if ( aSubDoc.GetType() == GIS_DOC )
{
continue;
}
assert( aSubDoc.GetDoc() != null );
ContentsInfo ci = (ContentsInfo) aSubDoc.GetDoc();
( Да, мы используем соглашения по стилю / коду MS C / C ++. И мне даже это нравится (исходя из того же фона)! Так что подайте в суд на нас. )
Во-первых, форма assert()
происходит от преобразования вызовов DEBUG.ASSERT()
. Мне не нравятся дополнительные скобки, так как assert является языковой конструкцией, а не (здесь больше не) вызовом функции. Мне также не нравится return (foo);
: -)
Далее, утверждения здесь не проверяются на инварианты, они скорее используются для защиты от плохих значений. Но, насколько я понимаю, они здесь бесполезны: assert выдаст исключение, даже не задокументированное со строкой-компаньоном, и только если утверждения включены. Поэтому, если у нас есть опция -ea
, мы просто выбрасываем утверждение вместо обычного исключения NullPointerException. Это не похоже на первостепенное преимущество, так как в любом случае мы ловим непроверенные исключения на самом высоком уровне.
Правильно ли я полагаю, что мы можем избавиться от них и жить с этим (т. Е. Позволить Java вызвать такое непроверенное исключение)? (или, конечно, проверить нулевое значение, если это возможно, что делается в других местах) ).
Примечание: если мне придется утверждать в приведенном выше фрагменте кода, я сделаю это по отношению к значению ci, а не к получателю: даже если большинство получателей оптимизированы / встроены, мы не можем быть уверены, поэтому мы должны избегать его двойного вызова .
Кто-то сказал, в последнем потоке, на который ссылаются, что публичные методы должны использовать тесты со значениями параметров (использование публичного API), а приватные методы должны полагаться на утверждения. Хороший совет.
Теперь оба вида методов должны проверять другой источник данных: внешний ввод. То есть. данные, поступающие от пользователя, из базы данных, из какого-либо файла или из сети, например.
В нашем коде я вижу утверждения против этих значений. Я всегда изменяю их на настоящий тест, поэтому они действуют даже при отключенных утверждениях: они не являются инвариантами и должны обрабатываться надлежащим образом.
Я себеЕдинственное возможное исключение, когда ввод предполагается постоянным, например, таблица базы данных, заполненная константами, используемыми в отношениях: программа прервется, если эта таблица будет изменена, но соответствующий код не обновлен.
Видите ли вы другие исключения?
Другое сравнительно частое использование, которое я вижу, которое кажется нормальным: при переключении по умолчанию или в конце серии else if
тестирование всех возможных значений (эти случаи датируются еще до нашего использования перечислений!), Там часто assert false : "Unexpected value for stuff: " + stuff;
Выглядит законно для меня (эти случаи не должны происходить в производстве), как вы думаете? (кроме советов "не переключайтесь, используйте OO", которые здесь не имеют значения).
И, наконец, есть ли другие полезные варианты использования или надоедливые ошибки Я пропустил здесь? (Возможно!)