2010-08-26 2 views
2

В моей базе кода есть много операторов #if DEBUG/#endif, которые в основном имеют логику типа утверждения, что я недостаточно храбр, чтобы работать на производстве.В чем недостаток условных атрибутов, а не # if/# 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(); 
} 

Буду ли я сожалею об изменении всех этих вопросов на новый способ ведения дел?

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

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

+0

Какой новый способ вы думаете? – SwDevMan81

+1

Мэтью рассказывает о '[Условный (« DEBUG »)]'. – Andreas

+0

Что еще более важно, что такое верх? –

ответ

3

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

+0

Я также использую кодовые контракты, но также можно отключить Кодовые контракты в Release. И без проверки статического анализа (который, как представляется, доступен тем, кто платит дополнительно), Code Contracts кажутся просто синтаксическим сахаром. Я предполагаю, что следующий вопрос заключается в том, чтобы изменить все коды # if/# endif и [Conditional()] на Code Contracts? – MatthewMartin

+0

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

+0

Я думал, что реактивные снаряды были прошлым, будущее - все о магнитной проекции и стрельбе из пушек. Я пойду в лагерь. –

2

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

После того, как вы проверите свой код, вы можете реорганизовать его содержимое.

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

+0

Это хороший совет, но ортогональный моему вопросу. – MatthewMartin

1

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

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

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

+0

Чтение этого, http://stackoverflow.com/questions/762299/is-it-worth-using-debug-assert-in-asp-net, похоже, для этого подхода существуют серьезные недостатки. malformed web.config остановит их от запуска, а неудавшееся утверждение в ASP.NET может вести себя как запрос, который никогда не возвращается! – MatthewMartin

1

Недостатки:

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

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

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

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

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

Короче мои Эмпирические правила являются:

  • предпочитает жестким проверяет & исключения с модульными тестами. Использование условных методов, где это невозможно (например, производительность критических проверок)
  • Имя условные методы явно
  • Pragma #IF из кода в теле метода
  • Будьте очень осторожны изменения потока управления программы в условных методов (I лично предпочитаю Debug.Assert вместо исключения при использовании условных методов, но я видел, что многие другие программисты используют исключения, поэтому это, вероятно, для обсуждения)
+0

# 4 обращается к вопросу, остальные точки являются минусами как для # if/# endif, так и для атрибута [Conditional()]. Но # 4, кажется, влияет только на размер сборки. – MatthewMartin

+0

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

Смежные вопросы