Правильное решение в Java: проанализируйте 2 числа из 2 строк и затем верните их сумму - PullRequest
84 голосов
/ 25 августа 2011

Довольно глупый вопрос.Учитывая код:

public static int sum(String a, String b) /* throws? WHAT? */ {
  int x = Integer.parseInt(a); // throws NumberFormatException
  int y = Integer.parseInt(b); // throws NumberFormatException
  return x + y;
}

Не могли бы вы сказать, хорошо ли это Java или нет?То, о чем я говорю, это NumberFormatException - непроверенное исключение.У вас нет , чтобы указать его как часть sum() подписи.Более того, насколько я понимаю, идея непроверенных исключений состоит лишь в том, чтобы сигнализировать о том, что реализация программы неверна, и, более того, перехват непроверенных исключений является плохой идеей, поскольку это похоже на исправление плохой программы во время выполнения .

Кто-нибудь уточнит, пожалуйста:

  1. Я должен указать NumberFormatException как часть сигнатуры метода.
  2. Я должен определить свое собственное проверенное исключение (BadDataException), обработайте NumberFormatException внутри метода и перебросьте его как BadDataException.
  3. Я должен определить свое собственное проверенное исключение (BadDataException), проверить обе строки как-то как регулярные выражения и бросить мойBadDataException если не совпадает.
  4. Ваша идея?

Обновление :

Представьте, что это не открытый кодрамки, которые вы должны использовать по какой-то причине.Вы смотрите на подпись метода и думаете: «Хорошо, он никогда не бросает».Затем, однажды, вы получили исключение.Это нормально?

Обновление 2 :

В некоторых комментариях говорится, что мой sum(String, String) плохой дизайн.Я абсолютно согласен, но для тех, кто считает, что оригинальная проблема никогда бы не появилась, если бы у нас был хороший дизайн, вот дополнительный вопрос:

Определение проблемы таково: у вас есть источник данных, где хранятся числакак String с.Этот источник может быть файлом XML, веб-страницей, окном рабочего стола с 2 полями редактирования, чем угодно.

Ваша цель - реализовать логику, которая принимает эти 2 String с, преобразует их в int с и отображает окно с сообщением "сумма равна ххх".

Независимо от того, чтоподход, который вы используете для разработки / реализации этого, вы будете иметь эти 2 точки внутренней функциональности :

  1. Место, где вы конвертируете String в int
  2. Место, куда вы добавляете 2 int s

Основной вопрос моего оригинального сообщения:

Integer.parseInt() ожидает правильно строка для передачи.Всякий раз, когда вы передаете неверную строку , это означает, что ваша программа неверна (не " ваш пользователь идиот").Вам нужно реализовать фрагмент кода, где с одной стороны у вас есть Integer.parseInt () с MUST семантикой , а с другой стороны, вы должны быть в порядке со случаями, когда ввод неправильный - СЛЕДУЕТсемантика .

Итак, вкратце: как мне реализовать СЛЕДУЕТ семантике , если у меня только ДОЛЖНЫ библиотеки .

Ответы [ 18 ]

1 голос
/ 25 августа 2011

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

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

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

  • Не нужно объявлятьПользовательское исключение как «выбрасывает», поскольку оно не проверено.

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

  • Также правильное документирование в java-doc является хорошей практикой и очень помогает.

1 голос
/ 25 августа 2011

Любое исключительное поведение должно быть разъяснено в документации. Либо следует указать, что этот метод возвращает специальное значение в случае сбоя (например, null, путем изменения типа возврата на Integer), либо в случае 1. Явное указание в сигнатуре метода позволяет пользователю игнорировать его, если он обеспечивает правильные строки другими средствами, но все же очевидно, что метод сам по себе не обрабатывает такого рода ошибки.

1 голос
/ 25 августа 2011

Хотя я согласен с ответом о том, что исключение времени выполнения должно быть разрешено перколировать, с точки зрения дизайна и удобства использования, было бы хорошей идеей заключить его в IllegalArgumentException, а не выдавать его как NumberFormatException. Затем это делает контракт вашего метода более понятным, в результате чего он объявляет, что ему был передан недопустимый аргумент, из-за которого он вызвал исключение.

Относительно обновления вопроса «Представьте себе, это не фреймворк с открытым исходным кодом, который вы должны использовать по какой-то причине. Вы смотрите на сигнатуру метода и думаете:« Хорошо, он никогда не выбрасывает ». Затем однажды вы есть исключение. Это нормально? " Javadoc вашего метода всегда должен отражать поведение вашего метода (ограничения до и после). Подумайте о строках интерфейсов, скажем, коллекции, где, если пустое значение не разрешено, Javadoc сообщает, что будет выдано исключение нулевого указателя, хотя оно никогда не является частью сигнатуры метода.

1 голос
/ 25 августа 2011
  1. Вы можете сделать это, чтобы было ясно, что это может произойти при неправильном вводе. Это может помочь кому-то, использующему ваш код, запомнить эту ситуацию. Точнее говоря, вы даете понять, что сами не обрабатываете его в коде или вместо этого возвращаете какое-то конкретное значение. Конечно, JavaDoc должен прояснить это тоже.
  2. Только если вы хотите, чтобы вызывающий абонент имел дело с проверенным исключением.
  3. Это похоже на излишество. Полагайтесь на синтаксический анализ, чтобы обнаружить неверный ввод.

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

1 голос
/ 25 августа 2011

Многое зависит от сценария, в котором вы находитесь.

Случай 1. Всегда вы, кто отлаживает код, и никто и исключение не вызовет плохой пользовательский опыт

Бросок по умолчанию NumberFormatException

Case2: код должен быть чрезвычайно понятным и понятным

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

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

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

  1. Исключение формата чисел
  2. Исключение переполнения
  3. Нулевое исключение и т. Д. *

и разберитесь со всеми этими

1 голос
/ 31 августа 2011

Я думаю, что ваше первое предложение «Довольно глупый вопрос» очень актуально.Зачем вам вообще писать метод с такой подписью?Есть ли смысл суммировать две строки?Если вызывающий метод хочет суммировать две строки, то вызывающий метод обязан убедиться, что они являются действительными целочисленными значениями, и преобразовать их перед вызовом метода.

В этом примере, если вызывающий метод не может преобразовать двеСтроки в int, он может делать несколько вещей.Это действительно зависит от того, на каком уровне происходит это суммирование.Я предполагаю, что преобразование String будет очень близко к внешнему коду (если это было сделано правильно), так что наиболее вероятным будет случай 1.

  1. Установить сообщение об ошибке и остановить обработкуили перенаправить на страницу с ошибкой
  2. Вернуть false (т. е. она поместит сумму в какой-то другой объект и не потребует ее возврата)если суммирование этих двух чисел не очень важно, это излишне, и, как упомянуто выше, это, вероятно, плохой дизайн, так как подразумевает, что преобразование выполняется в неправильном месте
1 голос
/ 25 августа 2011

Ответ на обновленный вопрос.

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

e.g ArrayIndexOutofBound

Также является общим неожиданным исключением из каждого цикла.

ConcurrentModificationException or something like that
0 голосов
/ 12 октября 2013

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

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

Дело в том, что семантика Integer.parseInt() известна - ее основная цель - проанализировать действительные целые числа.Вам не хватает явного шага проверки / анализа ввода пользователя.

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