Сведения о вопросе

Oleksandr

19:55, 8th August, 2020

Теги

java   refactoring   label    

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

Просмотров: 445   Ответов: 12

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

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

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

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 );
}     

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



  Сведения об ответе

dumai

06:33, 10th August, 2020

Глядя на представленные до сих пор решения:

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

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

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

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

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


  Сведения об ответе

nYU

13:15, 13th August, 2020

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


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

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

Приношу свои извинения за недоразумение.


  Сведения об ответе

прога

08:03, 1st August, 2020

С легкостью, мой добрый человек.

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 );
}

EDIT: вы совершенно правы, Андерс. Я отредактировал свое решение, чтобы учесть и это.


  Сведения об ответе

lats

23:10, 12th August, 2020

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

for( int idx = 0; idx 


  Сведения об ответе

DO__IT

00:14, 5th August, 2020

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

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

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

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

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


  Сведения об ответе

DAAA

17:51, 27th August, 2020

@ Николас

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

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

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

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


  Сведения об ответе

darknet

17:06, 17th August, 2020

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

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

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

Тем не менее, повторение одного и того же теста дважды не является теорией optimal—in.

EDIT: с другой стороны, этот пример на самом деле не является ужасным использованием ярлыков. Я согласен, что "goto is a no-no", но не из-за такого кода. Использование меток здесь фактически не оказывает существенного влияния на читаемость кода. Конечно, они не обязательны и могут быть легко опущены, но не использовать их просто потому, что "using labels is bad" не является хорошим аргументом в этом случае. В конце концов, удаление меток не делает код намного легче для чтения, как уже прокомментировали другие.


  Сведения об ответе

FAriza

01:22, 23rd August, 2020

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

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

Я задал SO вопрос о Конвенции (наличие этикетки во всех заглавных буквах или нет) для этикеток в Java.

В основном каждый ответ говорил мне "do not use them - there is always a better way! refactor!". Поэтому я разместил этот вопрос, чтобы попросить более читабельный (и, следовательно, лучший?) решение.

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

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

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

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


  Сведения об ответе

ASER

23:42, 21st August, 2020

Это работает для вас? Я извлек внутренний цикл в метод 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;
}


  Сведения об ответе

VCe znayu

19:31, 5th August, 2020

У гишу есть правильная идея :

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;
}


  Сведения об ответе

LAST

10:21, 8th August, 2020

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

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;
}


  Сведения об ответе

DINO

17:53, 24th August, 2020

@ Сади :

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

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

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

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

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

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

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

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

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

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться