Upload
kiev-altnet
View
1.786
Download
2
Embed Size (px)
DESCRIPTION
- Базовые понятия контрактного программирования - Практические аспекты - Библиотека Code Contracts - Ограничения контрактов
Citation preview
Проектирование по контракту
Сергей Тепляков, Visual C# MVP.NET Architect at Luxoft
SergeyTeplyakov.blogspot.com
Agenda
•Базовые понятия контрактного программирования•Практические аспекты•Библиотека Code Contracts•Ограничения контрактов
Определение
Проектирование по контракту (Design by Contract, DbC) – это формализация отношений между программным компонентом и его клиентами
?Анужнолиэто
?Чтоскажете
public interface IRepository{ Customer GetCustomer(string id); void SaveCustomer(Customer c);}
Стандартноерешение
•«Комментарии не лгут»•На крайний случай «Use the Source Luke!»
Давайтедобавимнемного!формальности
ОкорректностиПО
•Код сам по себе, не является корректным или некорректным!•Важна спецификация•«Задокументированный баг – это фича!»
Утверждениявконтрактах•Предусловия•Постусловия•Инвариант класса•Утверждения•Инвариант цикла (Eiffel specific)
Внедрение спецификациивкод
class Repository : IRepository{ public Customer GetCustomer(string id) { Contract.Requires(id != null); Contract.Ensures( Contract.Result<Customer>() != null); }}
Нарушенияутверждений•Нарушение предусловия – «баг» в
клиенте коде•Нарушение постусловия, инварианта
или утверждения – «баг» в сервисе
Инструменты DbC
•Утверждения•Статический анализатор•Документация (DRY)
– Контракты этообщее, понятие которое
покрываетмногие известныеООпринципы
ПринципзамещенияЛисков...если для каждого объекта o1 типа S существует объект o2 типа T такой, что для всех программ P, определенных в терминах T, поведение P не изменяется при замене o2 на o1, то S является подтипом (subtype) для T.
ПринципзамещенияЛисков
Метод Add
• ICollection.Add• IList.Add•Может ли метод добавлять 2 элемента?•Или не добавлять ни одного?
Правиланаследования
•Наследник может•ослабевать предусловие• усиливать постусловие•Инварианты суммируются
Сильныеислабыеусловия•X > 0 (слабее)•X > 5 (сильнее, строже)
Предусловиеинаследование
Отношениемеждутипами
Ковариантностьпо типу возвращаемого
значения
КонтравариантностьAction<in T>static void Foo(object obj) { }
// Контравариантность аргументов: // предусловие делегата Action<object> слабее // предусловия Action<string>, // поскольку typeof(object) > typeof(string) Action<string> action1 = Foo; // ИлиAction<string> action2 = new Action<object>(Foo);
action1("Hello Foo!");
Ковариантность Func<out T>static string Boo() { return "Boo"; }
// Ковариантность возвращаемого значения: // постусловие делегата Func<string> сильнее// постусловия Func<object>, // поскольку typeof(string) < typeof(object) Func<object> func1 = Boo; // Или Func<object> func2 = new Func<string>(Boo);
Ковариантностьисключенийclass Base { public: virtual void Foo() throw(std::exception) {} };
class Derived : public Base {public:/*override*/ void Foo() throw(std::logic_error) {}};
Принципсамурая
Мониторинг утвержденийво время
выполнения•Уровни утверждений•None•Requires•Ensures•Full•Assert on Contract Failures
Утвержденияивнешниеданные
Контракты vs Защитноепрограммирование
Проверка предусловий
(2 открытых метода)
Проверка при каждом обращении к полю (27 мест!)
Code Contracts
•Частичная поддержка в .NET 4.0•Устанавливается отдельно:•Статический анализатор•Rewriter• Генератор документации
Вернемсякметоду Add// From mscorlib.Contracts.dll[ContractClassFor(typeof (ICollection<>))]internal abstract class ICollectionContract<T> : ICollection<T>{ public void Add(T item) { // Исходный контракт Contract.Ensures(Count >= Contract.OldValue<int>(Count), "this.Count >= Contract.OldValue(this.Count)");
// Мы могли бы добавить! Contract.Ensures(Contains(item), "Contains(item) should be true!"); }}
Адаптация существующегокода
•Уже есть класс Guard?•Добавляем атрибут и получаем предусловие!
Code Contracts
•Contract.Requires•Contract.Ensures•Contract.Invariant•Contract.Assert/Assume
Альтернативная проверкапредусловий
public class SimpleClass{ public int Foo(string s) { if (s == null) throw new ArgumentNullException("s"); Contract.EndContractBlock();
return s.Length; }}
Альтернативная проверкапредусловий
public static class Guard{ [ContractArgumentValidatorAttribute] public static void IsNotNull<T>(T t) where T : class { if (t == null) throw new ArgumentNullException("t"); Contract.EndContractBlock(); }}
Ограничения DbC
•Аккуратнее со статическим анализатором!•Не переусердствуйте в формализации•Частичная поддержка Code Contracts в .NET Framework
ВажнейшиепринципыDbC• Разделение ответственности• Упрощение обязанностей•Обобщение существующих понятий•Формализация отношений
Дополнительныематериалы• Бертран Мейер, “Объектно-ориентированное конструирование
программных систем”• С. Тепляков, “Проектирование по контракту”, RSDN Magazine #1-
2010• Programming Stuff. “Альтернативная проверка предусловий в
Code Contracts”• Programming Stuff. “Принцип замещения Лисков и контракты”• Programming Stuff. “Принцип самурая”• Programming Stuff. “Как не надо писать код”• Александр Бындю. “Дополнение к LSP”
Спасибо за внимание
• Сергей Тепляков, Visual C# MVP• .NET Architect at Luxoft
• [email protected]• http://sergeyteplyakov.blogspot.com/