выход для = кода спагетти? - PullRequest
       1

выход для = кода спагетти?

6 голосов
/ 11 декабря 2010

Меня всегда учили иметь один выход из функций и писать код, который не перескакивает везде, является следующим плохим кодом или есть лучший способ написать цикл for без необходимости «выхода для»

dim dt as datatable = FillDataTableFunction()
dim bWrite as boolean = false
for each row as datarow in dt.rows
  if row.item("somecolumn") <> string.empty then 
    bWrite = true
    exit for
  end if 
next

if bWrite then 
  'do stuff
end if

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

Ответы [ 10 ]

20 голосов
/ 11 декабря 2010

«Меня всегда учили» - в какой-то момент жизни люди начинают учиться, а не учат: -)

Не принимайте ничего как Евангелие (даже от меня - если вы не согласны, примите решение самостоятельно). Посмотрите за руководящими принципами, чтобы увидеть , почему они существуют.

Причина, по которой вас учили, что множественные точки выхода плохи, заключается в том, что они часто приводят к коду, которому трудно следовать. Другими словами, 400-строчную функцию, заполненную операторами return, трудно проанализировать с точки зрения ее поведения.

Ваш маленький фрагмент кода не страдает от этого. Следующее правило: если вы видите поток управления на одном экране в редакторе, это нормально. И поскольку в любом редакторе, который я использовал за последние два десятилетия, поместится 12 строк, ваш код будет очень удобочитаемым.

Фактически, я видел код от людей "никогда не используйте несколько точек выхода", который гораздо менее читабелен, чем тот, который был бы получен при нарушении их правил. Как правило, он включает в себя операторы while с несколькими условиями, настолько запутанные, что им приходится разбивать его на несколько строк, и анализ по-прежнему труден.

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

8 голосов
/ 11 декабря 2010

То, что вы называете «кодом спагетти», - это использование старого ключевого слова «goto», которое интенсивно использовалось в прошлом. (например: Assembly, GwBasic и т. д.).

Использование разрывов для выхода из структур цикла и структур принятия решений совершенно естественно.

4 голосов
/ 11 декабря 2010

С вашим фрагментом кода не так много проблем.

Это скорее вопрос вкуса, но я бы выделил это в отдельную функцию:

Public Function ShouldWrite(ByVal dt As DataTable)
    For Each row As DataRow In dt.Rows
        If row.Item("somecolumn") <> String.Empty Then
            Return True
        End If
    Next
    Return False
End Function

Или используйте LINQ:

    Dim bWrite As Boolean = dt.AsEnumerable().Any(Function(row) row.Item("somecolumn") <> String.Empty)
2 голосов
/ 17 августа 2011

Это код, который я получил на работу

bool someboolean = dt.AsEnumerable().Any(row => row.Field<string>("RowName") != "")
2 голосов
/ 11 декабря 2010

Многие «правила» языков (будь то человеческие языки или компьютерные языки) существуют потому, что люди, которые имели представление о том, что казалось хорошим, а что казалось непристойным, хотели помочь другим писать хорошо, и, таким образом, пытались определить, что делает «хорошие» вещи отличается от "неприглядного" материала. Это не соблюдение (или его отсутствие) правила, которое делает что-то хорошее (или плохое). Скорее, именно тот факт, что вещи, которые следуют правилу, (как мы надеемся) обычно лучше, чем те, которые этого не делают, привел к написанию правила в первую очередь.

Мне не очень нравится "Exit For"; Я склонен думать, что в большинстве случаев, когда цикл for-next будет ранним выходом, цикл другого типа был бы лучше. Тем не менее, есть места, где цикл For-Next с ранним выходом чувствует себя хорошо, и поэтому я буду его использовать. Я наиболее склонен досрочно выходить из цикла for-next, если ожидается, что цикл будет выполняться до конца, но создание исключения для случая раннего выхода не будет правильным.

2 голосов
/ 11 декабря 2010

Выход For является социально приемлемым, поскольку он фактически оставляет цикл for внизу.Важно сделать код легким для понимания, особенно для вас, через несколько месяцев, когда вы забыли, что делали сегодня.Если вы привыкнете использовать Exit For, это будет легче распознать сразу, чем любой другой способ выхода из цикла.

2 голосов
/ 11 декабря 2010

Goto считается вредным в современном коде выглядит следующим образом.

def func:

  while stuff:
    ...
    return False
    ...
  end
  return true

end

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

2 голосов
/ 11 декабря 2010

Нужно рассмотреть гораздо больше, чем просто хорошая команда или плохая. Это очень сильно зависит от ситуации.

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

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

Инструкции типа exit имеют тенденцию наследования спагетти, поскольку они совершают переход к другой точке кода, но если переход близок, он не нарушает поток больше, чем, например, оператор if.

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

2 голосов
/ 11 декабря 2010

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

Код, который вы вставили, выглядит очень хорошо для меня, и совсем не похож на спагетти - вы замыкаете цикл, чтобы избежать необходимости повторять 100 000 строк, если вы найдете свой ответ в первых 100. В этом случае я бы сказал, что ваш Exit For полностью оправдан.

2 голосов
/ 11 декабря 2010

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

Однако , есть еще один шаг, который любой может изменить, чтобы улучшитьего / ее код: в цикле вы пытаетесь найти первую строку, в которой есть элемент, соответствующий некоторому условию.Если вы программируете более «функциональным» способом (я не знаю точно, какие возможности есть у VB в этом отношении, но это все же является хорошим соображением при проектировании), скажите:

bWrite = rows.exist(r | r.item("somecolumn") <> string.empty)

Обратите внимание, как работает весь циклсжато в схематическом описании того, что вы ищете.Этот «способ мышления» я считаю гораздо более важным, чем если бы вы использовали выход для или сложное условие в то время ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...