Подтвердить что ты не робот

If/else, хороший дизайн

Это приемлемо/хорошо подходит для упрощения этой функции:

bool TryDo(Class1 obj, SomeEnum type)
{
    if (obj.CanDo(type))
    {
        return Do(obj);
    }
    else
    {
        return false;
    }
}

как:

bool TryDo(Class1 obj, SomeEnum type)
{
    return obj.CanDo(type) && Do(obj);
}

Вторая версия короче, но, возможно, менее интуитивная.

4b9b3361

Ответ 1

Что я бы назвал:

return obj.CanDo(type) ? Do(obj) : false;

Ответ 2

Версия с скобками:

bool TryDo(Class1 obj, SomeEnum type)
{
    if (obj.CanDo(type))
    {
        return Do(obj);
    }

    return false;
}

Или версия без скобок (в ответах на комментарии это высокие дебаты об этом):

bool TryDo(Class1 obj, SomeEnum type)
{
    /*
     * If you want use this syntax of
     * "if", this doing this on self
     * responsibility, and i don't want
     * get down votes for this syntax,
     * because if I remove this from my
     * answer, i get down votes because many
     * peoples think brackets i wrong.
     * See comments for more information.
     */
    if (obj.CanDo(type))
        return Do(obj);

    return false;
}

Забастовкa >

Ваш первый пример кода лучше, но я думаю, что моя версия еще лучше.

Ваша вторая версия не является хорошей читабельностью и делает код более сложным для поддержки, это плохо.

Ответ 3

else бесполезен, а &&, насколько это очевидно, не так читается, как чистый текст.

Я предпочитаю следующее:

bool TryDo(Class1 obj, SomeEnum type)
{
    if (obj.CanDo(type))
    {
        return Do(obj);
    }   
    return false;
}

Ответ 4

Да.

Особенно с именами, похожими на ваши выбранные имена, то есть CanDoSomething и DoSomething абсолютно ясно любому компетентному программисту, что делает второй код: "если и только если условие выполнено, что-то сделать и вернуть результат". "тогда и только тогда, когда" является основным значением короткозамкнутого оператора &&.

Первый код свернут и излишне длинный, не указав больше информации, чем второй код.

Но в общем случае оба условия могут не формировать такого близкого отношения (как в CanDo и Do), и было бы лучше разделить их логически, потому что помещение их в одно и то же условие может не сделать интуитивного смысла.

Многие люди утверждают, что первая версия "намного понятнее". Иди очень нравится слышать их аргументы. Я не могу думать ни о чем.

С другой стороны, это тесно связанный (хотя и не совсем такой же) код:

if (condition)
    return true;
else
    return false;

это должно всегда быть преобразовано в это:

return condition;

Без исключения. Его краткое и более читаемое для того, кто компетентен на этом языке.

Ответ 5

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

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

Ответ 6

Другая альтернатива, которая может быть более читаемой, - это использование условного оператора:

bool TryDo(Class1 obj, SomeEnum type) {
  return obj.CanDo(type) ? Do(obj) : false;
}

Ответ 7

1-ая версия гораздо легче читать с меньшей вероятностью того, что ее неправильно поняли, и я думаю, что это важно в коде реального мира.

Ответ 8

Мне не нравится этот дизайн, и, возможно, не по понятной причине. Меня это беспокоит. return Do (obj); Для меня нет смысла, чтобы функция Do имела тип возврата bool. Является ли это заменой ошибок, вызывающих ошибку? Скорее всего, эта функция должна быть недействительной или возвращать сложный объект. Сценарий просто не должен появляться. Также, если bool как-то имеет смысл сейчас, он может легко перестать иметь смысл в будущем. С изменением кода вам потребуется больше re-factoring для исправления

Ответ 9

В этом случае я бы пошел с первым вариантом - он намного читабельнее, а намерение кода намного яснее.

Ответ 10

Ни потому, что, когда TryDo возвращает False, вы не можете определить, было ли это потому, что 'Not CanDo' или 'Do False'.

Я полностью понимаю, что вы можете проигнорировать результат, но способ его выражения подразумевает, что результат имеет смысл.

Если результат не имеет смысла, намерение будет более четким с

