частичный дизайн по контракту с утверждениями - PullRequest
1 голос
/ 26 февраля 2011

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

Мой пример написан на Java, но я полагаю, чтоИдея хороша для многих ОО-языков.

У нас есть такой класс:

class myClass{
    type1 field1;
    type2 field2;

    public myClass(type1 param1){
        //do something
    }

    public type3 method1(type1 param1, type3 param2){
        if (paramsAreNotOk()){
            throw new IllegalArgumentException();
        }
        // do a lot of things
        return //do something
    }
}

Мы расширяем код выше таким образом:

class myClass{
    type1 field1;
    type2 field2;

    public myClass(type1 param1){
        //do something

        assert invariant();
    }

    public type3 method1(final type1 param1, final type3 param2){
        assert invariant();
        myClass old;
        assert ((old = this.clone()) != null)

        if (paramsAreNotOk()){
            throw new IllegalArgumentException();
        }
        //do a lot of things
        type3 res = //do something

        assert method1_post(old, param1, param2, res);
        assert invariant();
        return res;
    }

    protected boolean invariant(){
        // states something about myClass and return a boolean
        // OR
        // uses some assertions on some helping methods
    }

    protected boolean method1_post(myClass old, type1 param1, type3 param2, type3 res){
        // states something about res and about the modifications made on old
        // OR
        // uses some assertions on some helping methods
    }
}

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

Теперь несколько вопросов:
- не мешает ли этот метод выступлениям?Я имею в виду, что даже старые локальные переменные и переменные res удаляются компилятором JIT, если утверждения отключены?
- видите ли вы какие-либо недостатки этого подхода?Почему бы вам не использовать это в своих классах?
- можете ли вы предложить какие-либо улучшения?

Спасибо за ваше чтение и за ваши мнения.

Ответы [ 3 ]

2 голосов
/ 24 октября 2011

Это не ужасно, и на самом деле это было написано другими до вас.Например, см. Разработка программ на Java Лискова / Гуттага, который использует ваш подход к проверке инвариантов, но называет его repOK (), а не invariant ().

В ограниченном приложении этоработает своего рода Сорта.Но есть много проблем, которые возникают из-за того, что спецификациям контракта не нужно беспокоиться о проблемах типа «кто звонит, кто», что делает реальный код.

  • Скажем, у вас есть некоторыеметод F, который вызывает другой метод G. Представьте, что F прерывает инвариант rep во время его работы, но исправляет некоторые вещи до его возврата.Это разрешено, а в некоторых случаях требуется, но G не знает об этом, и это неправильно вызовет исключение.
  • Конструкторы хуже.Скажем, класс D расширяет класс C и переопределяет invariant ().D () вызывает C (), что вызывает D.invariant (), что неверно.C не должен удовлетворять инварианту D, который является более сильным, чем его собственный.
  • Если клиенту передается неверный аргумент за пределами класса, то IllegalArgumentException вполне подходит.Но если вызывающий абонент находится внутри класса, это обычное нарушение старого контракта.Вы хотите различать два.Гари Ливенс рассказывает о том, как JML делает это в этой статье , если вам интересно.
  • Постусловия, выраженные в терминах других методов класса (то есть "постусловия"), будут вызывать бесконечное взаимноепри проверке рекурсии.

Я полагаю, что DbC интересен, и если у него есть язык (или, что еще лучше, что-то вроде декоратора функций Python), или у вас есть инструмент наподобие ModernJass , потом копайся. Но делать это на чистой Java невозможно.Тем не менее, я работаю над инструментом проверки инвариантов , который генерирует код, аналогичный тому, который у вас есть, за исключением проблем цепочки вызовов (вместо этого он работает, расширяя классы, чтобы принимать посетителя, который знает, когдауместно сделать проверку).Он требует Eclipse и имеет собственные проблемы (в основном связанные с плохими словами, такими как private и static), но механизм проверки - чистая Java.

2 голосов
/ 26 февраля 2011

Если вы хотите «Design By Contract» для Java, вы можете взглянуть на то, как (действительно) большие парни делают это!Вот недавний взгляд Google на эту тему с «Контрактами на Java»:

http://google -opensource.blogspot.com / 2011/02 / contract-for-java.html

Теперь ответим на два ваших вопроса:

- do you see any downside of this approach? Why wouldn't you use this in your classes?

Потому что одним недостатком является то, что он очень многословен: настолько многословен, что делает код едва читаемым.

- can you suggest any improvement?

Не изобретай велосипед ...

0 голосов
/ 26 февраля 2011

Видите ли вы какие-либо недостатки этого подхода?Почему бы вам не использовать это в своих классах?

Большинство написанных мной классов Java не являются клонируемыми, потому что нелегко реализовать Clonable прямо в Java.Поэтому я не реализую это, когда это не является абсолютно необходимым.Я не хотел бы делать это только для вашего подхода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...