Насколько хорошая идея использовать контракты кода в Visual Studio 2010 Professional (т.е. без статической проверки) для библиотек классов? - PullRequest
8 голосов
/ 13 апреля 2010

Я создаю библиотеки классов, некоторые из которых используются другими во всем мире, и теперь, когда я начинаю использовать Visual Studio 2010, я задаюсь вопросом, насколько хорошая идея для меня перейти на использование контрактов кода вместо обычные операторы if в старом стиле.

т. вместо этого:

if (fileName == null)
    throw new ArgumentNullException("fileName");

используйте это:

Contract.Requires(fileName != null);

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

Итак, у меня есть несколько вопросов:

  • Статическая проверка включена по умолчанию, если у вас есть доступ к ней? Или есть настройка, которую мне нужно включить в библиотеке классов (а так как у меня нет статической проверки, у меня не будет)
  • Мои страхи необоснованны? Является ли приведенный выше сценарий реальной проблемой?

Любой совет будет приветствоваться.


Редактировать : Позвольте мне уточнить, что я имею в виду.

Допустим, у меня есть следующий метод в классе:

public void LogToFile(string fileName, string message)
{
    Contracts.Requires(fileName != null);
    // log to the file here
}

и тогда у меня есть этот код:

public void Log(string message)
{
    var targetProvider = IoC.Resolve<IFileLogTargetProvider>();
    var fileName = targetProvider.GetTargetFileName();
    LogToFile(fileName, message);
}

Теперь, здесь, IoC включается, разрешает некоторый «случайный» класс, который предоставляет мне имя файла. Допустим, что для этой библиотеки нет никакого способа, которым я мог бы вернуть класс, который не дал бы мне непустое имя файла, однако, из-за природы вызова IoC, статический анализ не может проверить это и, следовательно, может предполагать, что возможное значение может быть нулевым.

Следовательно, статический анализ может заключить, что существует риск вызова метода LogToFile с аргументом null и, следовательно, невозможности его построения.

Я понимаю, что могу добавить в код предположения, говоря, что компилятор должен принять его так, как если бы fileName, который я получаю от этого метода, никогда не будет нулевым, но если у меня нет статического анализатора ( VS2010 Professional), приведенный выше код будет скомпилирован для меня, и, таким образом, я могу оставить это как спящую ошибку для кого-то с Ultimate, чтобы найти. Другими словами, не было бы предупреждения во время компиляции, что здесь может быть проблема, поэтому я мог бы выпустить библиотеку как есть.

Так это реальный сценарий и проблема?

Ответы [ 3 ]

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

Когда оба ваших метода LogToFile и Log являются частью вашей библиотеки, возможно, что ваш метод Log не скомпилируется после включения статической проверки.Это, конечно, также произойдет, когда вы предоставляете код другим, которые компилируют ваш код с помощью статической проверки.Однако, насколько я знаю, статическая проверка вашего клиента не будет проверять внутренние компоненты сборки, которую вы отправляете.Он будет статически проверять свой собственный код на соответствие общедоступному API вашей сборки.Так что, пока вы просто отправляете DLL, все будет в порядке.

Конечно, есть изменения в доставке библиотеки с очень раздражающим API для пользователей, у которых на самом деле включена статическая проверка, поэтому яЯ думаю, что рекомендуется отправлять вашу библиотеку только с определениями контракта, если вы проверили удобство использования API как со статической проверкой, так и без нее.

Пожалуйста, предупредите об изменении существующих вызовов if (cond) throw ex на Contracts.Requires(cond) призывы к общедоступным вызовам API, которые вы уже отправили в предыдущем выпуске.Обратите внимание, что метод Requires вызывает другое исключение (RequiresViolationException, если я правильно помню), чем то, что вы обычно выбрасываете (ArgumentException).В этой ситуации используйте перегрузку Contract.Requires .Таким образом, ваш интерфейс API останется неизменным.

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

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

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

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

РЕДАКТИРОВАТЬ: Исходя из того, что я могу почерпнуть из руководства, я подозреваю, что описанная вами ситуация действительно возможна. Однако я подумал, что это будут предупреждения, а не ошибки компиляции - и вы можете их подавить, используя System.Diagnostics.CodeAnalysis.SuppressMessage(). Потребители вашего кода, у которых есть статический верификатор, также могут отмечать конкретные случаи, которые следует игнорировать, но это, безусловно, может быть неудобно, если их много. Сегодня я постараюсь найти время, чтобы составить окончательный тест вашего сценария (в данный момент у меня нет доступа к статическому верификатору).

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

0 голосов
/ 14 апреля 2010

Нет; статический анализатор никогда не будет препятствовать успешной компиляции (если она не вылетит!).

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

...