void TryDo(Class1 obj, SomeEnum type)
{
    if (obj.CanDo(type))
        Do(obj);
    return;
}

Если результат имеет смысл, тогда должен быть способ разграничения двух "ложных" возвратов. И.Е. Что означает "Если (! TryDo (x))" означает?

Edit: Другими словами, OP-код говорит, что "я не умею плавать" - это то же самое, что "Я пытался плавать и утопал"

Ответ 11

Хотя ясно, что второй код для компетентного программиста, мне показалось бы более понятным и понятным в более общем случае написать код, как и любой другой, "если предварительное условие выполнено, сделать действие, иначе провалиться", стиль.

Это может быть достигнуто либо:

return obj.CanDo(type)? Do(obj) : false;

Или

if(obj.CanDo(type)) return Do(obj);
return false;

Я нахожу это превосходным, потому что этот же стиль можно тиражировать независимо от типа возврата. Например,

return (array.Length > 1)? array[0] : null;

Или

return (curActivity != null)? curActivity.Operate() : 0;

Тот же стиль можно также расширить до ситуаций, которые не имеют возвращаемого значения:

if(curSelection != null)
    curSelection.DoSomething();

Мои два цента.

Ответ 12

Мне не нравится вторая версия, так как я не являюсь поклонником порядка оценки подвыражений в условном выражении. Он помещает ожидаемый порядок в подвыражениях, которые, на мой взгляд, должны иметь одинаковый приоритет (хотя они и не делают).

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

Ответ 13

IMO это только ОК, если вторая функция не имеет побочных эффектов. Но поскольку Do() имеет побочные эффекты, я бы пошел с if.

Мое правило состоит в том, что выражение не должно иметь побочных эффектов. При вызове функций с побочным эффектом используйте оператор.
В этом руководстве возникает проблема, если функция возвращает код ошибки. В этом случае я принимаю присваивание этого кода ошибки переменной или прямо ее возвращаю. Но я не использую возвращаемое значение в сложном выражении. Поэтому, возможно, я должен сказать, что только внешний вызов функции в выражении должен иметь побочный эффект.

Подробнее см. Eric Lippert Blog.

Ответ 14

Проблема побочного эффекта, которую некоторые люди упоминают, является фиктивной. Никто не должен удивляться тому, что метод "Do" имеет побочный эффект.

Дело в том, что вы вызываете два метода. Оба эти метода имеют bool как возвращаемое значение. Ваш второй вариант очень ясный и лаконичный. (Хотя я бы избавился от внешней скобки, и вы забыли конечную точку с запятой.)

Ответ 15

Никогда не делай этого. Держите его простым и интуитивно понятным.

Ответ 16

Я мог бы ненавидеть это, но как насчет:

if (obj.CanDo(type)) return Do(obj);
return false;

Мне не нравится иметь брекеты для одного лайнера.

Ответ 17

Я думаю, что Class1 Type должен определить, может ли он это сделать, учитывая значение SomeEnum.

Я бы оставил решение о том, может ли он обрабатывать входные данные для принятия решения:

bool TryDo(Class1 obj, SomeEnum type)
{
    return obj.Do(type));    
}

Ответ 18

Для меня я предпочитаю второй метод. Большинство моих методов, возвращающих bool, сокращаются таким же образом, когда задействуется простая условная логика.

Ответ 19

Нет. Вторая версия

return (obj.CanDo(type) && Do(obj))

полагается на короткое замыкание поведения && оператор, который является оптимизацией, а не методом управления потоком программы. По моему мнению, это немного отличается от использования исключений для потока программы (и почти так же плохо).

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

Ответ 20

Уже есть несколько хороших ответов, но я подумал, что покажу еще один пример хорошего (удобочитаемого) кода.

bool TryDo(Class1 obj, SomeEnum type)
{
    bool result = false;

    if (obj.CanDo(type))
    {
        result = Do(obj);
    }

    return result;
}

Держите или удалите фигурные скобки назад вокруг тела оператора if в соответствии со вкусом.

Мне нравится этот подход, потому что он показывает, что результат false, если что-то еще не происходит, и я думаю, что это более ясно показывает, что Do() что-то делает и возвращает логическое значение, которое TryDo() использует как возвращаемое значение.