В нескольких местах в нашем коде мы используем блоки ОТЛАДКИ #if для упрощения разработки. Вещи как:
#if DEBUG
serverIP = localhost;
#else
serverIP = GetSetting()
#endif
или
private bool isLicensed()
#if DEBUG
return true;
#endif
return CheckSetting()
Существует также несколько мест, где мы вносим косметические изменения как это:
#if DEBUG
background = humorousImage.jpg
#else
background = standardColor
#endif
Действительно ли опасно зависеть от отладки #if для создания разработки легче? Если это, что такое допустимое использование отладки #if?
Это действительно плохая идея. Если вы пытаетесь поймать производственную ошибку, ваши отладочные пункты обязательно подведут вас на том или ином этапе. Вы хотите быть как можно ближе к коду, который работает на производстве. В вашем примере вы никогда не сможете найти ошибку в CheckSetting()
Судя по всему, ваш код слишком тесно связан. Что вы хотите сделать, так это сделать модули/классы менее зависимыми друг от друга и практиковать Test Driven Development. Также ознакомьтесь с инверсией контроля (она же инъекция зависимостей).
Эффективная работа с унаследованным кодом содержит несколько полезных идей о том, как внедрить TDD. Там также есть несколько действительно хороших указателей на то, как делать TDD в различных сценариях, где может быть трудно тестировать вещи.
Проблема с этим состоит в том, что вы с меньшей вероятностью найдете ошибки в #else
.
В общем, ваши отладочные сборки должны быть максимально похожи на ваши релизные сборки.
Я не могу сказать, что лично мне это нравится - я работаю в среде, где наше основное приложение (развернутое для 400+ пользователей) имеет 60+ модулей - и с 5 разработчиков работают над проектами и выпускают модули, просто знаете, рано или поздно кто-то случайно выпустит модуль отладки. :)
В идеале, я думаю, вам следует переместить эти настройки в файлы конфигурации и сохранить директивы #IF Debug для тестирования, ведения журнала и дополнительных задач «отладки». Также имейте в виду, что клиентский код, который вам когда-либо требовался для создания «отладочной» сборки, теперь будет вести себя совершенно иначе. Мои два цента.
Первое допустимое использование условного блока #if:
У нас есть новая система лицензирования / активации. Нам нужно, чтобы он был отключен для локальной отладки, но мы не хотим использовать параметр конфигурации, чтобы отключить его - тогда пользователь может обойти систему, изменив файл конфигурации!
Итак, мы используем блок условной компиляции:
#if !DISABLE_ACTIVATION
// activation code here
#endif
Надеюсь, это поможет немного раскрасить картину ...!
Вы должны стараться сохранить как можно более похожую рабочую среду и среду разработки, поэтому избегайте двух версий кода.
Одним из допустимых вариантов использования конструкции #if DEBUG
является добавление дополнительных проверок в код, которые не нужны в конечном продукте:
#if DEBUG
if (somehting that normally can't happen) throw new SomeException();
#endif
Мой текущий стиль - иметь файл с именем aadebug. h, который содержит набор условных определений, каждому из которых может предшествовать //, чтобы отключить его. Файл начинается:
//#define DX_DEBUG #ifdef DX_DEBUG #define DX_SKIP_LOGIN // #define DX_ALLOW_BULK_USER_CREATE #define DX_CREATE_EXCESS_LOGS // #define DX_RANDOM_PROBE_FAILURES #define SHORT_KEY_TIMEOUT // #define DX_OMIT_NET_VIEWER ... #endif
Если ОТЛАДКА включена, код главного экрана будет показывать «НЕ ДЛЯ ИСПОЛЬЗОВАНИЯ В ПРОИЗВОДСТВЕ». Все параметры, предназначенные только для отладки, можно отключить, отключив DX_DEBUG, но большинство параметров обычно управляются с помощью отдельных флагов. Если я решу, что какой-то параметр изжил себя, я удалю его # ifdef из источника, а затем удалю закомментированный #define из aadebug.h, но в противном случае я использую закомментированные # define, чтобы отслеживать, какие # Флаги ifdef все еще существуют.