Пустой результат и выбрасываемое исключение для предсказуемой, но непредсказуемой ошибки - PullRequest
0 голосов
/ 03 мая 2018

Каков предпочтительный дизайн для методов, которые встречают предсказуемый, но непредсказуемый отказ? Должны ли они возвращать пустой результат или выдавать исключение при ошибке? Пожалуйста, объясните ваши аргументы.

Я приведу два примера методов:

  1. Метод, подобный Arrays.binarySearch () , который возвращает индекс значения в массиве.
  2. Tickets.buy(20, 100). Билетный бот пытается купить как минимум 20 билетов за 100 долларов. Метод возвращает список купленных билетов.

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

Способ 1 может завершиться неудачей, если:

  • Массив не содержит нужного значения.

Способ 2 может завершиться неудачей, если:

  • Недостаточно билетов.
  • Билетов на продажу достаточно, но они стоят больше 100 долларов.

Java решила вернуть эквивалент пустого результата для метода 1, но, сделав то же самое для метода 2, вы не сможете различить два вида ошибок. Каковы рекомендации по выбору между двумя возможными конструкциями?

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

Ответы [ 4 ]

0 голосов
/ 15 мая 2018

В итоге я принял совет, найденный на https://stackoverflow.com/a/77361/14731

Моя интерпретация следующая:

  • С точки зрения пуриста, если цель Arrays.binarySearch() состоит в том, чтобы вернуть индекс элемента в массиве, то он должен выдать исключение, если совпадение не найдено. Тот факт, что ни у одного результата нет отрицательного индекса, является удобным фактом, который позволяет нам вместо этого возвращать -1. Но опять же, в идеальном мире этот метод должен быть исключением. Если бы этот метод отвечал на вопрос «содержит ли массив этот элемент» и возвращал boolean, то исключение не требовалось бы.
  • Tickets.buy(20, 100) предполагает, что совпадение будет найдено при покупке билетов. Если совпадений не найдено, следует выдать исключение.
0 голосов
/ 03 мая 2018

Лучший подход зависит от случая.

Дело 1: Поскольку метод возвращает индекс найденного элемента, я предлагаю вернуть -1, если нужное значение не было найдено. Придерживайтесь известного API, с которым почти все знакомы, например, indexOf().

Случай 2: Здесь я бы предложил использовать исключения (InsufficientMoneyException, OutOfTicketsException, ...). Пустой список или null не очень значимы, и различные случаи ошибок не могут быть отражены с этим. Таким образом, вы можете правильно обрабатывать исключения в соответствующих блоках перехвата.

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

0 голосов
/ 03 мая 2018

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

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

Следуя принципу единой ответственности , один метод должен делать одно.

Целью первого метода является поиск элемента, он может найти его или не найти. Это ожидаемое поведение .

Цель второго метода - купить билет. В отличие от первого метода, он не проверяет , может ли он купить билет или нет, он делает это. Ожидаемое поведение - билет куплен. Если такого поведения не происходит , что-то пошло не так, поэтому должно быть выдано исключение .

Я также думаю, что подход @ StriplingWarrior может быть не идеальным, потому что, если у вас более двух возможных случаев, вы не можете иметь Either<A, B, C, D, E, ...>.


RIP. Я потратил 15 минут на написание ответа, и я случайно открыл веб-консоль и удалил тело. Последний сохраненный ответ был как 10 минут назад. Я даже не знаю, как вы можете сделать это случайно. Я думаю, F12 и DEL довольно близко

0 голосов
/ 03 мая 2018

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

В первые дни Java было обычным возвращать обычно недопустимые значения, такие как -1 (в случае Arrays.binarySearch()) или null, чтобы представить отсутствие значения. Более современные API, как правило, возвращают Optional<>, чтобы обеспечить применение во время компиляции концепции, что результат может отсутствовать (а также провести различие между «без результата» и «результатом является null»). ).

В примере Tickets.buy() у вас может быть Either<String, List<Ticket>>, где значение «влево» может быть причиной неудачной покупки, а значение «вправо» - это билеты, которые был куплен, если это удалось.

...