Подтвердить что ты не робот

Проектирование по контракту и разработкам

Я работаю над улучшением процесса разработки нашей группы, и я рассматриваю, как лучше всего реализовать проект по контракту с тестовым развитием. Кажется, что у двух методов много перекрытий, и мне было интересно, есть ли у кого-нибудь представление о следующих (связанных) вопросах:

  • Разве это не против принципа DRY иметь TDD и DbC, если вы не используете какой-то генератор кода для генерации модульных тестов на основе контрактов? В противном случае вы должны поддерживать контракт в двух местах (тест и сам контракт), или я что-то упускаю?
  • В какой степени TDD делает DbC избыточным? Если я достаточно хорошо пишу тесты, они не эквивалентны написанию контракта? Получаю ли я только дополнительную выгоду, если я выполняю контракт во время выполнения, а также через тесты?
  • Значительно проще/гибче использовать TDD, а не TDD с DbC?

Основным вопросом этих вопросов является этот более общий вопрос: Если мы уже делаем TDD должным образом, получим ли мы существенную выгоду для накладных расходов, если мы также используем DbC?

Несколько деталей, хотя я думаю, что вопрос в основном зависит от языка:

  • Наша команда очень маленькая, и 10 программистов.
  • В основном мы используем Perl.
4b9b3361

Ответ 1

Обратите внимание на различия.

Дизайн, основанный на контракте. Контрактный дизайн.

Разработка, основанная на тестировании. Разработка, связанная с тестированием.

Они связаны тем, что предшествуют другому. Они описывают программное обеспечение на разных уровнях абстракции.

Вы отбрасываете дизайн, когда идете на реализацию? Считаете ли вы, что проектный документ является нарушением СУХОЙ? Поддерживаете ли вы контракт и код отдельно?

Программное обеспечение - это одна реализация контракта. Тесты - это другое. Руководство пользователя является третьим. Руководство по эксплуатации - четвертое. Процедуры резервного копирования и восстановления базы данных являются частью реализации контракта.

Я не вижу никаких накладных расходов от Design by Contract.

  • Если вы уже делаете дизайн, вы меняете формат с слишком большого количества слов на нужные слова, чтобы наметить договорные отношения.

  • Если вы не занимаетесь дизайном, то заключение контракта устранит проблемы, уменьшит стоимость и сложность.

Я не вижу потери гибкости.

  • начните с контракта,

  • затем

    а. писать тесты и

    б. написать код.

Посмотрите, как две операции по развитию существенно переплетаются и оба происходят из договора.

Ответ 2

Я думаю, что существует дублирование между DbC и TDD, однако я не думаю, что есть дублированная работа: введение DbC, вероятно, приведет к сокращению тестовых случаев.

Позвольте мне объяснить.

В TDD тесты на самом деле не тесты. Это поведенческие характеристики. Тем не менее, они также являются инструментами проектирования: сначала написав тест, вы используете внешний API вашего объекта под тестом - который вы еще не написали - так же, как и пользователь. Таким образом, вы создаете API таким образом, который имеет смысл для пользователя, а не таким образом, который облегчает вам реализацию. Что-то вроде queue.full? вместо queue.num_entries == queue.size.

Эта вторая часть не может быть заменена Контрактами.

Первая часть может быть частично заменена контрактами, по крайней мере для модульных тестов. Тесты TDD служат характеристиками поведения, как для других разработчиков (модульные тесты), так и для экспертов домена (приемочные тесты). Контракты также определяют поведение, для других разработчиков, для экспертов домена, а также для компилятора и библиотеки времени выполнения.

Но контракты имеют фиксированную детализацию: у вас есть метод pre- и postconditions, инварианты объектов, контракты модулей и т.д. Возможно, варианты цикла и инварианты. Единичные тесты, однако, тестовые единицы поведения. Они могут быть меньше метода или состоять из нескольких методов. Это не то, что вы можете делать с контрактами. И для "большой картины" вам все равно нужны интеграционные тесты, функциональные тесты и приемочные испытания.

И есть еще одна важная часть TDD, которую DbC не покрывает: средний D. В TDD тесты приводят ваш процесс разработки: вы никогда не пишете одну строку кода реализации, если у вас нет теста с ошибкой, вы никогда не пишете одну строку тестового кода, за исключением тех случаев, когда все ваши тесты проходят, вы пишете минимальный код реализации, чтобы пройти тесты, вы только пишете минимальное количество тестового кода для создания теста с ошибкой.

В заключение: используйте тесты для разработки "потока", "ощущения" API. Используйте контракты для разработки, ну, контракта API. Используйте тесты, чтобы обеспечить "ритм" для процесса разработки.

Что-то вроде этого:

  • Напишите приемочный тест для функции
  • Напишите unit test для устройства, которое реализует часть этой функции
  • Используя подпись метода, разработанную на шаге 2, напишите прототип метода
  • Добавить постусловие
  • Добавить предварительное условие
  • Реализация тела метода
  • Если приемочный тест проходит, перейти 1, иначе перейти 2

