Рефакторинг прочь помеченных петель

После того, как я был убежден , что меченые брейки / продолжается в общей сложности «Ноно» над здесь , мне нужна помощь , чтобы удалить метку из моего кода.

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

Надеюсь, фрагмент кода в принципе понятен…

vectorLoop:
for( int idx = 0; idx < vectorLength; idx++) {
    if( conditionAtVectorPosition( v, idx ) ) continue vectorLoop;

    matrixLoop:
    for( rowIdx = 0; rowIdx < n; rowIdx++ ) {
        if( anotherConditionAtVector( v, rowIdx ) ) continue matrixLoop;
        if( conditionAtMatrixRowCol( m, rowIdx, idx ) ) continue vectorLoop;
    }
    setValueInVector( v, idx );
}     

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

19.08.2008 07:42:02
12 ОТВЕТОВ
РЕШЕНИЕ

Рассматривая представленные решения:

  • Все они выглядят менее читабельными, чем оригинал, в том смысле, что они тратят больше кода на механизм кода, а не на сам алгоритм

  • Некоторые из них сломаны или были до того, как были отредактированы. Больше всего удивляет тот факт, что людям приходится очень серьезно задумываться о том, как писать код без меток и ничего не ломать.

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

  • Рефакторинг соответствующей части кода в метод фактически не имеет смысла: он перестраивает способ размещения кода в файле, но не влияет на его выполнение.

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

34
19.08.2008 10:14:51

Легко, мой хороший человек.

for( int idx = 0; idx < vectorLength; idx++) {
  if( conditionAtVectorPosition( v, idx ) ) continue;

  for( rowIdx = 0; rowIdx < n; rowIdx++ ) {
    if( anotherConditionAtVector( v, rowIdx ) ) continue;
    if( conditionAtMatrixRowCol( m, rowIdx, idx ) ) break;
  }
  if( !conditionAtMatrixRowCol( m, rowIdx, idx ) )
    setValueInVector( v, idx );
}

РЕДАКТИРОВАТЬ: Совершенно верно, вы Андерс. Я отредактировал свое решение, чтобы учесть это.

1
19.08.2008 08:00:10

@ Патрик, вы предполагаете, что вызываете setValueInVector (v, idx); в конце второго цикла все в порядке. Если код должен быть идентичным, логически, он должен быть переписан как-то так:

for (int idx = 0; idx 
1
19.08.2008 07:56:04

Это работает для вас? Я извлек внутренний цикл в метод CheckedEntireMatrix (вы можете назвать его лучше, чем я) - Кроме того, мой Java немного ржавый .. но я думаю, что он передает сообщение

for( int idx = 0; idx < vectorLength; idx++) {
    if( conditionAtVectorPosition( v, idx ) 
    || !CheckedEntireMatrix(v)) continue;

    setValueInVector( v, idx );
}

private bool CheckedEntireMatrix(Vector v)
{
    for( rowIdx = 0; rowIdx < n; rowIdx++ ) {
        if( anotherConditionAtVector( v, rowIdx ) ) continue;
        if( conditionAtMatrixRowCol( m, rowIdx, idx ) ) return false;
    }   
    return true;
}
0
19.08.2008 07:56:50

Гишу имеет правильную идею:

for( int idx = 0; idx < vectorLength; idx++) {
    if (!conditionAtVectorPosition( v, idx ) 
        && checkedRow(v, idx))
         setValueInVector( v, idx );
}

private boolean checkedRow(Vector v, int idx) {
    for( rowIdx = 0; rowIdx < n; rowIdx++ ) {
        if( anotherConditionAtVector( v, rowIdx ) ) continue;
        if( conditionAtMatrixRowCol( m, rowIdx, idx ) ) return false;
    }  
    return true;
}
0
19.08.2008 08:46:08

Я не слишком уверен, чтобы понять первый продолжить. Я бы скопировал Гишу и написал что-то вроде (извините, если есть ошибки):

for( int idx = 0; idx < vectorLength; idx++) {
    if( !conditionAtVectorPosition( v, idx ) && CheckedEntireMatrix(v))
        setValueInVector( v, idx );
}

inline bool CheckedEntireMatrix(Vector v) {
    for(rowIdx = 0; rowIdx < n; rowIdx++)
        if ( !anotherConditionAtVector(v,rowIdx) && conditionAtMatrixRowCol(m,rowIdx,idx) ) 
            return false;
    return true;
}
0
19.08.2008 08:50:59

От чтения вашего кода.

  • Я заметил, что вы удаляете недопустимые векторные позиции в conditionAtVectorPosition, а затем вы удаляете недопустимые строки в anotherConditionAtVector.
  • Кажется, что проверка строк в anotherConditionAtVector является избыточной, поскольку, каково бы ни было значение idx, anotherConditionAtVector зависит только от индекса строки (при условии, что anotherConditionAtVector не имеет побочных эффектов).

Так что вы можете сделать это:

  • Сначала получите действительные позиции с помощью conditionAtVectorPosition (это допустимые столбцы).
  • Затем получите действительные строки, используя anotherConditionAtVector.
  • Наконец, используйте conditionAtMatrixRowCol, используя допустимые столбцы и строки.

Надеюсь, это поможет.

1
19.08.2008 09:09:28

@ Сэди :

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

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

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

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

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

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

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

Я не вижу смысла. Да, это не меняет поведение, как ... рефакторинг?

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

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

0
23.05.2017 12:18:32
Это должны быть комментарии. (Я знаю, что функция не выходила, когда она была опубликована.)
Laurel 27.08.2016 22:01:04

@ Николас

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

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

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

Все рефакторинги в этом потоке эмулируют поведение метки с использованием других языковых функций - как если бы вы переносили код на язык без меток.

1
23.05.2017 10:32:51
Некоторые приходят с потерей производительности при выполнении одного и того же теста дважды, что не всегда может быть тривиальным. Альтернативой этому является хранение и передача логических значений, что становится уродливым.
Нарушение производительности незначительно. Тем не менее, я согласен с тем, что запуск теста дважды не является хорошим решением.

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

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

При этом выполнение одного и того же теста дважды не является оптимальным - в теории.

РЕДАКТИРОВАТЬ: Если подумать, пример на самом деле не ужасное использование меток. Я согласен с тем, что "goto is no-no" , но не из-за такого кода. Использование меток здесь не оказывает существенного влияния на читаемость кода. Конечно, они не являются обязательными и могут быть легко опущены, но не использовать их просто потому, что «использование меток плохо» в данном случае не является хорошим аргументом. В конце концов, удаление меток не делает код намного проще для чтения, как уже прокомментировали другие.

1
19.08.2008 12:22:07

Этот вопрос был не об оптимизации алгоритма - но все равно спасибо ;-)

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

Я задал SO вопрос о соглашении (с меткой во всех заглавных буквах или нет) для меток в Java.

В основном каждый ответ говорил мне: «Не используйте их - всегда есть лучший способ! Рефакторинг!». Поэтому я разместил этот вопрос, чтобы попросить более читаемое (и, следовательно, лучшее?) Решение.

До сих пор я не до конца убежден представленными альтернативами.

Пожалуйста, не поймите меня неправильно. Этикетки злые большую часть времени.

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

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

1
23.05.2017 12:10:51

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


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

То, что я себе представлял, было совсем другим фрагментом кода - приведя пример, я вижу, что он намного чище, чем я думал.

Мои извинения за недоразумение.

1
20.08.2008 04:26:04