Я занимаюсь программированием на языках, производных от C, уже пару десятилетий. Где-то по ходу дела я решил, что больше не хочу писать:
if (var) // in C
if ($var) # in Perl
когда я имел в виду:
if (var != 0)
if (defined $var and $var ne '')
Я думаю, что отчасти это связано с тем, что у меня строго типизированный мозг, и в моем понимании «если» требует логического выражения.
Или, может быть, это потому, что я так часто использую Perl, а правда и ложь в Perl - это такое минное поле.
Или, может быть, это просто потому, что сейчас я в основном программист на Java.
Каковы ваши предпочтения и почему?
Мне просто было интересно узнать, что люди думают о подобных вопросах и думают ли они об этом вообще. Этому вопросу уже больше года. SO за это время сильно изменилась. И вы правы: сейчас много догматических проповедей о ТАК - кажется, не так уж много «живи и давай жить другим» - и я должен задаться вопросом, насколько репрезентативны такие идеи.





if (var)
Меньше печатать, если вы уверены, что не тестируете что-то не то.
Не только меньше печатать, но и меньше читать, а это значит, что требуется меньше умственных способностей, чтобы понять это.
if (v) на 3 нажатия клавиши меньше для ввода и чтения, так что это намного лучше.
все дело в семантике. Спросите мою жену, она будет грустить, оба пути не читаются (она не программист). Для обученного программиста на C это совершенно ясно, поэтому я также предпочитаю короткий путь.
@PolyThinker, это неправда.
я предпочитаю
if (var != 0)
Легче читать / понимать. Поскольку вы пишете код один раз, но читаете довольно много раз, легкое чтение важнее, чем легкое написание.
Я использую это, если только var не является логическим. Я никогда не делаю if (var == true).
if (var) мне одинаково легко читать (если не проще). Чем больше читать, тем труднее понять. Но я согласен, что это чисто субъективно.
Я согласен с PolyThinker ... для меня if (var) легче читать, потому что читать меньше, и я уже понимаю его значение.
Предупреждение: теория «меньше читать - значит легче понимать» неизбежно приводит к выводу, что APL - это самый легкий для чтения компьютерный язык. Наши тесты говорят об обратном.
Я предпочитаю явные тесты, если результат в круглых скобках не является явным логическим значением. Фраза «if (1)», хотя синтаксически и семантически верна с точки зрения языка, не логична. Оно должно быть истинным или ложным, а не приводиться автоматически.
Я предпочитаю читаемый логический код, чем меньше печатать каждый день.
Я также категорически презираю код вида:
if (gotError == FALSE) ...
if (isComplete == TRUE) ...
Если логическое значение правильно названо (а оно должно быть), правильный способ сделать это:
if (!gotError) ...
if (isComplete) ...
Это потому, что (используя reductio ad absurdum) boolVal == TRUE - это просто еще одно логическое значение, так где же остановиться?
if (isComplete == TRUE) ...
if ((isComplete == TRUE) == TRUE) ...
if (((isComplete == TRUE) == TRUE) == TRUE) ...
if ((((isComplete == TRUE) == TRUE) == TRUE) == TRUE)...
И так до бесконечности.
У меня есть несколько способов сделать это:
для логических значений:
if (x)
для ints:
if (x != 0) // always compare, never assume true/false on int values
для указателей:
if (x /* != 0 */) // I've always done this, not sure where I picked it up but I like it
В наши дни я думаю, что лучше иметь вызов функции, который описывает, что на самом деле означает логика внутри оператора if.
Обновлено: обратите внимание, что 0 (вместо NULL) связано с тем, что в наши дни я в основном использую C++
Почему вы используете «if (x / *! = 0 * /)»? Чтобы генерировать меньше (а значит, быстрее) кода? Есть ли разница в коде, созданном для «if (x)» и «if (x! = 0)»?
Читаемость, больше всего на свете. Когда я был моложе, я делал некоторые уроки, и это немного помогло новичкам (если (x)) может сбивать с толку, как ни удивительно. Я всегда осторожен с логикой :-) Я не думаю, что он генерирует меньше кода, в любом случае недостаточно, чтобы быть значимым :-)
VBScript? Этот фрагмент кода объявляет вариант, поэтому bFlag равен нулю, что фактически является ложью.
Dim bFlag
If bFlag Then
Мне это не нравится. Таким образом, даже в VB с возможностью более конкретных объявлений я обнаруживаю, что выражаюсь явно независимо от типа.
Dim bFlag As Boolean
If bFlag = False Then
Другая проблема связана с правилами именования переменных. Если вы используете режим под влиянием Венгрии, вы можете визуально сказать, что данная переменная является логической, поэтому конкретизировать, истинно она или ложно, не так важно. Если, однако, вы используете какую-то другую технику именования переменных или, что еще хуже, именование произвольным образом, то уместно указать, что именно тестируется.
Если у вас есть значение, которое должно быть логическим, вы должны чувствовать себя комфортно, просто выполняя:
if ( var )
if ( $var )
Если у вас есть более конкретные требования для вашего «логического» значения, вы всегда можете выполнить некоторую подготовительную работу / проверить свою переменную и назначить ее другой переменной с более определенными логическими значениями.
$shouldDoSomething = ( defined $var and $var ne '' ) ? 1 : 0;
if ( $shouldDoSomething ) {
// Handle this case.
}
Это может немного очистить код. Также полезно, если вы собираетесь использовать это условие более одного раза. На самом деле, я считаю, что это случается довольно часто. Кроме того, мне кажется, что приведенное выше гораздо более читабельно, чем встроенное:
if ( defined $var and $var ne '' ) {
// Handle this case.
}
? 1: 0 не нужен и, на мой взгляд, запутан.
Вы правы, в данном конкретном примере это не нужно. Я добавил его, чтобы разобраться с тем, что «правда и ложь в Perl» являются «таким минным полем», упомянутым в вопросе. С помощью этого кода вы будете знать, что $ shouldDoSomething всегда будет либо 0, либо 1.
Мне нравится, что мои if имеют смысл при чтении вслух:
if (is_it_happening) ...
if (number_of_sheep != 0) ...
if (pointer_to_something != NULL) ...
Константы на LHS пожалуйста :)
@JaredPar: константы слева или справа - это тема для другого потока
константы слева не позволяют прочитать его вслух.
@Shy 0! = Number_of_sheep (ноль - это не количество овец) звучит для меня нормально: P
Для мастера-джедая это особенно хорошо.
че: Обидно, что здесь нельзя модерировать комментарии как +1 Забавно, как на Slashdot. Я бы поддержал твою.
Константы в LHS имели смысл, когда компиляторы были мертвыми. Теперь они помечают предупреждение, если вы пытаетесь назначить его внутри if, и у всех должен быть включен параметр «рассматривать предупреждения как ошибку».
@Jesse: Я так думаю. Константы в левой части были созданы для предотвращения ошибок программиста. В английском языке константы всегда находятся в правой части уравнения. «Мой бензобак пуст», «Ваша рубашка зеленая», «Если указатель не ПУСТОЙ» и т. д.
@shoosh, это правда только если ты англичанин.
В Javascript (про другие динамические языки не знаю)
if (x)
а также
if (x != 0)
означают разные вещи. Я буду использовать первое, когда я ожидаю, что x будет содержать ссылку на объект или строку, длина которой не должна быть нулевой. Это достаточно известная идиома.
Я бы сказал, что если вы сравниваете истинное целое число, никогда не выполняйте неявное преобразование в логическое значение, поскольку это подразумевает другое значение переменной.
Но опять же, этот стиль настолько популярен, что, вероятно, не так уж важно, но, работая с C#, я пишу свой код C++ в этом стиле:
Boolean или int, который в основном является логическим:
if (val)
Истинное целое число с важностью более чем истина / ложь:
if (val != 0)
Указатель какой-то:
if (val != NULL)
Но как многие люди скажут о стилях кодирования, которые не имеют функционального значения, вероятно, лучше всего быть последовательным, а если вы работаете с существующим кодом, будьте согласованы с этим кодом.
Очень часто использую:
if (x) {
DoSomething;
DoSomething2;
}
Потому что это меньше письма, а книга, в которой читается, говорит:
Few good programmers use form if (x!=0), they use if (x).
Но иногда используют и другую форму:
if (x!=0)
HNY! :-)
В какой книге это сказано?
Я удивлен, что никто не упомянул другой вариант, который защищал стандарты кодирования моего бывшего работодателя:
if ( 0 != x );
Где константа всегда указывалась первой (особенно это важно для сравнений, так как они иногда опечатываются в присваиваниях - источник многих ошибок)
Это стиль, который я использовал с тех пор в моем C / Perl / C++ / VB.Net с тех пор (очевидно, что в C# вопрос становится спорным, который фактически не допускает сценарий if (x) (если, конечно, x на самом деле не является логическим).
Хотелось бы знать, почему кто-то проголосовал против этого ...
Согласны, вниз избиратели должны комментировать!
Сегодня получил еще один необъяснимый голос против ...
он должен быть отвергнут, потому что он не по теме. константа на LHS против RHS отличается от того, как проверять логическое значение.
Но это также выражение предпочтений, когда есть три варианта. возможно, ответом должно было быть «ни то, ни другое», что менее полезно
Константы на LHS абсурдны и предполагают недостаток интеллекта у других кодировщиков и у вас самих.
В C# было явно запрещено писать
if (x){}
если x не является логическим типом. Неявного преобразования в bool из большинства других типов нет.
Я много использовал эту форму для написания JavaScript, PHP и тому подобного, чтобы проверить ненулевое значение. Но опять же, я получил несколько (легко обнаруживаемых) ошибок из-за этого ... Думаю, нам лучше без него.
Когда я использую его для логических переменных, я твердо верю в легко читаемые имена. Я обычно называю такие логические переменные именами, начинающимися с «is», «has» или чего-то подобного.
В Perl if (defined $var and $var ne '') и if ( $var) НЕ эквивалентны. Попробуйте с $var=0. И наоборот, если вы тестируете $var!=0, все строки, которые не могут быть преобразованы в числа, не пройдут тест (с предупреждением, если они у вас включены).
Таким образом, вы должны точно знать, что содержит ваша переменная (число или строка, может ли это быть undef), чтобы вы могли соответствующим образом протестировать.
Обычно я просто пишу if ( $var) и позволяю Perl позаботиться об этом. Я считаю, что это легче читать, и это самый распространенный стиль в Perl.
На самом деле, очень часто правильный тест оказывается if ( defined $var). Вот где пригодится новый оператор Perl // (в версии 5.10). $var= $val // $default или часто $var //= $default, где $var получит $default, только если $val (соответственно $var) - это undef.
Вот почему я сказал: «Истина и ложь в Perl - такое минное поле». Обычно я хочу знать, "определены ли $ var и $ var ne ''". Обычно я не хочу, чтобы тест возвращал false, если "$ var eq '0'"
Я обычно предпочитаю if (var) или if ($var), если var используется как логическое, даже если в языке нет такого типа.
Я очень не люблю такие конструкции, как if (!strcmp(...)) или if (var == true). Первый пытается быть слишком умным, второй слишком тупым - хотя он хорошо масштабируется до if ((var == true) == true), ... ;-)
Некоторые языки, такие как Perl и C++, предоставляют дополнительную или даже определяемую пользователем интерпретацию правильности. Если преобразование в логическое значение кажется слишком волшебным, помните, что это в основном просто is_true(var) или var.booleanValue(), или что-то в этом роде за сценой, просто более сжатый синтаксис.
Что касается вашего вопроса, мне нравится формулировать условия в позитивном ключе. Вместо
if (!condition) {
g();
}
else {
f();
}
я предпочитаю
if (condition) {
f();
}
else {
g();
}
Даже если ветка всего одна, и условие не очень простое. (Признаком этого является необходимость комментария.) Например, вместо
// explain reason for condition here
if (!condition) {
f();
}
Я предпочитаю сформулировать это как
if (condition) {
// explain condition here
}
else {
f();
}
Я предпочитаю удобочитаемость, как и большинство людей, мне нравится иметь возможность сканировать свой код и читать его, не слишком много думать, это идет рука об руку, хотя и с хорошо названными именами переменных. Если ваши имена переменных звучат так, как будто это должен быть простой if (isPurchasable), я использую его, но он относится к номеру, дате или аналогичному стилю, я использую if (stock > 0).
Необходимость писать комментарий для оператора if тоже мне - ужасная идея, если выражение настолько простое, оператор if, как показано ниже, хотя я могу понять, почему следует использовать комментарии.
if (isPurchasable && stock > 0 && credit >= cost && !reserved) {
// Checks to see if customer can purchase product.
}
читаемый код улучшает ремонтопригодность и понимание кода. Код предназначен для людей. IL или бинарный - для компьютеров.
Стоит ли вам действительно быть программистом, если вы не хотите слишком много думать !?
@Джеймс; хороший момент, но не совсем то, что я имел в виду; мышление должно быть сохранено для актуальной проблемы; если простое определение того, что делает мой код, требует размышлений, то решение любой проблемы займет вдвое больше времени.
Для скаляров числовых значений я обычно пишу if ( $num_foo ), когда $num_foo находится под моим контролем. Если это пользовательский ввод или полученный извне, я либо сначала нумерую его, либо подробно описываю тест. Это зависит от множества факторов. Главный критерий - когда и как удобно работать с неопределенными значениями, чтобы избежать предупреждений.
Чтобы проверить непустую строку, я писал if ( $foo ), потому что правильное заклинание - это слишком много набирать:
if ( defined $foo and length $foo )
Но меня не устраивало такое положение вещей, поэтому Я инициировал изменение поведения length undef в Perl 5.12 выдает предупреждение и возвращает 0 до Perl 5.10 включительно. В 5.12 он просто молча вернет undef. Поэтому в небулевых контекстах вы все равно получаете предупреждение, оно происходит только после оценки вызова length, а не до него. Но в логических контекстах предупреждения нет, поэтому проверку на наличие непустой строки намного проще сделать правильно:
if ( length $foo )
На мой взгляд, простота лучше всего.
Чем проще вы сделаете код, тем лучше. Кроме того, тем меньше вероятность того, что вы совершите ошибку. Поэтому я бы использовал
if (var)
Но, в конце концов, вы должны использовать то, что лучше всего подходит для вашего собственного образа мышления.
Мне не всегда это удается, но я стараюсь использовать
if (0 != var)
так что это соответствует оборонительному стилю
if (0 == var)
Я предпочитаю голый:
if ($canDo) {
}
вместо чего-то вроде:
if ($canDo == true) {
}
Там, где условное выражение сложно, я комментирую его либо явно с помощью комментария, либо неявно с помощью хорошего имени переменной. Я также стараюсь быть очень точным при установке логической переменной, предпочитая:
my($canDo) = !0;
к
my($canDo) = 1;
Последнее сбивает с толку; зачем назначать дискретное значение логическому?
Тем не менее, учитывая множество значений Perl для выражения «оценивается как истинное», я могу понять, почему в долгосрочной перспективе более практично быть более ясным. Тем не менее, одна из вещей, которые мне больше всего нравятся в Perl, - это его естественная лингвистическая текучесть, и я предпочитаю придерживаться этого в своем коде (оставляя комментарии и имена переменных для дальнейшего пояснения, если это необходимо).
Все очень просто. if ( var ) проверяет правдивость. if ( var != 0 ) проверяет, что это не номер 0. ОНИ НЕЗАМЕНЯЕМЫЕ! Есть три причины.
Во-первых, использовать if ( var != 0 ) для проверки истины сложнее. Там просто больше, чтобы прочитать и понять. Вы должны понять, что != и 0 - это идиома, означающая «верно». Не имея четкого визуального рисунка, вам придется немного изучить его, чтобы понять, что это не то же самое, что if ( var == 0). Это тонкое различие, но о нем стоит упомянуть. Тот факт, что стиль if ( 0 != var ) существует, внушает доверие. Лучше просто устранить проблему и для правды использовать if ( var ).
Во-вторых, что более важно, намерение должно быть ясным. Вы проверяете истину или проверяете число (или его отсутствие)? if ( var ) проверяет истину, if ( var != 0 ) проверяет число. Чтобы определить что-либо еще, требуется знание авторского стиля, которого, мы должны предположить, не знает программист по обслуживанию.
В-третьих, здесь есть предположение о значениях истинных, ложных и числовых операторов, которые могут работать на одних языках, а не на других. В Perl и, как мне кажется, в Javascript пустая строка неверна. Многие операторы возвращают пустую строку за ложь. Так что проверка правды с if ( var != 0 ) приводит к предупреждению. Это становится более очевидным, когда вы делаете что-то более наивное, например if ( var == 1 ), чтобы обозначить истину, явно опасное предположение. Мне кажется, что многие молодые программисты пишут это и, в свою очередь, пишут функции, возвращающие нечетные, но верные числа, для наказания за подобные вещи. Или, когда я в настроении пожертвовать, я продезинфицировал возвращаемое значение с помощью return var ? 1 : 0.
В соответствующем примечании Perl вернет последнее вычисленное выражение из подпрограммы, поэтому на самом деле нет необходимости писать return. Объедините это с представлением людей о том, что явно return работает медленнее, и вы получите множество людей, злоупотребляющих этим фактом.
sub set {
my( $self, $key, $value ) = @_;
$self->{$key} = $value;
}
set вернет $value. Это было задумано? Я не знаю. Я точно знаю, что кто-то начнет на это полагаться. И программист обслуживания не будет знать, могут ли они это изменить. Поэтому мне нравится явно помещать возврат в каждую нетривиальную подпрограмму.
sub set {
my( $self, $key, $value ) = @_;
$self->{$key} = $value;
return;
}
В этом случае я решил, что set пока ничего не вернет, и это решение будет совершенно понятно как читателю, так и пользователю.
Полный код поддерживает этого чувака.
Мне нравятся твои рассуждения, я никогда не думал об этом так.
@nemo Я вырос на этой книге. :)
+1 для вашей идиомы, чтобы включить явный возврат void, когда подпрограмма не предназначена для возврата ничего. Я никогда не думал об этом ракурсе. Кстати, мой исходный вопрос гласит: «... когда я имел в виду, если var! = 0», поэтому я не предполагал, что разные формы эквивалентны, просто в некоторых ситуациях одну можно заменить другой для лучшей читаемости.
Я считаю, что if (X) {/ * ... * /} намного легче читать (по крайней мере, на C).
Если я не ожидаю, что кто-то еще прочитает код, я бы использовал короткий. Если я ожидаю, что кто-то действительно прочитает мой код, я бы подумал об использовании длинной формы для удобства чтения.
Кто-то всегда собирается прочитать код.
На мой взгляд, лучше if (var != 0).
Мне нравятся конструкции Python:
if var:
return "I like the way I do it!"
Это просто например ;-)
Если у вас есть int-bool в C, который уже содержит флаг (а не счетчик), и вы тестируете его с помощью «if (var! = 0)», где он заканчивается? Разве «if ((var! = 0)! = 0)» не было бы даже лучше? :-)
Кто-то читал Геделя, Эшера и Баха - или пропустил это и сразу перешел к Льюису Кэрроллу :-)
Я никогда не читал ни первого, ни чего-либо другого. Об этом мне рассказал мой первый курс CS проф.
Ну, я не сказал, что это ты :-) Но я рекомендую их обоих.
Есть языки, на которых у вас нет выбора. В Specman, например, нельзя писать:
var x: uint;
if (x) {
bla
};
Но вы может делаете:
var x: uint;
if (x != 0) {
bla
};
или же
var x: bool;
if (x) {
bla
};
Однако делать нельзя:
var x: bool;
if (x != 0) {
bla
};
Потому что вы не можете сравнивать логическое значение с целым числом.
Переходя с C и Perl, я всегда думал, что это раздражает, пока я действительно не начал много писать на Specman. Код просто понятнее.
Серьезно, я не понимаю, насколько это полезный вопрос? Догматическая проповедь в ответах меня так злит (в основном потому, что я не согласен)! Если у вас было 5 повторений и трудности с написанием английского, он был бы закрыт без дальнейших размышлений.