Как стать автором
Обновить

Комментарии 107

Ужас какой. Для этих целей нужно заводить константы, которые описывают, зачем такое нужно, а еще лучше — специальные properties в файлах настройки программы.
Будьте проще — посмотрите на названия блога и день недели. :)
Пятнично :)
А ведь есть вероятность того, что конструкции в if (false) {… } будут игнорироваться компилятором так же как и обычные комментарии?
Компилятором игнорироваться они точно не будут
Он их обычно в итоговый бинарник не добавляет при включённых оптимизациях.
Понял разницу.
Я потому и обращал внимание на дебаг-конфигурацию. В ней этот код, скорее всего, не будет выброшен.
Скорее всего эта проверка использовалась для того что бы включить/выключить debug mode, но зачем? Есть ведь директивы препроцессора для этих целей.
Есть. Но представьте, что действия нужно выполнять не всегда в дебаг режиме, а только иногда. Вот шли вы в пошаговой отладке — и вдруг захотелось дампануть весь объект на диск (пусть операция занимает много времени). Останавливаться, править код и перезапускать? Долго. Дампить в дебаге всегда? Долго.
Есть же блок #if DEBUG или Watcher тот же.
Не во всех языках он есть.
Пример на С# написан, вот и привел такой пример.
Где нет #if DEBUG, наверняка, есть другие человеческие приемы, в отличии от примера ОП-поста
А Watcher почти везде есть.
Пример написан безотносительно языка. а по поводу #ifdef я ответил уже выше
Ну, в Go, например, других приёмов нету.
В исходник на практически любом языке можно вставить #define/#if и т.д. Просто перед компиляцией нужно пропустить его через препроцессор cpp, что легко делается добавлением одной строчки в Makefile.
А мысль, что это просто говнокод, не посещала?
тогда гугл говнокодит, видел такое условие в demos для андроид, могу дать ссылку если интересно
Можно подумать, в гугле супермены сидят и говнокод не пишут.
я этого не говорил, но не думаю, что это говнокод, скорее всего они таким образом закомментировали дополнительную функциональность, которая не требовалась для работы примера, но имела право на существование
А Вы читали статью дальше первого абзаца?
Да.
а, ну тогда ладно.
Сам такого никогда не писал, но видел, как заказчик после себя в коде оставлял такие блоки с кодом, где вызывались некоторые фичи для «потестировать, а потом когда-нибудь включим»
Есть ещё вариация на тему. Знаю людей, которые так хранят куски кода, которые редко, но надо вызывать при специальном режиме работы вспомогательной программы (утилиты). При этом совет удалить такой код (он всё равно есть в системе контроля версий) они отказываются.
А я знаю людей, которые так хранят куски кода, чтобы копипастить их в другие места. Удобный темплейт — всегда под рукой. Тоже удалять отказываются…
Печально. В том числе для этого вообще есть gist.github. Сам почти не пользуюсь, но ряд знакомых утвердают, что это весьма удобно.
Чтобы достать его из системы контроля, надо помнить, когда он есть, а потом вытащить из старой версии файла и вставить в нужное место новой (код вокруг этого куска давно изменился)? Нет уж, пусть лучше на месте полежит. Я его, правда, окружаю #if false, а не if(false), но идея насчет контроля кода компилятором мне понравилась. Жаль только, что он будет давать ворнинги.
Пока ваш код лежит в #if false, он точно также не анализируется компилятором на предмет ошибок, так что это не аргумент. Сказанное справедливо для C#, как дела обстоят в C++, я не знаю. А про вытащить старую версию файла тоже надуманно. Просмотр истории файла делается в два клика, если ваша IDE интегрирована с клиентом системы контроля версий.

Но я признаю, что это всё на любителя. У каждого свои привычки и т.д. «Кто как хочет...», как говорится.
В процессе автоматического рефакторинга могут происходить такие казусы.
Надо просто запустить ещё один проход — он по идее должен такую конструкцию выбросить ;) А Вы чем, кстати, для автоматизированного рефакторинга пользуетесь, если не секрет?
Я пользуюсь продуктами от JetBrains в своих проектах.
false переопределен? Как вариант.
Классная мысль, но за такое сами знаете, что надо делать. :)
За такой код вы тоже сами всё знаете)
Так что возможное решение не дебильнее задачи :)
#define TRUE random()%2
Постулат современный политики.
Ну я в самом начале предложил принять, что false — это false.
Ну просто понадобилось зачем-то быстро выключить часть кода (видимо с целью потом его также быстро включить), не заморачиваясь с комментариями или директивами препроцессора.
Кстати, в ранних версиях LabVIEW до введения Disable структуры подобный метод был практически единственным.
Такое вполне может встретиться в процессе отладки, однако из продакшн кода такие конструкции надо выкидывать при code review, либо пользоваться макросами, объясняющими суть происходящего, иначе они запросто могут вводить в ступор следующих программистов.
Все ж это бессмысленно.

