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

Библиотека для облегчения использования принципа "дизайн по контракту"

Есть ли какая-либо библиотека, которая помогает реализовать проект по принципу контракта в приложении С++?

В частности, я ищу библиотеку, которая обеспечивает использование принципа, что-то вроде this.

4b9b3361

Ответ 1

Я следил за учениями следующих статей:

  • Исключение или ошибка? (Miro Samek, Журнал пользователей C/С++, 2003)
  • Простая поддержка дизайна по контракту в С++ (Pedro Guerreiro, TOOLS, 2001).

То, что я в конечном счете применял, было в значительной степени подходом Samek. Простое создание макросов для REQUIRE, ENSURE, CHECK и INVARIANT (на основе существующего макроса assert) было очень полезным. Конечно, это не так хорошо, как поддержка родного языка, но в любом случае, это позволяет вам получить большую часть практической ценности от этой техники.

Что касается библиотек, я не думаю, что он платит их, потому что одним из важных значений механизма утверждения является его простота.

За разницу между кодом отладки и производством см. Когда должны оставаться утверждения в производственном коде?.

Ответ 2

Простейшая?

Утвердить утверждения в начале вашей функции, чтобы проверить ваши требования. Утвердить утверждения в конце вашей функции, чтобы проверить ваши результаты.

Да, это грубо, его не большая система, но его простота делает его универсальным и портативным.

Ответ 3

Некоторые шаблоны проектирования, такие как не виртуальный интерфейс, делают естественным писать пре/пост-условия для данного метода:

#include <cassert>

class Car {
    virtual bool engine_running_impl() = 0;
    virtual void stop_impl() = 0;
    virtual void start_impl() = 0;

    public:
    bool engine_running() {
        return engine_running_impl();
    }

    void stop() {
        assert(engine_running());
        stop_impl();
        assert(! engine_running());
    }

    void start()
    {
        assert(! engine_running());
        start_impl();
        assert(engine_running());
    }
}


class CarImpl : public Car {
    bool engine_running_impl() {
        /* ... */
    }

    void stop_impl() {
        /* ... */
    }

    void start_impl() {
        /* ... */
    }
}

Ответ 4

Если вы не против использования функций С++ 0x, вы можете реализовать предварительные условия и постусловия с помощью lambdas и RAII.

Простой пример постусловия:

struct __call_on_destructor {
  std::tr1::function<void()> _function;
  template<class Func> inline __call_on_destructor(Func func) {
      _function = func;
  }
  inline ~__call_on_destructor() {
      _function();
  }
};

#define on_scope_exit(function) \
  __call_on_destructor PP_UNIQUE_LABEL(on_exit) (function)

#define ensures(expression) \
  on_scope_exit([&] () { assert(expression); })

Аналогично, вы можете реализовать предварительные условия и инварианты. Код был взят из чрезвычайно простой С++ 0x Contracts library.

Ответ 5

Попробуйте следующее: Contract ++. Он был принят к Boost (но еще не доставляется).

Ответ 6

У меня есть заголовок litle С++ с требованиями, страхованием и инвариантами. Он имеет менее 400 мест и должен удовлетворять вашим потребностям. Вы можете найти его под dhc.hpp Он сообщает об ошибках полезным способом и может быть скомпилирован через define.

#include <dbc.hpp>

class InvarTest {
public:
        int a = 0;
        int b = 9;

        INVARIANT_BEGIN
                Inv(RN(0,a,32));
                Inv(RN(0,b,10));
        INVARIANT_END

        inline void changeMethod() {
                Invariant(); // this runs the invariant block at the beginning and end of the method
                a = 33;         
        }
};

int testFunc(int a, double d, int* ip) {
        // RN = a in range 0 to 10, NaN = not a number, NN = not null
        Rqr(RN(0,a,10), NaN(d), RN(0.0,d,1.0), NN(ip));

        // Enr return the passed value
        return Esr(RN(0.0,a+d,20.3));
}

void testFunc2(std::vector<int>& a, std::shared_ptr<int> sp) {
        Rqr( SB(a,0), TE(a.size() % 12 == 0), NN(sp));
}

Ответ 7

Использовать стандартный ASSERT/Q_ASSERT, но остерегайтесь "недействительных" утверждений, особенно если вы оставите такую ​​диагностику во внешнем тестировании (создайте без NDEBUG).

Небольшая история о реализации DBC (с использованием утверждений) в проекте С++ и политике "отладка всегда включена".

Мы использовали стандартные инструменты (ASSERT()/Q_ASSERT()) в качестве реализации DBC, пока мы не достигли следующей ситуации в тестировании интеграции: наша последняя сборка всегда терпела неудачу сразу после запуска. Было не очень профессионально выпускать такую ​​версию (после недели внутренних усилий по обеспечению качества).

Как появилась проблема?

  • Разработчик оставил неправильное утверждение (недопустимое логическое выражение) в исходном коде
  • Во всех наших сборках до выпуска были включены утверждения (для отслеживания ошибок в тестах интеграции)
  • Внутренний QA имеет различные настройки среды, чем тесты интеграции, поэтому "ошибка утверждения" не была видна

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

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

Я нашел, возможно, интересное разрешение на основе С++ для этой проблемы: слабые asserions. Идея не останавливать цельное приложение при неудачном завершении, но записывать stacktrace для последующего анализа и продолжать. Мы можем проверить столько ожиданий, сколько пожелаем, без страха перед сбоем, и мы получим обратную связь (stacktraces) от интеграции. Один прогон процесса может обеспечить множество неудачных утверждений для анализа вместо одного (потому что не вызывается прерывание()).

Реализация этой идеи (с использованием некоторой магии LD_PRELOAD) кратко описана здесь: http://blog.aplikacja.info/2011/10/assert-to-abort-or-not-to-abort-thats-the-question/