Утверждения Java используются недостаточно

StackOverflow https://stackoverflow.com/questions/298909

  •  08-07-2019
  •  | 
  •  

Вопрос

Мне интересно, почему assert ключевое слово так мало используется в Java?Я почти никогда не видел, чтобы их использовали, но думаю, что это отличная идея.Я, конечно, предпочитаю краткость:

assert param != null : "Param cannot be null";

к многословию:

if (param == null) {
    throw new IllegalArgumentException("Param cannot be null");
}

Я подозреваю, что они используются недостаточно, потому что

  • Они появились относительно поздно (Java 1.4), и к тому времени многие люди уже сформировали свой стиль/привычку к программированию на Java.
  • По умолчанию они отключены во время выполнения.
Это было полезно?

Решение

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

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

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

Ваша точка зрения на то, что они «опаздывают» в Java, также является причиной того, что их не так широко видят.

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

Другие советы

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

Если этот метод является частным методом внутри одного из ваших классов, с утверждением все в порядке, потому что вы просто пытаетесь убедиться, что случайно не передадите ему нулевой аргумент.Вы тестируете с включенными утверждениями, и когда вы протестировали все пути и не активировали утверждение, вы можете отключить их, чтобы не тратить на них ресурсы.Они также полезны в качестве комментариев.Ан assert в начале метода является хорошей документацией для сопровождающих о том, что им следует соблюдать определенные предварительные условия, а также assert в конце постусловие документирует, что должен делать метод.Они могут быть так же полезны, как и комментарии;более того, потому что с включенными утверждениями они фактически ПРОВЕРЯЮТ то, что документируют.

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

От Программирование с утверждениями

По умолчанию утверждения отключены во время выполнения.Два переключателя командной строки позволяют выборочно включать или отключать утверждения.

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

В «Эффективной Java» Джошуа Блох предложил (в теме «Проверка правильности параметров»), что (что-то вроде простого правила) для общедоступных методов мы должны проверять аргументы и выдавать необходимое исключение, если оно признано недействительным, и для непубличных методов (которые не раскрываются, и вы, как их пользователь, должны гарантировать их достоверность) вместо этого мы можем использовать утверждение.

yc