Хоть я и не С программист, но можно назначить константы (В PHP у них глобальная область видимости)
И в них писать Boolean, который как раз и отвечает за дебаг.

А вот этот if(false) нужно будет найти в куче файлов и заменить на if(true).
Не логично и не лаконично.
Если слепо следовать DRY (и только), то константу/переменную нужно вводить как раз тогда, когда появляется второе такое место.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
В Qt Creator тоже
Мне тоже кажется это такой способ закомментировать код, не потеряв при этом syntax highlighting
#define false true
:D
НЛО прилетело и опубликовало эту надпись здесь
возможно это защита от таких переопределений :)
прикольный вариант :)
Ещё адекватный, имхо, вариант — true/false в условии имеет функцию ключа компиляции или параметра конфига. Грубо говоря, true — использовать gd, false — использовать imagemagik. Но по каким-то причинам использовать, например, константы для придания семантики булеву значению, не стали.
Ну, если хочется что-то отладить, можно использовать такую конструкцию в качестве комментария, чтобы потом в процессе пробовать запускать программу то с false то с true, это быстрее, чем то писать /* */, то стирать это. Хотя я бы скорее вынес переменную true/false в #define:)
Такой код есть в шаблоне корзины в Битриксе :)
В PHP версии? Если да, то это же кошмар!
Весь код Битрикса это один сплошной кошмар
bitrix/components/bitrix/store.sale.basket.basket/templates/.default/basket_items.php
строка 8 :)
>store.sale.basket.basket
харе кришна, харе рама, харе-харе
НЛО прилетело и опубликовало эту надпись здесь
Непонятно, за что пост начали минусовать. Мне он показался интересным, забавным и таким, где можно подумать. Я смог назвать все варианты кроме «выполнение иногда нужных операций в режиме отладки». Интересный примем, который где-то может вполне пригодиться.
Могу добавить в копилку ещё некоторые варианты. Взято из разных проектов.

1) Обходные маневры
// Old versions of MSVC (6.0 and previous) don't
// support C99 for loop scoping rules. This fixes them.
# if (_MSC_VER <= 1200)
// This trick will generate a warning; disable the warning
# pragma warning (disable : 4127)
# define for if (false) {} else for
# endif

2) Что-то типа static_assert
// Ensures that To is a sub-type of From *. This test is here only
// for compile-time type checking, and has no overhead in an
// optimized build at run-time, as it will be optimized away
// completely.
if (false) {
const To to = NULL;
::testing::internal::ImplicitCast_<From*>(to);
}

3) Недописанный ещё до конца код
if (0)
{
// TODO: Prefix with date
код которые компилируется, но ещё не работает
}

4) Удаление нестандартных расширений
//__try and __except dont work in gcc, so heres some defines to take em out
#define __try
#define __except(x) if(false)
> # pragma warning (disable: 4127)
> # define for if (false) {} else for

Главное потом не забыть это убрать. Я б предупреждение таки не стал отключать.

А как, кстати, PVS на все эти трюки реагирует?
Никак. А на что реагировать?
Если есть if (false), то это или раскрытый макрос или так и надо (человек так хочет).
Конечно, это может быть опечатка. Но ловить их, это неблагодарный труд. Это очень распространенная конструкция. Это я вам точно говорю.
о, а это, кстати, чуть ли не единственные разумные причины. 3) это правда просто временное закомментирование кода, а все остальное — вполне жизненно. И 1,2,4 — пожалуй единственные убедительные причины появления такого if-а в коммитах.

а, вру. у меня еще вот такой был:

  if (LITTLE_ENDIAN && some_condition)
  {
     ...
  }
  else
  {
     ...
  }


