Какова обратная сторона условных атрибутов по сравнению с # if / # endif? - PullRequest
2 голосов
/ 26 августа 2010

В моей базе кода много операторов #if DEBUG/#endif, которые в основном имеют логику типа утверждений, что я недостаточно смел, чтобы работать на производстве.

[Conditional("DEBUG")]
public void CheckFontSizeMath()
{
  //This check must not block SellSnakeOil() in production, even if it fails.
  if(perferredSize+increment!=increment+preferredSize)
    throw new WeAreInAnUnexpectedParallelUniverseException();
}

Буду ли я сожалеть, что изменил все это на новый способ ведения дел?

ОБНОВЛЕНИЕ : Я ищу разницу между характеристиками двух похожих, но разных синтаксических стилей для выполнения Утверждений. Я понимаю, что существует множество других способов демонстрации работы приложений, и я тоже это делаю. Я не готов полностью отказаться от утверждений.

Также я обновил имя метода для реалистичного сценария только для отладочной версии.

Ответы [ 4 ]

3 голосов
/ 26 августа 2010

Нет проблем сделать это. Более современный подход заключается в использовании кодовых контрактов .

2 голосов
/ 26 августа 2010

Пишите тесты! Тогда вам не нужно бояться, что ваш код делает что-то, чего вы не ожидаете, когда начинаете вносить эти изменения.

Как только вы тестируете свой код, вы можете рефакторировать его так, как вам хочется.

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

1 голос
/ 26 августа 2010

Минусы:

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

  2. Поведение может различаться в разных конфигурациях. Если вы неосторожны, вы можете в конечном итоге поместить не относящуюся к отладке логику в условный метод или добавить побочные эффекты, чтобы ваш производственный код не работал правильно (в основном то же самое, что случайный вызов методов внутри макросов ASSERT () в C ++; эффекты отстой!) Самое главное здесь исключения. Условные методы не позволяют вам возвращать значения по любой причине, чтобы исключить одну потенциальную ошибку. Тем не менее, они позволяют генерировать исключения, которые могут резко изменить путь, по которому происходит ошибка. Это усложняет понимание и поддержание вещей.

  3. На сайте вызова не очевидно, что вызываются условные методы. Вы просто видите «DoSomething ();». Я предпочитаю называть свои условные методы соглашением, в котором я знаю, что это условно; например DEBUG_SanityCheckBufferContents ().

  4. Если вы не #измените тело метода, ваш отладочный код все еще будет существовать, и его можно будет проверять / вызывать, среди прочего, с помощью отражения. IL метода все еще излучается, а сайты вызовов - нет.

  5. Это делает модульное тестирование очень трудным, так как поведение отличается в разных конфигурациях. Это то же самое, что и в пункте 2, но я добавил его в качестве отдельного пункта, потому что это действительно отстойно с точки зрения тестирования. Большинство разработчиков запускают тесты в режиме отладки или выпуска до регистрации, но не в обоих случаях. Наш CI запускает оба набора тестов, так что после проверки всех тестов просто необходимо что-то проверить, чтобы убедиться, что вы нарушили конфигурацию отладки, но тесты пройдены, потому что вы выполнили сборку релиза (или наоборот).

Короче говоря, мои эмпирические правила таковы:

  • Предпочитают жесткие проверки и исключения при юнит-тестах. Используйте условные методы там, где это невозможно (например, критические проверки производительности)
  • Четко назовите условные методы
  • Pragma # если код в теле метода
  • Будьте очень осторожны с изменением потока управления программой в условных методах (лично я предпочитаю Debug.Assert вместо исключения при использовании условных методов, но я видел множество других программистов, использующих исключения, так что это, вероятно, обсуждается)
1 голос
/ 26 августа 2010

Другие варианты, которые у вас есть, это либо использовать кодовые контракты, как это было предложено Хансом, либо использовать методы утверждения в пространстве имен System.Diagnostics.Debug, например,

Debug.Assert(1 + 1 == 2, "Math went wrong!");

Эта проверка автоматически удаляется при сборке выпускаверсия.

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