Возвращаемые значения против возвращаемых кодов ошибок? - PullRequest
1 голос
/ 11 октября 2011

Это общий вопрос программирования, не относящийся к какому-либо конкретному языку.

Обычно новый программист напишет метод, который вычисляет некоторое значение, а затем возвращает значение:

public Integer doSomething()
{
   // Calculate something
   return something;
}

public void main()
{
  Integer myValue = doSomething();
}

Но когда возникает исключение во время вычисления something, каков наилучший способ обработки исключения, особенно при предоставлении обратной связи с пользователем?Если вы делаете попытку / улов вычисления something и если обнаруживается исключение, что вы возвращаете?Ничего не было рассчитано, так вы возвращаете ноль?И как только вы вернете его (каким бы оно ни было), вам нужно будет выполнить еще одну попытку / перехват в родительском методе, который проверяет, было ли возвращено правильное значение?А если нет, то убедитесь, что пользователь получил какую-то обратную связь?

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

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

ОБНОВЛЕНИЕ для уточнения

Рассмотрите следующий код:

public void main()
{
  int myValue = getMyValue();

  MyUIObject whatever = new MyUIObject();
  whatever.displayValue(myValue); // Display the value in the UI or something
}

public Integer getMyValue()
{
  try
  {
    // Calculate some value
  } catch (exception e) {
    // ??
  }
  return value;
}

Я вызываю метод для получения некоторого значения типа int, затем возвращаю его.Вернувшись в main(), я что-то делаю со значением, например, показываю это в журнале в этом случае.Обычно я бы отображал значение в пользовательском интерфейсе для пользователя.

В любом случае, если исключение перехвачено в getMyValue(), то возвращается ли value, но оно равно нулю?Что происходит в main() тогда?Должен ли я проверить, является ли это допустимым значением и в main()?

Мне нужна программа, чтобы соответствующим образом обработать ошибку и продолжить.Кто-то ниже предложил отобразить соответствующую информацию в пользовательском интерфейсе из метода getMyValue().Я вижу две потенциальные проблемы:

  1. Кажется, что я бы смешал бизнес-логику с (в данном случае) логикой для пользовательского интерфейса.
  2. Я должен был бы передать ссылкуот MyUIObject до getMyValue() или что-то еще, чтобы я мог получить к нему доступ из функции.В приведенном выше простом примере это не так уж и сложно, но если есть набор элементов пользовательского интерфейса, которые необходимо обновить или изменить в зависимости от того, что происходит в getMyValue(), передача их всех может быть немного ...

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

Ответы [ 3 ]

2 голосов
/ 11 октября 2011

Я думаю, что вы не совсем понимаете исключения.

Если вы бросаете исключение, вы не обычно возвращаетесь из функции:

public Integer doSomething()
{
   throw new my_exception();
   // The following code does NOT get run
   return something;
}

public void main()
{
  Integer myValue = doSomething();
}

ОсновнойПреимущества исключений:

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

Я рекомендую этот пост Эрика Липперта , в котором обсуждаетсяИсключения и когда это и не подходит для их обработки.


ОБНОВЛЕНИЕ (в ответ на комментарий):

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

Например:

try
{
   // Perform calculation
}
catch (ExceptionType ex)
{
   // A problem of type 'ExceptionType' occurred - you can do whatever you
   // want here.
   // You could log it to a list, which will be later shown to the user,
   // you could set a flag to pop up a dialog box later, etc
}

// The code here will still get run even if ExceptionType was thrown inside
// the try {} block, because we caught and handled that exception.

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


ОБНОВЛЕНИЕ 2 в ответ на ваши изменения:

Вы должны обработать исключение на уровне, на котором вы можете ответить так, как вы хотите.Для вашего примера, вы правы, вам не следует отлавливать исключение так глубоко в коде, поскольку у вас нет доступа к пользовательскому интерфейсу и т. Д., И, следовательно, вы не можете сделать что-нибудь полезное.* Как насчет этой версии вашего примера кода:

public void main()
{
  int myValue = -1; // some default value
  String error = null; // or however you do it in Java (:

  try
  {
    getMyValue();
  }
  catch (exception e)
  {
    error = "Error calculating value. Check your input or something.";
  }

  if (error != null)
  {
    // Display the error message to the user, or maybe add it to a list of many
    // errors to be displayed later, etc.
    // Note: if we are just adding to a list, we could do that in the catch().
  }

  // Run this code regardless of error - will display default value
  // if there was error.
  // Alternatively, we could wrap this in an 'else' if we don't want to
  // display anything in the case of an error.
  MyUIObject whatever = new MyUIObject();
  whatever.displayValue(myValue); // Display the value in the UI or something
}

public Integer getMyValue()
{
  // Calculate some value, don't worry about exceptions since we can't
  // do anything useful at this level.
  return value;
}
0 голосов
/ 11 октября 2011

Исключения - это свойство объектно-ориентированных языков (OOL). Если вы используете OOL, вы должны предпочесть исключения. Это намного лучше, чем возвращать коды ошибок. Вы можете найти хорошие примеры того, как подход с кодами ошибок генерирует значительно более длинный исходный код, чем код на основе исключений. Например, если вы хотите прочитать файл, что-то с ним сделать и сохранить в другом формате. Вы можете делать это на C без исключений, но ваш код будет полон операторов if (error) ..., возможно, вы попытаетесь использовать некоторые операторы goto, возможно, некоторые макросы, чтобы сделать его короче. Но также абсолютно непрозрачен и труден для понимания. Также вы часто можете просто забыть проверить возвращаемое значение, чтобы вы не увидели ошибку и программа продолжилась. Это не хорошо. С другой стороны, если вы пишете в OOL и используете исключения, ваш исходный код сосредоточен на том, «что делать, если ошибок нет», а обработка ошибок находится в другом месте. Только один единственный код обработки ошибок для многих возможных ошибок файла. Исходный код короче, понятнее и т. Д.

Лично я бы никогда не попытался вернуть коды ошибок на объектно-ориентированных языках. Единственным исключением является C ++, где система исключений имеет некоторые ограничения.

0 голосов
/ 11 октября 2011

Вы писали:

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

[EDIT] На самом деле исключение можно рассматривать как код ошибки, который идет вместе с относительнымсообщение, и вы, как программист, должны знать, где ваше исключение должно быть перехвачено, обработано и в конечном итоге отображено пользователю.Пока вы позволяете исключению распространяться (спускаясь в стек вызываемых функций), никакие возвращаемые значения не используются, поэтому вам не нужно заботиться об обработке связанных пропущенных значений.Хорошая обработка исключений - довольно сложная проблема.

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

 public Integer doSomething(){

     try{

         throw new my_exception();}

     catch{ return err_value;} 

     }

бессмысленно.

...