читаемость выше чем с #ifdef'ами и компилируются всегда обе ветки (то есть некоторые ошибки big-endian кода компилятор поймает уже на low-endian).
Не раз видел такое в raw php темплейтах, чтобы закомментировать ненужный в данный момент большой кусок html кода.

<?php if(false): ?>

большой кусок кода

<?php endif ?>
НЛО прилетело и опубликовало эту надпись здесь
Есть ещё одно применение для ActionScript 3.0 — не вызывать конструктор предка. Если программист этого не делает руками, то компилятор подставляет этот вызов в начало конструктора, а если компилятор найдёт его даже под if(false), то сам ничего делать не будет. В итоге получаем объект, для которого не вызван конструктор предка. Костыль конечно, но иногда можно использовать.
неа, неправда.
Флексовый компилятор достаточно умён чтобы выбросить if(false), и тогда, после выбрасывания этого куска конструктор будет вписан. И даже if (2!=2) он, по-моему, палит, точно не помню. А вот if((2+2)!=4) вот это не палит. Связано это видимо с тем что он не производит вычисления при компиляции, т.к. в байткоде будет сложение и потом сравнение.
Во время отладки Set next statement внутрь if (false)?
Я правда в таких случаях пишу как-то так:
static bool debug = false;
if (debug)
{

Мне как-то проще переменную отладчиком поменять, чем c Set next statement играться.
Таки угадал один из вариантов. Но я всё равно за if (debug).
Посмотрел на это, и пришла в голову садистская мысль:

#define false true

Пятница наверное, домой пора.
Я иногда использую строку в условии:

if ("Send report to owner") {
   // здесь куча строчек кода / вычислений, которые можно отнести к какой-то маленькой фиче,
   // прошитой только в этом файле. Отключать эту фичу никому в голову не придет (поэтому и не дефайн),
   // но не хочется размазывать все ее переменные/действия по файлу (скажем это не мой, макаронный код).
   // Да, можно сделать функцию c говорящим названием (даже если она не реюзается).
   // Но фраза на английском наиболее говорящая.
}

if ("Dumb block to refactor") {
  // тут и так все понятно. Это вместо того чтобы писать два комментария:
  # TODO refactor this block
  ...
  # end of block to refactor
}

>но не хочется размазывать все ее переменные/действия по файлу

// Send report to owner
{
// Do something
}


не?
Да, так тоже можно. Согласен, наверное я скорее выпендриваюсь :)
НЛО прилетело и опубликовало эту надпись здесь
Для подсказки в Zend Studio часто пишу так:
if(0) $a = new MyClass()
Ну и забываю иногда удалить :)
а phpDoc в ZS не рулит?
ну там /** @var $a MyClass */ или типа того?
Нет, @var действует только на поля класса.
Иногда помогает @return MyClass
Но часто функция может возвращать объекты разных типов (фабрика, например, ну или просто объявленная в родительском классе функция — Zend Studio всегда будет думать, что она возвращает родительский класс), и чтобы ZS подсказывала функции нужного класса, приходится делать такое фиктивное присваивание.
Печально. Мне в PhpStorm такой способ помогает, странно что ZS так себя ведет.
Вот спасибо. Если когда-нибудь я встречу в коде нечто подобное, буду знать, где корень зла.
Шутки-шутками, а ведь немало тех, кто возьмет это в оборот.
Что значит, возьмёт? Нормальная практика. Ну может в продакш коде опасно такое оставлять, но для внутреннего использования или ресёча — вполне себе нормальный код.
В большинстве случаев, я уверен, из дев версии такой код перейдет и в продакшн. Это во-первых, а во-вторых, выше уже заметили, что лучше использовать константу с адекватным именем, например DEBUG_MODE. Даже постороннему человеку сразу будет понятно, что это за условный блок.
хм, щас ковыряю чужой сайт на битриксе и смотрю на этот ужоснах, походу автор реально так коментил куски кода, да так и оставил. сайты всё стерпят :(
Ещё отмечу, что для быстрого включения/отключения кода писать не if(false), а if(0), который превращается в true одним символом: if(1).

Ну и ещё из этого разряда:
// было
if(some_condition && some_another_condition) { /* do */ }

А теперь отключаем блок:
if(false && some_condition && some_another_condition) { /* do */ }

Ессно, тут надо быть осторожным, учитывать блоки else и всё такое, но всяко быстрее, чем «выделить и закомментировать».
Я как-то раз из-за
if (false && $this->billing->makePayment()....)

отключил биллинг на продакшне :) спас только звонок клиента через день — «эм… собственно, а почему деньги списываются, а товар не продаётся?» (слава богу, начальник так и не узнал об этом) =)
В пхп нет lazy evaluation? Врёте же, небось написали что-то вроде такого:
if ($this->billing->makePayment() && false)
Не совсем понял, а в чем разница? От переменых мест слагаемых сумма разве не меняется?
Меняется, Билли, меняется.
В обоих случаях блок внутри if'а не сработает. Но в Вашем случае $this->billing->makePayment() выполнится, а в моем — нет.