@Дон, ты расстроен тем, что утверждения отключены по умолчанию.Я тоже был таким и написал этот небольшой Javac-плагин, который встраивает их (т.е. выдает байт-код для if (!expr) throw Ex вместо этого глупого байт-кода утверждения.

Если вы включите fa.jar в вашем пути к классам при компиляции кода Java он совершит свое волшебство, а затем сообщит

Note: %n assertions inlined.

@видеть http://smallwiki.unibe.ch/adriankuhn/javacompiler/forceassertions и альтернативно на github https://github.com/akuhn/javac

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

Утверждения предназначены только для тестирования и имеют два побочных эффекта:Большие двоичные файлы и снижение производительности при включении (поэтому их можно отключить!)

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

Утверждения полезны, потому что они:

  • своевременно обнаруживать ошибки ПРОГРАММИРОВАНИЯ
  • код документа с использованием кода

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

В Прагматичный программист они даже рекомендуют запустить их в производство.

Оставьте утверждения включенными

Используйте утверждения, чтобы предотвратить невозможное.

Обратите внимание, что утверждения выдают AssertionError в случае сбоя, поэтому они не перехватываются исключением catch.

Утверждения очень ограничены:Вы можете тестировать только логические условия, и вам нужно каждый раз писать код для полезного сообщения об ошибке.Сравните это с функцией AssertEquals() в JUnit, которая позволяет генерировать полезное сообщение об ошибке на основе входных данных и даже отображать два входных данных рядом в среде IDE в программе JUnit.

Кроме того, вы не можете искать утверждения ни в одной IDE, которую я видел до сих пор, но каждая IDE может искать вызовы методов.

Фактически они появились в Java 1.4.

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

Как заявили другие:утверждения не подходят для проверки ввода пользователя.

Если вас беспокоит многословие, я рекомендую вам проверить написанную мной библиотеку: https://bitbucket.org/cowwoc/requirements/.Это позволит вам выразить эти проверки с использованием очень небольшого количества кода и даже сгенерирует сообщение об ошибке от вашего имени:

requireThat("name", value).isNotNull();

и если вы настаиваете на использовании утверждений, вы тоже можете сделать это:

assertThat("name", value).isNotNull();

Вывод будет выглядеть следующим образом:

java.lang.NullPointerException: name may not be null

вр; доктор

  • Да, используйте тестирование утверждений в производстве где это имеет смысл.
  • Используйте другие библиотеки (Юнит, УтверждатьJ, Хэмкрест, и т. д.), а не встроенный assert объект, если хотите.

Большинство других ответов на этой странице придерживаются принципа «Утверждения обычно не используются в рабочем коде».Хотя это верно для приложений для повышения производительности, таких как текстовый процессор или электронная таблица, в пользовательских бизнес-приложениях, где Java так часто используется, тестирование утверждений в рабочей среде чрезвычайно полезно и распространено.

Как и многие постулаты в мире программирования, то, что изначально истинно в одном контексте, неверно истолковывается, а затем неверно применяется в других контекстах.

Приложения для повышения производительности

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

Формализованное тестирование утверждений зародилось в таких приложениях, как текстовый процессор, например Microsoft Word или электронная таблица типа Майкрософт Эксель.Эти приложения могут вызывать массив проверок утверждений. при каждом нажатии клавиши сделанный пользователем.Такой крайний повторение серьезно влияло на производительность.Таким образом, утверждения были включены только в бета-версиях таких продуктов, выпускаемых ограниченным тиражом.Итак, максима.

Бизнес-приложения

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

Тестирование бизнес-правил

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

Условия выполнения

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

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

Санитарные проверки

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

Например, проверка того, что округление пятицентовой монеты (0,05) до пенни приводит к получению пятицентовой монеты (0,05) в определенной библиотеке, помогло мне стать одним из первых, кто обнаружил недостаток технологии с плавающей запятой, которую Apple включила в свою программу. Розетта библиотека во время перехода с PowerPC на Intel.Такой недостаток, дошедший до общественности, казался невозможным.Но, что удивительно, уязвимость ускользнула от внимания создателя Transitive и Apple, а также разработчиков раннего доступа, тестирующих бета-версии Apple.

(Кстати, я должен упомянуть… никогда не используйте плавающая запятая для денег, использовать BigDecimal.)

Выбор фреймворков

Вместо использования встроенного assert возможности, вы можете рассмотреть возможность использования другой структуры утверждений.У вас есть несколько вариантов, в том числе:

Или сверните сами.Создайте небольшой класс для использования в своем проекте.Что-то вроде этого.

package work.basil.example;

public class Assertions {
    static public void assertTrue ( Boolean booleanExpression , CharSequence message ) throws java.lang.AssertionError {
        if ( booleanExpression ) {
            // No code needed here.
        } else { // If booleanExpression is false rather than expected true, throw assertion error.
            // FIXME: Add logging.
            throw new java.lang.AssertionError( message.toString() );
        }
    }

}

Пример использования:

Assertions.assertTrue( 
    localTime.isBefore( LocalTime.NOON ) , 
    "The time-of-day is too late, after noon: " + localTime + ". Message # 816a2a26-2b95-45fa-9b0a-5d10884d819d." 
) ;

Ваши вопросы

Они появились относительно поздно (Java 1.4), и к тому времени многие люди уже сформировали свой стиль/привычку к программированию на Java.

Да, это совершенно верно.Многие были разочарованы API, разработанным Sun/JCP для тестирования утверждений.Ее дизайн был тусклым по сравнению с существующими библиотеками.Многие проигнорировали новый API и остановились на известных инструментах (сторонних инструментах или собственных мини-библиотеках).

По умолчанию они отключены во время выполнения. ПОЧЕМУ, ПОЧЕМУ??

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

Другая причина отключения по умолчанию могла быть связана с тем фактом, что, добавляя новую функцию утверждения, Sun украла слово assert.Это было нет ранее зарезервированное ключевое слово и требовало одного из немногих изменений, когда-либо внесенных в язык Java.Имя метода assert использовался многими библиотеками и многими разработчиками в их собственном коде.Для обсуждения этого исторического перехода прочитайте эту старую документацию: Программирование с утверждениями.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top