Net, контракти коду

Проектування за контрактом - ідея, запозичена з мови програмування Eiffel. В простір імен System.Diagnostics.Contracts версії .NET 4 включені класи для статичних перевірок коду і перевірок часу виконання, які можуть застосовуватися всіма мовами .NET.

За допомогою цієї функціональності можна визначати передумови, постумови і інваріанти всередині методу. Передумови перераховують вимоги, яким повинні задовольняти параметри, постумови визначають вимоги до повертається даними, а інваріанти - вимоги до змінних всередині самого методу.

Інформація про контракт може бути скомпільована в оцінний і робочий код. Можна також визначити окрему збірку контракту, і багато перевірки також можуть бути виконані статично, без запуску програми.

Контракти допускається визначати на інтерфейсах; це змусить реалізації інтерфейсів задовольняти вимоги цих контрактів. Інструменти для роботи з контрактами можуть переписати збірку, запровадивши перевірки контракту в код для їх виконання під час функціонування програми, перевіряти контракти під час компіляції і додавати інформацію про контракти в генерується документацію XML.

Net, контракти коду

Контракти коду визначаються класом Contract. Всі вимоги контрактів, які задаються в методі, незалежно від того, є вони передумовою або постусловіем, повинні поміщатися в початок методу. Можна також призначити глобальний обробник події ContractFailed, який буде викликатися при кожному порушенні контракту під час виконання. Виклик SetHandled () з параметром е типу ContractFailedEventArgs припинить стандартну поведінку при збої з генерацією винятку.

Передумови (Requires)

Передумови перевіряють параметри, передані в метод Requires () і Requires() - це передумови, які можуть бути визначені за допомогою класу Contract. Методу Requires () має передаватися булевское значення, а також необов'язковий ланцюжок повідомлення у другому параметрі, яка відображається в разі, якщо умова не виконана. У наступному прикладі потрібно, щоб значення аргументу min було менше або дорівнює значенню аргументу max:

Показаний нижче контракт генерує виняток ArgumentNullException, якщо аргумент o дорівнює null. Виняток не генерується, якщо обробник події ContractFailed встановлює подія в handled (оброблено). Крім того, якщо у вікні властивостей проекту прапорець Assert on Contract Failure (Затвердження при порушенні контракту) відзначений, то замість генерації певного виключення викликається метод Trace.Assert () для припинення роботи програми:

виклик Requires() НЕ анотований атрибутом [Conditional ( "CONTRACTS_FULL")], і також не має умови для символу DEBUG, тому дана перевірка часу виконання здійснюється в будь-якому випадку. Requires() Генерує певний виняток, якщо умова не виконана.

У величезній масі успадкованого коду аргументи часто перевіряються операторами if з генерацією винятку в разі порушення заданого умови. Завдяки контрактам коду, немає необхідності переписувати верифікацію. Досить лише додати один рядок коду:

EndContractBlock () визначає, що попередній код повинен бути оброблений як контракт. Якщо використовуються інші оператори контракту, то в EndContractBlock () немає необхідності.

Для перевірки колекцій, які використовуються в якості аргументів, в класі Contract передбачені методи Exists () і ForAll (). Метод ForAll () перевіряє кожен елемент в колекції на предмет відповідності умові. У наступному прикладі проводиться перевірка, що кожен елемент колекції має значення менше 12. За допомогою методу Exists () можна перевірити, чи відповідає умові хоча б один елемент колекції:

Обидва методи, Exists () і ForAll (), мають перевантаження, якій замість IEnumerable можна передати два цілих числа - fromInclusive і toExclusive. Діапазон чисел (виключаючи toExclusive) передається делегату Predicate, визначеному в третьому параметрі. Exists () і ForAll () можуть використовуватися з передумовою, умовою поста, а також інваріантами.

Післяумови (Ensures)

Визначення постусловіем гарантує дотримання певних умов щодо поділюваних даних і значень. І хоча вони визначають деякі гарантії про що повертаються значеннях, проте, вони повинні записуватися на початку методу; всі вимоги контракту повинні визначатися на початку методу.

Ensures () і EnsuresOnThrow() - це постумови. Наступний контракт гарантує, що значення змінної sharedState буде менше 6 в кінці методу. До цього значення може змінюватися:

За допомогою EnsuresOnThrow() Гарантується, що розділене стан задовольнить умові в разі генерації зазначеного винятку.

Для гарантування повертається до контракту Ensures () може використовуватися спеціальне значення Result. Тут результат типу int також визначено узагальненим типом T для методу Result (). Контракт Ensures () гарантує, що повертається значення буде менше 6.

Можна також порівнювати значення зі старим значенням. Це робиться за допомогою методу 01dValue(). який повертає початкове значення переданої методу змінної.

інваріанти

Інваріанти визначають контракти для змінних протягом часу життя методу. Contract.Requires () визначає вхідні вимоги, Contract.Ensures () - вимоги на кінець методу. Contract.Invariant () визначає умови, яких слід дотримуватися протягом часу життя методу:

Схожі статті