Является ли проверка подлинной экспликации плохим по дизайну?

Является ли я ошибочным явным образом проверять логическое значение true. Было бы лучше сделать простой if(success)?

Я видел разные анекдоты о том, как if (someBoolean === true) - ужасный код на строго типизированном языке, но он также считается плохим на слабо типизированных языках?

Это применимо для любого слабо типизированного языка, который делает принуждение типа в выражении if.

Конкретный пример:

var onSuccess = function (JSONfromServer) {
    // explicitly check for the boolean value `true`
    if (JSONfromServer === true) {
         // do some things
    }
}

// pass it to an ajax as a callback
doSomeAjax(onSuccess);

[изменить]

В этом конкретном случае переменная успеха - это любой действительный JSON, возвращаемый с сервера. Так может быть и все. если его булевская истина, то успех произошел. Если это некоторый объект обработки ошибок, тогда он будет обработан. Если это что-то еще, то, вероятно, это будет спокойно обрабатываться.

Вопрос заключался в том, чтобы вернуть серверу true как JSON и проверить хороший способ обработки случая, когда действие преуспело.

Я хотел бы избежать специфики JavaScript и AJAX.

Ответы

Ответ 1

Я сам в этом разумеваю.

В одном отношении образец кода, который вы опубликовали, хорош, из-за того, как Javascript обрабатывает принуждение типа. Простой if (success) будет вводить блок if, если success является правдивым - например. это будет непустая строка. Тройные равенства гарантируют, что success действительно является логическим значением true, что является более сильной гарантией, чем вы получите с более короткой версией (и, вероятно, той, которая вам нужна).

Однако, если вам это нужно - т.е. вы не знаете, будет ли success логическим, или строкой, или целым числом - я бы сказал, что сам код запах. Независимо от того, как вы выполняете сравнение, я всегда буду сравнивать с переменной, которая неизбежно будет логической; в этот момент не имеет значения, какая форма сравнения используется, поскольку они были бы эквивалентны. Фактически, я бы даже представил "избыточную" переменную следующим образом:

var successCount = items.size(); // or some other way to get an integer
var success = successCount > 0;
if (success) {
   ...
}

Итак, эмм, да. Я не думаю, что кто-то мог действительно жаловаться на (явное) использование === в сравнении из-за его функциональной разницы. Но тем не менее, если вы явно используете логические флаги success, то я не думаю, что кто-то должен жаловаться на короткий стиль.

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

Ответ 2

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

Рассмотрим:

if (false)     // evaluates to false.
if (0)         // evaluates to false, 0 is falsy.
if ("")        // evaluates to false, empty strings are falsy.
if (null)      // evaluates to false, null values are falsy.
if (undefined) // evaluates to false, undefined values are falsy.
if (NaN)       // evaluates to false, NaN is falsy.

Все остальные значения для объектов являются правдивыми.

Если значения правды и ложности приводят к ошибкам в вашей логике, вы должны явно использовать операторы === и !== для обеспечения сопоставления объектов по типу и значению.

Ответ 3

Как правило, вы ожидаете имена логических переменных, например:

success, enabled, pass

чтобы иметь истинное значение. Итак,

if(success) //or

if(enabled) //or

if(pass) //or

if(enabled) //or

понятна и логически читаема. Но если у вас есть такие переменные, как:

result, status, port1.bit7

лучше написать:

if(result == true) //or

if(status == false) //or

if(port1.bit7 == true)

потому что это легко понять так, как показано ниже:

if(result)
{
  ....
}

Считываемость - это ремонтопригодность.

Ответ 4

Что может пойти не так? Точно, ничего. В лучшем случае ваша функция ничего не делает. Это еще лучше, если принять какой-то случайный аргумент как true.

Если вы используете true все другое время, тогда вы также должны явно проверить его.

Хотя я уверен в пользу if foo: в Python, здесь есть большая разница, и это тот факт, что в конечном итоге какой-то случайный jQuery-программист может прийти долго и думает: "О! Он также работает с string и new Boolean()" и использует это.

Что касается предложения Шона использовать !!, это действительно зависит от того, хотите ли вы только принять логическое значение или что-то истинное. Для чистого API я бы принял только булевы.

Ответ 5

Я немного читал о JavaScript, и я никогда не видел, чтобы кто-то говорил, что if(success) был плохой практикой. Я бы сделал это. Вы уверены, что параметр success всегда будет логическим? Прямо сейчас, если это когда-нибудь изменится на что-то еще, вам придется отредактировать функцию. Но если вы просто используете if(success), он будет работать для других "правдивых" и "ложных" значений, таких как строка или пустая строка, или 1 vs 0.

Если вы хотите преобразовать любой параметр в его логическое значение, вы можете просто свести его к нулю: !!success; но это не обязательно внутри такого условного выражения.

Ответ 6

Чтобы добавить к этому разговору, переменные sessionStorage и localStorage могут храниться только как строки сегодня, поэтому, если вы используете:

sessionStorage.setItem('completed',true);

Он будет фактически преобразован в строку и сохранен как "истина". Я видел, как многие люди пишут методы и преобразования, чтобы манипулировать этим значением, чтобы они могли использовать оператор if с использованием логического значения, где простой

if sessionStorage.getItem('completed') === 'true';

было бы достаточно и совершенно разборчивым и поддерживаемым, на мой взгляд.

Ответ 7

Является ли это запахом кода или запахом языка или деталями реализации или вопросом соглашения?

Действительно, это зависит от ситуации.

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

В том же духе Хоар извинился за изобретение ссылки null, которая так же близка к корню этой правдивой проблемы, как я вижу. Дизайн JavaScript просто смешивает проблему, добавляя еще более правдоподобные значения, заставляя многих просто защищать явные проверки, чтобы избежать трудностей в устранении ошибок (Douglas Crockford). Сообщество JavaScript приняло сам язык, немного застряло. Основная команда Python выступает против противоположности, поскольку, по-видимому, дизайн языка упрощается, а не смешивает их, и основная команда по-прежнему планирует изменить язык. Небольшие итеративные изменения являются сущностью больших улучшений с течением времени, будь то соглашение или дизайн языка.

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

Например, True и False являются фактически подклассами int в Python, 0 и 1 в частности. Это имеет несколько преимуществ дизайна. Затем PEP8 выступает за то, чтобы предпочесть делать

if a_reference:
    pass

Единственное время None действительно даже нужно использовать в Python - это указать необязательный параметр.

def foo(bar=optional): # NOTE I made up this idealistic construct
    """Looks good at the surface"""
    pass

def foo(bar=None):
    """But this is clear to the programmer"""
    pass

JavaScript неявно имеет все переменные как необязательные:

function foo(x, y, z) {
    // Certainly not clear to the programmer.
}

И Крокфорд защищает явно проверку вещей, чтобы попытаться добавить ясность в язык.

if (foo === undefined) {
    // pass
}

В основном JavaScript добавлен Null Reference # 2, известный как undefined. Я также думаю, что смешно, что язык JavaScript настолько плохо изучается сообществом разработчиков, что, по их мнению, это справедливый компромисс, чтобы добавить сложность использования чего-то вроде CoffeeScript, GWT, Pajamas, чтобы иметь лучший язык на стороне клиента. Конечно, я не согласен с дополнительной сложностью, но, к сожалению, некоторые люди могут извлечь выгоду, по крайней мере временно, и быстрее выполнять работу под рукой, вместо того, чтобы иметь дело с JavaScript.

Я думаю, что это глупое решение в долгосрочной перспективе.