SlideShare a Scribd company logo
1 of 38
Проектирование по
    контракту
      Сергей Тепляков, 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
     • Sergey.Teplyakov@gmail.com
• http://sergeyteplyakov.blogspot.com/

More Related Content

What's hot

C++ осень 2013 лекция 8
C++ осень 2013 лекция 8C++ осень 2013 лекция 8
C++ осень 2013 лекция 8Technopark
 
Dependency Injection в Java на примере эволюции Spring — Guice — CDI/Weld
Dependency Injection в Java на примере эволюции Spring — Guice — CDI/WeldDependency Injection в Java на примере эволюции Spring — Guice — CDI/Weld
Dependency Injection в Java на примере эволюции Spring — Guice — CDI/WeldCUSTIS
 
C++ осень 2013 лекция 7
C++ осень 2013 лекция 7C++ осень 2013 лекция 7
C++ осень 2013 лекция 7Technopark
 
C++ осень 2013 лекция 4
C++ осень 2013 лекция 4C++ осень 2013 лекция 4
C++ осень 2013 лекция 4Technopark
 
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияЕвгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияPlatonov Sergey
 
C# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущееC# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущееGetDev.NET
 

What's hot (6)

C++ осень 2013 лекция 8
C++ осень 2013 лекция 8C++ осень 2013 лекция 8
C++ осень 2013 лекция 8
 
Dependency Injection в Java на примере эволюции Spring — Guice — CDI/Weld
Dependency Injection в Java на примере эволюции Spring — Guice — CDI/WeldDependency Injection в Java на примере эволюции Spring — Guice — CDI/Weld
Dependency Injection в Java на примере эволюции Spring — Guice — CDI/Weld
 
C++ осень 2013 лекция 7
C++ осень 2013 лекция 7C++ осень 2013 лекция 7
C++ осень 2013 лекция 7
 
C++ осень 2013 лекция 4
C++ осень 2013 лекция 4C++ осень 2013 лекция 4
C++ осень 2013 лекция 4
 
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализацияЕвгений Зуев, С++ в России: Стандарт языка и его реализация
Евгений Зуев, С++ в России: Стандарт языка и его реализация
 
C# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущееC# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущее
 

Similar to Design by Contract

Проектирование по контракту
Проектирование по контрактуПроектирование по контракту
Проектирование по контрактуAlexander Byndyu
 
Dynamic Language Runtime
Dynamic Language RuntimeDynamic Language Runtime
Dynamic Language RuntimeSQALab
 
Evgeny Rybak Presentation
Evgeny Rybak PresentationEvgeny Rybak Presentation
Evgeny Rybak Presentationsef2009
 
По ту сторону ООП: PEAK-Rules и PyProtocols
По ту сторону ООП: PEAK-Rules и PyProtocolsПо ту сторону ООП: PEAK-Rules и PyProtocols
По ту сторону ООП: PEAK-Rules и PyProtocolsSergey Schetinin
 
Code Contracts
Code ContractsCode Contracts
Code ContractsDima Pasko
 
Никита Галкин "Testing in Node.js World"
Никита Галкин "Testing in Node.js World"Никита Галкин "Testing in Node.js World"
Никита Галкин "Testing in Node.js World"Fwdays
 
Как пройти собеседование и получить первую работу на Swift
Как пройти собеседование и получить первую работу на SwiftКак пройти собеседование и получить первую работу на Swift
Как пройти собеседование и получить первую работу на SwiftAnton Loginov
 
Dependency injection
Dependency injectionDependency injection
Dependency injectionGetDev.NET
 
Code Contracts ABC 16.04.2011
Code Contracts ABC 16.04.2011Code Contracts ABC 16.04.2011
Code Contracts ABC 16.04.2011Dmytro Mindra
 
Node.js for enterprise 2021 - JavaScript Fwdays 3
Node.js for enterprise 2021 - JavaScript Fwdays 3Node.js for enterprise 2021 - JavaScript Fwdays 3
Node.js for enterprise 2021 - JavaScript Fwdays 3Timur Shemsedinov
 
C# Desktop. Занятие 16.
C# Desktop. Занятие 16.C# Desktop. Занятие 16.
C# Desktop. Занятие 16.Igor Shkulipa
 
Архитектура в Agile: слабая связность
Архитектура в Agile: слабая связностьАрхитектура в Agile: слабая связность
Архитектура в Agile: слабая связностьAndrey Bibichev
 
Миграция кода с Magento 1 на Magento 2
Миграция кода с Magento 1 на Magento 2Миграция кода с Magento 1 на Magento 2
Миграция кода с Magento 1 на Magento 2Elogic Magento Development
 
Как это работает: DLR
Как это работает: DLRКак это работает: DLR
Как это работает: DLRMikhail Shcherbakov
 
Roslyn API : SyntaxTree vs CodeDom, SemanticModel vs Reflection
Roslyn API: SyntaxTree vs CodeDom, SemanticModel vs ReflectionRoslyn API: SyntaxTree vs CodeDom, SemanticModel vs Reflection
Roslyn API : SyntaxTree vs CodeDom, SemanticModel vs ReflectionDenis Tsvettsih
 
Игорь Кашкута
Игорь КашкутаИгорь Кашкута
Игорь КашкутаCodeFest
 
разработка бизнес приложений (8)
разработка бизнес приложений (8)разработка бизнес приложений (8)
разработка бизнес приложений (8)Alexander Gornik
 
Cpp0x Introduction
Cpp0x IntroductionCpp0x Introduction
Cpp0x IntroductionFedor Vompe
 

Similar to Design by Contract (20)

Проектирование по контракту
Проектирование по контрактуПроектирование по контракту
Проектирование по контракту
 
Design by Contract basics
Design by Contract basicsDesign by Contract basics
Design by Contract basics
 
Dynamic Language Runtime
Dynamic Language RuntimeDynamic Language Runtime
Dynamic Language Runtime
 
Evgeny Rybak Presentation
Evgeny Rybak PresentationEvgeny Rybak Presentation
Evgeny Rybak Presentation
 
По ту сторону ООП: PEAK-Rules и PyProtocols
По ту сторону ООП: PEAK-Rules и PyProtocolsПо ту сторону ООП: PEAK-Rules и PyProtocols
По ту сторону ООП: PEAK-Rules и PyProtocols
 
Code Contracts
Code ContractsCode Contracts
Code Contracts
 
Никита Галкин "Testing in Node.js World"
Никита Галкин "Testing in Node.js World"Никита Галкин "Testing in Node.js World"
Никита Галкин "Testing in Node.js World"
 
Как пройти собеседование и получить первую работу на Swift
Как пройти собеседование и получить первую работу на SwiftКак пройти собеседование и получить первую работу на Swift
Как пройти собеседование и получить первую работу на Swift
 
Dependency injection
Dependency injectionDependency injection
Dependency injection
 
Code Contracts ABC 16.04.2011
Code Contracts ABC 16.04.2011Code Contracts ABC 16.04.2011
Code Contracts ABC 16.04.2011
 
Node.js for enterprise 2021 - JavaScript Fwdays 3
Node.js for enterprise 2021 - JavaScript Fwdays 3Node.js for enterprise 2021 - JavaScript Fwdays 3
Node.js for enterprise 2021 - JavaScript Fwdays 3
 
C# Desktop. Занятие 16.
C# Desktop. Занятие 16.C# Desktop. Занятие 16.
C# Desktop. Занятие 16.
 
Архитектура в Agile: слабая связность
Архитектура в Agile: слабая связностьАрхитектура в Agile: слабая связность
Архитектура в Agile: слабая связность
 
Миграция кода с Magento 1 на Magento 2
Миграция кода с Magento 1 на Magento 2Миграция кода с Magento 1 на Magento 2
Миграция кода с Magento 1 на Magento 2
 
Как это работает: DLR
Как это работает: DLRКак это работает: DLR
Как это работает: DLR
 
Roslyn API : SyntaxTree vs CodeDom, SemanticModel vs Reflection
Roslyn API: SyntaxTree vs CodeDom, SemanticModel vs ReflectionRoslyn API: SyntaxTree vs CodeDom, SemanticModel vs Reflection
Roslyn API : SyntaxTree vs CodeDom, SemanticModel vs Reflection
 
Python и Cython
Python и CythonPython и Cython
Python и Cython
 
Игорь Кашкута
Игорь КашкутаИгорь Кашкута
Игорь Кашкута
 
разработка бизнес приложений (8)
разработка бизнес приложений (8)разработка бизнес приложений (8)
разработка бизнес приложений (8)
 
Cpp0x Introduction
Cpp0x IntroductionCpp0x Introduction
Cpp0x Introduction
 

More from Kiev ALT.NET

Micro-ORM Introduction - Don't overcomplicate
Micro-ORM Introduction - Don't overcomplicateMicro-ORM Introduction - Don't overcomplicate
Micro-ORM Introduction - Don't overcomplicateKiev ALT.NET
 
Reactive Extensions
Reactive ExtensionsReactive Extensions
Reactive ExtensionsKiev ALT.NET
 
Continuous Integration (CI)
Continuous Integration (CI)Continuous Integration (CI)
Continuous Integration (CI)Kiev ALT.NET
 
