Это нормально для разных классов реализации, чтобы бросать разные типы исключений? - PullRequest
1 голос
/ 19 ноября 2009

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

(плохой) пример:

public interface IWidgetWorker {
    /// <summary>
    /// Do the work required for the specified work id.
    /// </summary>
    /// <param name="workId">The id of the piece of work to do</param>
    /// <exception cref="ArgumentException">Thrown if workId is empty</exception>
    public void DoWork(Guid workId);
}

public class DatabaseWidgetWorker : IWidgetWorker {
    public void DoWork(Guid workId) { 
        // throw some database related exception
    }
}

public class WebWidgetWorker : IWidgetWorker {
    public void DoWork(Guid workId) {
        // throw some web related exception
    }
}

Может быть, я добавлю WidgetWorkerException класс? Где я документирую, какие конкретные исключения могут генерировать реализующие классы?

Ответы [ 3 ]

3 голосов
/ 19 ноября 2009

Часть дизайна интерфейса часто документирует ожидаемые исключения. Эти исключения логичны во время создания интерфейса, например InvalidOperationException для вызова метода и неправильного состояния объекта или ArgumentOutOfRangeException при передаче неправильного параметра.

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

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

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

0 голосов
/ 19 ноября 2009

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

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

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

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

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

0 голосов
/ 19 ноября 2009

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

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