4-я конференция .NET разработчиков
28 апреля 2012



   Проектирование по контракту
                Сергей Тепляков, Visual C# MVP
                    .NET Architect at Luxoft
                 SergeyTeplyakov.blogspot.com
Контракты




            http://www.flickr.com/photos/lofink/4501610335/
О чем поговорим?
• Базовые понятия контрактного
  программирования
• Практические аспекты
• Ограничения контрактов
Определение
Проектирование по контракту
(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
  элемента?
• Или не добавлять ни одного?
Правила наследования
• Наследник может
 • ослабевать предусловие
 • усиливать постусловие
• Инварианты суммируются
Отношение между типами
Ковариантность по типу
возвращаемого значения
Другие примеры
• .NET/C#
  • Ковариантность массивов в .NET
  • Ковариантность/контравариантность
    делегатов и интерфейсов
• Java/C++
  • Ковариантность исключений
  • Ковариантность возвращаемых типов
Контракты vs Защитное
  программирование


    Проверка    Проверка при
предусловий     каждом
 (2 открытых    обращении к
      метода)   полю (27 мест!)
Code Contracts
• Частичная поддержка в .NET 4.0
• Устанавливается отдельно:
  • Статический анализатор
  • Rewriter
  • Генератор документации
Утверждения и входные данные
Ограничения DbC
• Аккуратнее со статическим
  анализатором!
• Не переусердствуйте в
  формализации
• Частичная поддержка Code Contracts
  в .NET Framework
Важнейшие принципы DbC
•   Разделение ответственности
•   Упрощение обязанностей
•   Обобщение существующих понятий
•   Формализация отношений
Дополнительные материалы
• Бертран Мейер, “Объектно-ориентированное конструирование
  программных систем”
• С. Тепляков, “Проектирование по контракту”, RSDN Magazine #1-2010
• Programming Stuff. “Альтернативная проверка предусловий в Code
  Contracts”
• Programming Stuff. “Принцип замещения Лисков и контракты”
• Programming Stuff. “Как не надо писать код”
• Александр Бындю. “Дополнение к LSP”
Спасибо за внимание

  Сергей Тепляков, Visual C# MVP
       .NET Architect at Luxoft
    Sergey.Teplyakov@gmail.com
http://sergeyteplyakov.blogspot.com/

Design by Contract basics

Editor's Notes

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