WebSharper - веб-программирование без слёз
WebSharper - веб-программирование без слёзWebSharper - веб-программирование без слёз
WebSharper - веб-программирование без слёзKiev ALT.NET
 
F# - функциональный язык «новой» волны
F# - функциональный  язык «новой» волныF# - функциональный  язык «новой» волны
F# - функциональный язык «новой» волныKiev ALT.NET
 
Caliburn Micro Overview
Caliburn Micro OverviewCaliburn Micro Overview
Caliburn Micro OverviewKiev ALT.NET
 
Введение в MVVM
Введение в MVVMВведение в MVVM
Введение в MVVMKiev ALT.NET
 
Command-Query Responsibility Segregation: теория и практика
Command-Query Responsibility Segregation: теория и практикаCommand-Query Responsibility Segregation: теория и практика
Command-Query Responsibility Segregation: теория и практикаKiev ALT.NET
 

More from Kiev ALT.NET (16)

CQRS EventStore
CQRS EventStoreCQRS EventStore
CQRS EventStore
 
Micro-ORM Introduction - Don't overcomplicate
Micro-ORM Introduction - Don't overcomplicateMicro-ORM Introduction - Don't overcomplicate
Micro-ORM Introduction - Don't overcomplicate
 
Async
AsyncAsync
Async
 
Linq providers
Linq providersLinq providers
Linq providers
 
Reactive Extensions
Reactive ExtensionsReactive Extensions
Reactive Extensions
 
NoSql, MongoDb
NoSql, MongoDbNoSql, MongoDb
NoSql, MongoDb
 
CouchDb
CouchDbCouchDb
CouchDb
 
Orchard
OrchardOrchard
Orchard
 
Mercurial
MercurialMercurial
Mercurial
 
CI via TFS
CI via TFSCI via TFS
CI via TFS
 
Continuous Integration (CI)
Continuous Integration (CI)Continuous Integration (CI)
Continuous Integration (CI)
 
WebSharper - веб-программирование без слёз
WebSharper - веб-программирование без слёзWebSharper - веб-программирование без слёз
WebSharper - веб-программирование без слёз
 
F# - функциональный язык «новой» волны
F# - функциональный  язык «новой» волныF# - функциональный  язык «новой» волны
F# - функциональный язык «новой» волны
 
Caliburn Micro Overview
Caliburn Micro OverviewCaliburn Micro Overview
Caliburn Micro Overview
 
Введение в MVVM
Введение в MVVMВведение в MVVM
Введение в MVVM
 
Command-Query Responsibility Segregation: теория и практика
Command-Query Responsibility Segregation: теория и практикаCommand-Query Responsibility Segregation: теория и практика
Command-Query Responsibility Segregation: теория и практика
 

Design by Contract

Editor's Notes

  1. Такие слова, как «формализация» или «спецификация» чужды и страшны большинству разработчиков. Сразу же возникает вопрос: а стоит ли затевать весь этот сыр-бор ради этого? Чем не подходят старые, проверенные временем практики, без всяких там контрактов?
  2. А что если описать отношения между классом (или интерфейсом) и его клиентами более формальным образом.Например, можно сказать, что я сделаю свою работу, но только в том случае, если свою работу сделает вызывающий код.Таким образом, мы четко разделим отношения класса и его клиенты; каждый из них будет точно знать, на что рассчитывать от другой стороны и не будет перепроверять это по десять раз.Кстати, обратите внимание, что я не говорю о тотальной формализации отношений, зачастую достаточно разделить эти обязанности в вашей голове, чтобы такое разделение нашло отражение в вашем коде и дизайне.Но прежде чем переходить к способам разделения ответственностей, давайте рассмотрим еще одну важную характеристику.Я думаю, что многие разработчики спорят друг с другом во время код или дизайн ревью (или с представителями отдела качества) о том, содержит ли баг некоторый фрагмент кода или нет.
  3. Сейчас существует огромное множество различных паттернов, принципов, идиом, которые должны помочь в создании хорошего дизайна. Я ничего не имею, например, против принципов SOLID, но у меня есть совет, как их лучше запомнить и, главное, как ими лучше пользоваться на практике.На самом деле, контрактное программирование (прошу, не путайте с конкретными библиотеками, типа Code Contracts) – это отличный инструмент в борьбе за хороший дизайн.Для начала, давайте рассмотрим один из SOLID принципов: принцип замещения Лисков. Именно на нем строится очень важный аспект любой ОО модели, поскольку он лежит в основе полиморфного поведения.Может стоит сказать о том, что в самой навороченной книге по ООП – в книге Бертрана Мейера описано очень мало разных принципов. Из известных есть только Open Closed.