Почему? Потому что парсер «ленивый».
В Вашем примере:
он смотрит на первую часть условия, находит там false, а за ним — логическое «и». Значит на второй операнд можно и не смотреть.
В моем:
проводит успешную оплату. Потом применяет «и» на false и внутрь блока уже не заходит.

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

В общем, добро пожаловать в программирование.
Я так тестировал свой механизм проверки покрытия кода тестами (проценты).
Второй вариант — когда то писал я шаблонизатор, где однажды выполненный фрагмент кода можно было повторять.
Например, сверху и снизу страницы постраничная навигация.
<fragment paginator>
 //тут постраничная навигация
</fragment>
// тут контент
<include fragment="paginator">


И если сверху он бывает не нужен, то отключается. Был даже тег который пребразовывался в <?php if(false) {
Парсер съел тег <hidden>, который пребразовывался в <?php if(false) {
Дисклеймер для тех, кто прочитает эти строки не в январе 2012, а допустим, в июне 2013. Это не фрагмент кода, по которому учатся. Если подобные вещи выносить во внешние файлы, то затраченное время будет меньше на много порядков (примерно в 1000-2000 раз по моим подсчётам и моим примерам).
Более того, гораздо лучше подготовить заранее переменную и выводить её в шаблон хоть тыщу раз.
*тьфу, феврале
Как насчёт такого: внутри if(false) {...} содержится упоминание статического класса. И хотя в этот блок исполнение никогда не зайдёт, статический класс будет проинициализирован, а его статический конструктор будет вызван. Я прав?
Хотя, с таким нужно быть очень осторожным, так как компилятор может оптимизировать код и просто удалить блок, в который исполнение никогда не зайдёт.
Внутри может быть банальный набор #define, которые нужны, а исполняемый код рядом не нужен.
Нет, конструктор вызван не будет пока выполнение не дойдёт до точки, где определена переменная. И да, компилятор скорее всего удалит этот блок при включённой оптимизации.
Какая переменная?
Статическая внутри if (false). Я про С++ говорил, а вы, похоже, про C#. Недоразумение :)
Хотя, что бы вы ни имели в виду, вы правы :) По крайней мере, для C#, статический конструктор не вызывается, пока не встречается хоть какое-то использование класса. Я когда-то читал, что вызов статического конструктора — это вообще недетерменированная штука, и не стоит рассчитывать, что он вызовется в какой-то определенный момент.
Так что, моё изначальное предположение не подтвердилось.
НЛО прилетело и опубликовало эту надпись здесь
А еще так можно хранить примеры и это удобнее чем в комментариях, т.к. работает подсветка и навигация по коду. при компиляции оно все-равно поскипается оптимизатором. Да и дебажить бывает очень даже удобно таким способом.
НЛО прилетело и опубликовало эту надпись здесь
Я пишу на Lua, и использую такую конструкцию для включения дебаг режима исключительно в начале main файла, впринципе, можно было бы создать глобальную переменную DEBUG = true, и менять ее, а не условие, но за чем лишний раз засорять глобальное пространство.
Не могу поставить плюс, поэтому спасибо. Не задумывался о таком применении.
В 1С — единственный вариант type hinting для значений, тип которых неизвестен (например передаваемый в функцию параметр), например:
Процедура ПриветХабр(Параметр)
    Если Ложь Тогда 
        Параметр = Новый СписокЗначений;
    КонецЕсли;
    ...

(не плюйтесь про код на родном языке, в США так все пишут ;))
нужно было назвать статью «Как оправдать свой говнокод»
Я пишу if (1==2), такая конструкция при просмотре кода сильнее бросается в глаза
А какой язык?
перл, пхп
оно же возвратит true? вот '===' другое дело…
хотя я могу ошибаться.
ошибаетесь.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий