13. Контракты – это общее
понятие, которое покрывает
многие известные ОО
принципы
14. Принцип замещения Лисков
...если для каждого объекта o1 типа S
существует объект o2 типа T такой, что для
всех программ P, определенных в терминах T,
поведение P не изменяется при замене o2 на o1,
то S является подтипом (subtype) для T.
29. Code Contracts
• Частичная поддержка в .NET 4.0
• Устанавливается отдельно:
• Статический анализатор
• Rewriter
• Генератор документации
30. Вернемся к методу 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!");
}
}
33. Альтернативная проверка
предусловий
public class SimpleClass
{
public int Foo(string s)
{
if (s == null)
throw new ArgumentNullException("s");
Contract.EndContractBlock();
return s.Length;
}
}
34. Альтернативная проверка
предусловий
public static class Guard
{
[ContractArgumentValidatorAttribute]
public static void IsNotNull<T>(T t) where T : class
{
if (t == null)
throw new ArgumentNullException("t");
Contract.EndContractBlock();
}
}
35. Ограничения DbC
• Аккуратнее со статическим
анализатором!
• Не переусердствуйте в
формализации
• Частичная поддержка Code
Contracts в .NET Framework
37. Дополнительные материалы
• Бертран Мейер, “Объектно-ориентированное конструирование
программных систем”
• С. Тепляков, “Проектирование по контракту”, RSDN Magazine #1-
2010
• Programming Stuff. “Альтернативная проверка предусловий в Code
Contracts”
• Programming Stuff. “Принцип замещения Лисков и контракты”
• Programming Stuff. “Принцип самурая”
• Programming Stuff. “Как не надо писать код”
• Александр Бындю. “Дополнение к LSP”
38. Спасибо за внимание
• Сергей Тепляков, Visual C# MVP
• .NET Architect at Luxoft
• Sergey.Teplyakov@gmail.com
• http://sergeyteplyakov.blogspot.com/
Editor's Notes
Такие слова, как «формализация» или «спецификация» чужды и страшны большинству разработчиков. Сразу же возникает вопрос: а стоит ли затевать весь этот сыр-бор ради этого? Чем не подходят старые, проверенные временем практики, без всяких там контрактов?
А что если описать отношения между классом (или интерфейсом) и его клиентами более формальным образом.Например, можно сказать, что я сделаю свою работу, но только в том случае, если свою работу сделает вызывающий код.Таким образом, мы четко разделим отношения класса и его клиенты; каждый из них будет точно знать, на что рассчитывать от другой стороны и не будет перепроверять это по десять раз.Кстати, обратите внимание, что я не говорю о тотальной формализации отношений, зачастую достаточно разделить эти обязанности в вашей голове, чтобы такое разделение нашло отражение в вашем коде и дизайне.Но прежде чем переходить к способам разделения ответственностей, давайте рассмотрим еще одну важную характеристику.Я думаю, что многие разработчики спорят друг с другом во время код или дизайн ревью (или с представителями отдела качества) о том, содержит ли баг некоторый фрагмент кода или нет.
Сейчас существует огромное множество различных паттернов, принципов, идиом, которые должны помочь в создании хорошего дизайна. Я ничего не имею, например, против принципов SOLID, но у меня есть совет, как их лучше запомнить и, главное, как ими лучше пользоваться на практике.На самом деле, контрактное программирование (прошу, не путайте с конкретными библиотеками, типа Code Contracts) – это отличный инструмент в борьбе за хороший дизайн.Для начала, давайте рассмотрим один из SOLID принципов: принцип замещения Лисков. Именно на нем строится очень важный аспект любой ОО модели, поскольку он лежит в основе полиморфного поведения.Может стоит сказать о том, что в самой навороченной книге по ООП – в книге Бертрана Мейера описано очень мало разных принципов. Из известных есть только Open Closed.