Проверенные и непроверенные исключения и мысли о дизайне - PullRequest
2 голосов
/ 05 марта 2010

Допустим, есть неизменный тип записи:

public class Record
{
    public Record(int x, int y) {
        Validator.ValidateX(x);
        Validator.ValidateY(y);
        X=x;
        Y=y;
    }

    public final int X;
    public final int Y;

    public static class Validator {
        public void ValidateX(int x) { if(x < 0) { throw new UnCheckedException; } }
        public void ValidateY(int y) { if(y < 0) { throw new UnCheckedException; } }
    }
}

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

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

Мысли все? я должен сделать проверено или не проверено, или есть лучший дизайн для этого?

UPDATE:

моя путаница исходит из этого scenerio: обычно запись будет использоваться так:

Record r = new Record(1,2);
OtherObj o = new OtherObj(r);

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

Однако, когда вы получаете параметры для Записи от пользователя, вы хотите проверить их правильно? так что вы можете позвонить

Record.ValidateX(inputX);
Record.ValidateY(inputY);

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

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

* * ОБНОВЛЕНИЕ тысячи двадцать-три (2): Я начинаю думать, что мне нужно, чтобы ValidateX генерировал проверенное исключение, потому что это обычно то, что будет использоваться, если задействован пользовательский ввод. В этом случае мы могли бы снова попросить пользователя ввести данные. Тем не менее, для конструктора Record он выдаст проверенное исключение, поскольку создание Record с недопустимыми аргументами является нарушением API. Новый код будет выглядеть так:
public class Record
{
    public Record(int x, int y) {
        try
        {
            Validator.ValidateX(x);
            Validator.ValidateY(y);
        }catch(CheckedException xcpt) { throw new UnCheckedException(xcpt.getMessage()); }
        X=x;
        Y=y;
    }

    public final int X;
    public final int Y;

    public static class Validator {
        public void ValidateX(int x) throws CheckedException { if(x < 0) { throw new CheckedException; } }
        public void ValidateY(int y) throws CheckedException { if(y < 0) { throw new CheckedException; } }
    }
}

Теперь программист может проверить параметры перед передачей их в класс Record. Если это не так, это является нарушением API и генерируется непроверенное исключение.

Как это звучит?!

Ответы [ 6 ]

6 голосов
/ 05 марта 2010

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

Нет, я думаю, что причина, по которой вы выбрасываете непроверенное исключение, заключается в том, чтовлечет за собой нарушение договора со стороны пользователя этого API, а не исключительное условие при нормальном функционировании этого метода.Посмотрите, как Java SDK использует NullPointerException, IllegalArgumentException и т. Д., Которые RuntimeExceptions , поскольку представляют нарушение контракта.

4 голосов
/ 05 марта 2010

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

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

3 голосов
/ 05 марта 2010

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

Проверка параметров, используемых в API, является совершенно другим видом. Их не нужно проверять, потому что в противном случае вы добавите try / catch к каждому вызову функции. Всякий раз, когда методу передается недопустимый аргумент, это, безусловно, ошибка программирования. Обычным способом является создание исключения IllegalArgumentException или NullPointerException (или любого другого, который соответствует вашим потребностям). В api звонках оставь проверенные исключения на

  1. Подтверждения, которые вы обещаете абоненту API
  2. Ожидаемые исключительные условия (запрошенный файл не существует, ошибка записи и т. Д.)

Помимо вышеизложенного, возможность восстановления также важна для принятия решения о проверенном или непроверенном исключении. Если вы никогда не сможете восстановить (что обычно происходит в случае ошибки программирования), вы можете (или должны?) Сделать исключение без проверки.

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

public boolean validateX(int x)
{
     return x > 0;
}

private void validateParameter(int x)
{
     if (validateX(x))
     {
         throw new IllegalArgumentException("X is invalid");
     }
}

Это немного больше работы, но она даст вам лучшее из обоих миров. Сделав функцию параметра validate закрытой, вы можете быть уверены, что случайно не используете ее за пределами своего класса. Конечно, вы также можете поместить деталь if(validateX(x)) ... в свой конструктор.

2 голосов
/ 05 марта 2010

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

1 голос
/ 05 марта 2010

Как правило, я всегда обрабатываю исключения в общедоступном интерфейсе для моего компонента / layer / api. Это позволяет исключениям пузыриться и обрабатываться на верхнем уровне - Последний ответственный момент , обеспечивая при этом обработку исключения в моем коде, избегая утечек исключений .

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

1 голос
/ 05 марта 2010

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

public interface Validator<T> {
    public boolean isValid(T object);
}

public final class PositiveIntegerValidator implements Validator<Integer> {
    public boolean isValid(Integer object) {
        return object != null && object > 0;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...