Если вы хотите узнать, что написал Бертран Мейер, изобретатель Design by Contract, думающий о объединении TDD и DbC, есть хорошая статья его группы, называемая Контрактный дизайн = Разработка, основанная на тестах - Написание тестовых случаев. Основная предпосылка заключается в том, что контракты предоставляют абстрактное представление обо всех возможных случаях, тогда как тестовые случаи проверяют только конкретные случаи. Поэтому из контрактов может автоматически генерироваться подходящая тестовая жгут.

Ответ 3

Я бы добавил:

API - это контракт для программистов, определение пользовательского интерфейса - это контракт с клиентами, протокол - это контракт на взаимодействие клиент-сервер. Сначала возьмите их, затем вы сможете использовать параллельные дорожки разработки и не потеряться в сорняках. Да, периодически проверяйте, чтобы убедиться, что требования выполнены, но никогда не начинайте новый трек без контракта. И "контракт" - сильное слово: после его развертывания он никогда не должен меняться. Вы должны включать управление версиями и интроспекцию с помощью get-go, изменения в контракте выполняются только наборами расширений, номера версий изменяются вместе с ними, а затем вы можете делать такие вещи, как грациозное ухудшение при работе со смешанными или старыми установками.

Я усвоил этот урок сложным путем, с большим проектом, который забрели в никогда не существовавшие земли, а затем применил его в правильном направлении позже, когда серьезно под пистолетом, выживания компании, короткой временной шкалы. Мы определили протокол, определили и написали набор эмуляций протоколов для каждой стороны транзакций (в основном, консервированные генераторы сообщений и принятые средства проверки сообщений, одно очко для двухмозгового кодирования), а затем раздельно, чтобы отдельно писать сервер и клиентские концы приложения. Мы перестроили ночь шоу, и он просто сработал. Требования, дизайн, контракт, тест, код, интеграция. В этой последовательности. Повторяйте до запекания.

Я немного увлекаюсь дизайном TLA. Как и в случае с шаблонами, рецепты, совместимые с buzz-word, являются хорошим руководством, но, по моему опыту, нет такой вещи, как процедура проектирования или управления проектами одного размера. Если вы делаете вещи точно по книге (tm), то, если это не договор DOD с процедурными требованиями DOD, вы, вероятно, столкнетесь с проблемой где-то на этом пути. Прочитайте Книгу (ы), да, но обязательно поймите их, а затем учтите также и сторону людей вашей команды. Правила, которые выполняются только в Книге, не будут применяться равномерно - даже если они будут принудительно применены к инструменту, могут быть исключения (например, svn комментарии оставлены пустыми или загадочными). Процедуры имеют тенденцию следовать, когда цепочка инструментов не только обеспечивает их соблюдение, но и делает их проще, чем любые возможные короткие сокращения. Поверьте мне, когда ситуация становится жесткой, вы найдете краткие сокращения, и вы можете не знать о тех, которые привыкли в 3 часа ночи, пока не стало слишком поздно.

Ответ 4

Вы также можете использовать исполняемые приемочные тесты, которые написаны на языке домена контракта. Это может быть не фактический "контракт", а на полпути между юнит-тестами и контрактом.

Я бы пересчитал, используя Ruby Cucumber http://github.com/aslakhellesoy/cucumber

Но так как вы магазин Perl, то, возможно, вы можете использовать мою небольшую попытку p5-огурца. http://github.com/kesor/p5-cucumber

Ответ 5

Microsoft выполнила работу по автоматической генерации модульных тестов на основе кодовых контрактов и параметризованных unit test. Например. в контракте указано, что счет должен быть увеличен на единицу, когда элемент добавляется в коллекцию, а параметризованный unit test говорит, как добавить элементы "n" в коллекцию. Затем Pex попытается создать unit test, который докажет, что контракт нарушен. Смотрите обзор для обзора.

Если работает, ваш unit test должен быть написан только для одного примера каждой вещи, которую вы пытаетесь протестировать, и PEX сможет затем обработать элементы данных, которые будут разбиты тест.

Ответ 7

Когда вы используете TDD для реализации нового метода, вам нужен какой-то ввод: вам нужно знать утверждения для проверки ваших тестов. Конструкция по контракту дает вам эти утверждения: это пост-условия и инварианты метода.

Ответ 8

Я нашел DbC очень удобным для ускорения цикла red-green-refactor, потому что он помогает идентифицировать модульные тесты для начала. С DbC я начинаю думать о предварительных условиях, что должен быть обработан объект TDD-ed, и каждое предварительное условие может представлять неудачный unit test запуск цикла red-green-refactor. В какой-то момент я переключаюсь на запуск цикла с неудачной unit test для пост-состояния, а затем просто продолжаю поток TDD. Я пробовал этот подход с новичками в TDD, и он действительно работает в кикстарте мышления TDD.

В целом, подумайте о DbC как эффективном способе определения ключевых тестов поведения. DbC помогает при анализе входов (предварительных условий) и выходов (пост-условий), которые являются двумя вещами, которые нам необходимы для управления (входами) и наблюдениями (выходами) для записи тестируемого программного обеспечения (аналогичная цель TDD).