Рефакторинг в Eclipse / Java: примените «Метод извлечения» (Alt Shift M) после этого

#java #eclipse #refactoring

#java #eclipse #рефакторинг

Вопрос:

Я хотел бы знать, возможно ли заменить некоторый код вызовом метода, извлеченного ранее.

Например, у меня есть класс с похожими шаблонами:

 public class ExtractMethodDemo {
    public void doSequence() {
        long n1; n2;
        // Compute and print count
        n1 = 70;
        n2 = compute(n1);                                        // <-- 1st
        System.out.printf("Input %4s, output = %s.%n", n1, n2);  // <-- occurrence
        ....
        // Compute and print count again
        n2 = n2 % 100;
        n1 = compute(n2);                                        // <-- Nth
        System.out.printf("Input %4s, output = %s.%n", n2, n1);  // <-- occurrence
    }
}
  

Я рефакторирую, используя метод, но по какой-то причине некоторые вхождения все еще не реорганизованы (возможно, если Replace additional occurrences... флажок снят, или если тот же код вставлен позже):

 public void doSequence() {
    long n1; n2;
    // Compute and print count
    n1 = 70;
    n2 = doAll(n1);                                          // <--- method extracted
    // ....
    // Compute and print count again
    n2 = n2 % 100;
    n1 = compute(n2);                                        // <--- oops! this one is
    System.out.printf("Input %4s, output = %s.%n", n2, n1);  // <--- still old style
}

private long doAll(long n) {
    long n2; // (BTW: not the n2 declared in doSequence!)
    n2 = compute(n);
    System.out.printf("Input %4s, output = %s.%n", n, n2);
    return n2;
}
  

Возможно ли впоследствии реорганизовать последовательности повторного преобразования:

 public void doSequence() {
    long n1; n2;
    // Compute and print count
    n1 = 70;
    n2 = doAll(n1);
    // ....
    // Compute and print count again
    n2 = n2 % 100;
    n1 = doAll(n2);    // <--- would be great to apply same refactoring afterwards
}
  

Комментарии:

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

Ответ №1:

Возможно, немного лучше, чем повторное встраивание кода, было бы извлечь метод во всем теле нового кода с Replace Additional Occurrences checked, а затем встроить новый метод из исходного вызова. Таким образом, вы меньше рискуете выбрать неправильные строки для извлечения.

Обновление: вот пример:

Вы начинаете с

 extractableCode(1);
extractableCode(2);
extractableCode(3);
  

и извлеките исходный блок, оставив вам

 extractedMethod(1);
extractableCode(2);
extractableCode(3);
...
function extractedMethod(int i) {
    extractableCode(i);
}
  

Ваш способ — встроить extractedMethod, затем повторить извлечение с заменой всех вхождений. Я предлагаю вместо этого извлечь изнутри extractedMethod() :

 extractedMethod(1);
secondExtractedMethod(2);
secondExtractedMethod(3);
...
function extractedMethod(int i) {
    secondExtractedMethod(i);
}
function secondExtractedMethod(int i) {
    extractableCode(i);
}
  

Затем вставьте ваш исходный вызов в первый извлеченный метод:

 secondExtractedMethod(1);
secondExtractedMethod(2);
secondExtractedMethod(3);
...
function secondExtractedMethod(int i) {
    extractableCode(i);
}
  

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

Комментарии:

1. Спасибо. Простите меня, я не понимаю последовательности действий, в частности, что такое «все тело нового кода). В моем примере … 1. Я выбираю две забытые строки (N-е вхождение) 2. Извлекаю в новый метод (например, doAll2). 3. ?