Подтвердить что ты не робот

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

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

public static Point calculateIntersection(Line line1, Line line2) {

    if (line1 == null || line2 == null) {
        throw new NullPointerException(" some message ");
    }

    if (line1.getConstant() == line2.getConstant()) {
        return new Point(0, line1.getConstant());
    }

    if (line1.getSlope() == line2.getSlope()) {
        throw new IllegalArgumentException("slopes are same, the lines do not intersect.");
    }

    int x = (line2.getConstant() - line1.getConstant()) / (line1.getSlope() - line2.getSlope());
    int y = line1.getSlope() * x + line1.getConstant();

    return new Point(x, y);
}

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

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

Спасибо

4b9b3361

Ответ 1

Вопрос заключается в том, чтобы вызывать исключение из-за незаконного аргумента правильно делать?

Это зависит от того, как вы хотите/нужно "кадрировать" это условие; то есть это ошибка, ошибка ввода пользователя или что-то, что программа должна иметь возможность иметь дело?

  • Если случай двух непересекающихся строк однозначно является "ошибкой", то IllegalArgumentException отлично. Для этого и предназначен исключение. (Обратите внимание, что это неконтролируемое исключение, поэтому ожидается, что он не будет пойман/восстановлен.)

  • Если это случай, когда вы ожидаете, что программа сможет сама восстанавливаться, то предпочтительной является обычное исключение. Таким образом, вы уменьшаете вероятность того, что ваш код запутается (скажем) в методе библиотеки, который бросает (скажем) IllegalArgumentException..., чем означает нечто иное, чем "две пересекаемые строки".

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

Ответ 2

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

Вы также очень разумно определили поведение своего класса в одной из нечетких входных ситуаций, а именно две совпадающие "постоянные" (горизонтальные) линии, где вы возвращаете точку на x=0 на этой строке. Аналогичным образом вы должны выбрать возвращаемые значения для других случаев некорректных входов: совпадающие вертикальные линии, совпадающие строки, которые не являются ни горизонтальными, ни вертикальными, и несогласованными параллельными линиями.

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

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

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

Ответ 3

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

Учитывая, что в 99 +% ситуаций не будет такой ошибки, это исключительное условие и не объявляет проверенное исключение, поэтому неконтролируемое исключение действительно выглядит как правильный выбор.

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

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

Ответ 4

Как утверждают Энди Лоури и @KamikazeCZ, это не должно быть исключением.

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

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

Итак, вернемся к тому, что должен вернуть этот метод? Некоторое значение дозорного, так же, как indexOf возвращает -1 в библиотеке коллекций. Возвращение null является разумным дозорным. В Java 8 вы можете вернуть Optional<Point>, чтобы помочь напоминать вызывающему, что не может быть надлежащего Point.

У вас тоже есть дополнительная проблема: что кто-то просит пересечение строки с самим собой? (Математически пересечение двух строк равно либо 0, 1, либо бесконечно много точек.) Возможно, вам нужно будет вернуть два значения часового, что более активно, в Java. На этот раз этот метод мог бы выйти из ситуации: "в случае нескольких ответов этот метод может вернуть любой из них" или (что бы я, вероятно, сделал) "... возвращает точку, ближайшую к началу координат".

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

Наконец: при сравнении результатов getSlope() с помощью == будьте осторожны с ошибками округления с плавающей запятой. Это может быть лучше всего здесь, но это все еще проблематично. То, как вы предполагаете (или округлите) пересечение с int s, тем не менее, предполагает, что у вас могут быть особые ограничения/предположения в вашей проблеме.

Ответ 5

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