Контракты кода: должны ли мы указывать операторы Contract.Requires (...) избыточно при делегировании методов? - PullRequest
9 голосов
/ 29 марта 2010

Я собираюсь использовать новую функцию .NET 4 Code Contracts для дальнейшей разработки. Это заставило меня задуматься, нужно ли нам указывать эквивалентные операторы Contract.Requires(...) избыточно в цепочке методов.

Я думаю, что пример кода стоит тысячи слов:

    public bool CrushGodzilla(string weapon, int velocity)
    {
        Contract.Requires(weapon != null);

        // long code

        return false;
    }

    public bool CrushGodzilla(string weapon)
    {
        Contract.Requires(weapon != null);   // specify contract requirement here
                                             // as well???

        return this.CrushGodzilla(weapon, int.MaxValue);
    }

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

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

Также будет предусмотрена функция проверка времени компиляции и, возможно, проверка времени разработки контрактов кода. Кажется, он еще не доступен для C # в Visual Studio 2010, но я думаю, что некоторые языки, такие как Spec #, уже делают. Эти движки, вероятно, дадут нам подсказки, когда мы напишем код для вызова такого метода, и наш аргумент в настоящее время может или будет null.

Поэтому мне интересно, будут ли эти движки всегда анализировать стек вызовов, пока не найдут метод с контрактом, который в настоящее время не выполняется?

Кроме того, здесь я узнал о разнице между Contract.Requires(...) и Contract.Assume(...). Я полагаю, что разницу также следует рассматривать в контексте этого вопроса?

Ответы [ 2 ]

14 голосов
/ 29 марта 2010

Я думаю, что будет наилучшей практикой указывать все контракты по каждому из публичных методов. Контракт - это больше, чем просто «то, что проверяется» - это тоже документация, эффективно. Если вы вызываете метод, но не знаете, к какому контракту применяется, было бы странно, если бы сбой контракта был ниже: это означало бы ошибку в вызываемом вами методе, а не в вашем метод.

Обратите внимание, что если вы используете C # 4 в своем проекте, вы можете рассмотреть возможность использования необязательных параметров и именованных аргументов, чтобы избежать таких перегрузок. Это бесполезно, если вам нужно вызывать код с языка, который не поддерживает их, конечно.

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

4 голосов
/ 13 апреля 2010

Также появится функция проверка времени компиляции и, возможно, также проверка времени проектирования кода контракты. Кажется, он еще не доступен для C # в Visual Studio 2010 ...

Он доступен, но для его работы необходимо использовать VS2010 Ultimate edition.

Предупреждение : Это немного умозрительно, но, похоже, это правильно из того, что я узнал, используя его;

Вам нужно распространять ограничения через ваши методы вручную, как вы это сделали.

Единственная информация, которую Code Contracts может видеть снаружи метода, - это то, что вы ему сообщаете. Он может проверять предположения и утверждения внутри метода, но этот анализ не распространяется. Другими словами, CC не может «видеть сквозь» ваши методы, поэтому он автоматически не знает, что CrushGodzilla(string) потребует, чтобы weapon было ненулевым.

При использовании статического анализа он выполнит проверки в CrushGodzilla(string) и поймет, что weapon не может быть нулевым, используя external информацию о CrushGodzilla(string,int), и предложит добавить Requires ненулевое предварительное условие. (Нераспространение - это факт, что эти знания не будут использоваться для анализа остальной части программы.)

На самом деле я не нашел нигде такого хорошего документирования этого статического анализатора, несмотря на то, что выглядел.

...