Договор. Страхование и обработка исключений
Недавно я обнаружил API.NET Contracts, и, хотя мне не нравится способ реализации с использованием методов, а не расширенный синтаксис (на мой взгляд,Sing # сделал все правильно), я предпочитаю использовать их старым / обычным способом используя if для проверки нуля.
Я также приближаюсь к своим первым вызовам Contract.Ensures и наткнулся на вопрос, как мы будем обращаться с исключениями в методе, содержащем Contract.Ensures, которые пострадали от исключения во время работы?
Слово Контракт.Гарантирует, что мне кажется, что я должен обработать исключения внутри метода и снова привести мой класс в правильное состояние, но что если я не смогу?
Допустим, у нас есть этот класс здесь:
public class PluginManager
{
private ILoadedFromAtCompileTimeUnknownAssembly extension;
public bool IsFinished { get; private set; }
public void Finish()
{
extension.Finish();
this.IsFinished = true;
}
}
мы можем использовать Contract.Ensures, чтобы убедиться, что IsFinished верен после завершения метода?
2 ответа
Да. Обеспечивает в основном означает "Гарантирует, что метод завершается нормально", то есть без исключений.
Мне очень трудно правильно понять концепцию кодовых контрактов. Контракты кода предназначены для поиска ошибок программирования. При таком способе вы можете удалить контракты из вашей сборки выпуска, и ваше приложение продолжит работать идеально.
НО очень трудно отличить программирование (он же логические ошибки) от проблем конфигурации и ввода данных. Эти проверки должны оставаться в ваших сборках релиза. Поэтому плохая идея использовать Code Contracts для проверки правильности загрузки расширения / плагина, поскольку он обычно настраивается в вашем приложении. Если вы удаляете контракты в своей сборке выпуска, вы получаете другое поведение вашего приложения в зависимости от того, неправильно ли вы настроили свое приложение в сборках отладки или выпуска.
Нарушения контракта регистрируются только с одним типом исключения, что делает невозможным реагирование на верхних уровнях вашего приложения, например, на проблему конфигурации или логическую ошибку в вашем приложении. С реакцией я не хочу продолжать, но чтобы представить удаленно полезное сообщение пользователю / разработчику, что пошло не так.
Кодекс контракта выглядит красиво на поверхности, но я боюсь, что большинство людей используют его неправильно. Он не предназначен для замены всех ваших нулевых проверок для проверки ввода в ваших методах. Вы должны заменять только те методы, которые проверяет NULL, на контракты кода, где вы уверены, что логическая проблема, а не входные данные, является основной причиной.
Если вы ожидаете, что имя файла в вашем, например, консольном приложении будет входным, и пользователь забыл указать имя файла в командной строке, не стоит приветствовать пользователя с ContracException.
- Сообщение об ошибке может сбить пользователя с толку.
- Вы не можете отличить ошибки программирования от проблем с проверкой пользовательского ввода.
- Вы не можете перехватить какое-либо конкретное ContractException, поскольку тип исключения является внутренним.
Смотрите документацию пользователя.
7.6 ContractException Тип ContractException не является общедоступным типом и передается в виде вложенного частного типа в каждую сборку, для которой включена проверка контракта во время выполнения. Таким образом, невозможно написать обработчики перехвата, перехватывающие только ContractException . Таким образом, исключения из контракта могут обрабатываться только как часть общего исключения. Логическое обоснование такой конструкции заключается в том, что программы не должны содержать логику управления, которая зависит от сбоев контракта, так же как программы не должны перехватывать ArgumentNullException или аналогичные исключения проверки.