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

Какова наилучшая практика для блоков catch catch для создания чистого кода?

Возможный дубликат:
Рекомендации по управлению исключениями в JAVA или С#

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

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

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

Каждый конструктивный комментарий приветствуется.:)

import java.awt.Point;
import java.io.Closeable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;

/**
 * <p>This is a dummy code.</p>
 * The aim is present the best practice on exception separation and handling.
 */
public class ExceptionHandlingDemo {
    // System.out is not a good practice. Using logger is good for testing too (can be checked if the expected error messages are produced).
    private Logger logger = LoggerFactory.getLogger(ExceptionHandlingDemo.class);

    // instance of cannot work with List<Point>
    private interface PointList extends List<Point> {}

    /**
     * The method that loads a list of points from a file.
     * @param path - The path and the name of the file to be loaded.
     * Precondition: path cannot be {@code null}. In such case {@link NullPointerException} will be thrown. 
     * Postcondition: if the file don't exist, some IOException occurs or the file doesn't contain the list the returned object is {@code null}.
     * */
    /* (Google throws NullpointerExceptio) since it is not forbidden for the developers to throw it. I know this is arguable but this is out of topic for now. */
    public List<Point> loadPointList(final String path) {
        Preconditions.checkNotNull(path, "The path of the file cannot be null");

        List<Point> pointListToReturn = null;
        ObjectInputStream in = null;

        try {
            in = openObjectInputStream(path);
            pointListToReturn = readPointList(in);
        } catch (final Throwable throwable) {
            handleException(throwable);
        } finally {
            close(in);
        }

        return pointListToReturn;
    }

    /*======== Private helper methods by now ========*/

    private ObjectInputStream openObjectInputStream(final String filename) throws FileNotFoundException, IOException {
        return new ObjectInputStream(new FileInputStream(filename));
    }

    private List<Point> readPointList(final ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
        final Object object = objectInputStream.readObject();

        List<Point> ret = null;

        if (object instanceof PointList) {
            ret = (PointList) object;
        }
        return ret;
    }

    private void handleException(final Throwable throwable) {
        // I don't know the best practice here ...
        logger.error(throwable.toString());
    }

    private void close(final Closeable closeable) { 
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException e) {
                logger.error("Failed closing: %s", closeable);
            }
        }
    }

    /*======== Getters and setters by now. ========*/

    // ...

    /**
     * @param args
     */
    public static void main(String[] args) {
        ExceptionHandlingDemo test = new ExceptionHandlingDemo();
        test.loadPointList("test-filename.ext");
    }
}

Редакция:

Чего я хочу избежать, это писать много случаев catch друг за другом...

4b9b3361

Ответ 1

Несколько предложений на первый взгляд:

  • Вы не должны улавливать Throwable и вместо этого выискивать как можно более конкретное исключение. Проблема с ловкостью Throwable заключается в том, что будут включать классы Error, такие как OutOfMemoryError и тому подобное. Вы хотите, чтобы те проходили мимо (они неконтролированы по какой-то причине).
  • Когда вы регистрируете исключения, всегда передавайте исключение, а не только его toString(). Очень сложно диагностировать проблемы без трассировки стека.
  • Вероятно, вам не нужен общий метод обработки исключений.

Итак, в местах, где вы ловите исключения, вы хотите что-то вроде этого:

} catch (IOException e) {
    logger.error("some relevant message", e);
    // now handle the exception case
}

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

Ответ 2

За проверенными исключениями, которые я не буду беспокоить, я всегда использую org.apache.commons.lang.UnhandledException.

Например

/**
 * Calls Thread.sleep(millis)
 */
public static void threadSleep(final long millis) {
    try {
        Thread.sleep(millis);
    } catch (final InterruptedException e) {
        throw new UnhandledException(e);
    }
}

Ответ 3

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

Самое важное для меня - это то, что у вас НИКОГДА нет пустого блока catch - один из них может занять поразительное количество времени, чтобы обнаружить, что что-то внутри try действительно вызывает исключение.

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

Ответ 4

Есть несколько вариантов, которые вы можете выбрать.

  • Одна из самых важных преимуществ использования исключений заключается в том, что вы можете иметь единственный обработчик исключений для всех случаев. Когда вы пишете свой код, вы должны сначала подумать о функциональности, а затем об обработке исключений. В результате вы можете пропустить в некоторых местах try/catch вообще для непроверенных исключений и объявить свои методы как throws SomeCheckedException для отмеченных исключений. Это позволяет вам иметь минимальное количество обработчиков исключений.

  • Если вы не знаете, что именно делать с исключением, просто снимите его.

  • Если вы поймали проверенное исключение, но не хотите, чтобы клиенты, использующие ваш код, обрабатывали исключения, вы можете проверить обновление исключений в unchecked. (Hibernate обрабатывает исключения таким образом. Они улавливают проверенное исключение sql и вместо этого исключают исключенные исключения)
  • Если предыдущая рекомендация вам не подходит, вы также можете выбрать несколько вариантов:
    • вы можете просто добавить ведение журнала и повторить одно и то же исключение.
    • вы можете использовать цепочки исключений, бросая новое исключение с помощью метода initCause()
    • вы можете подумать, что код, вызывающий ваш код, не должен знать ничего об исходном исключении, вы можете его заархивировать, создав новое исключение или используя метод fillInStackTrace().
  • Что касается ловли Throwable. Да, в методах вы не должны его поймать. Но, как правило, клиент, который использует вашу программу, вообще не должен видеть excetpions, в результате вы можете поймать Throwable в обработчике некоторых исключений, который является вершиной в цепочке.