티스토리 뷰

Web

Refactoring With IntelliJ Summary

Aaron 2022. 7. 8. 20:25
반응형

Refactoring With IntelliJ

Change Signature

  • 클래스의 생성자에 parameter 추가

Convert Anonymous to Inner Class

  • 익명 클래스를 내부 클래스로 변환
  • New 또는 생성자에 커서를 위치시키고 리팩토링

Before

public class Class {
    public Interface method() {
        final int i = 0;
        return new Interface() {
            public int publicMethod() {
            return i;}
        };
    }
}

After

public class Class {
    public Interface method() {
        final int i = 0;
        return new MyInterfaceClass(i);
    }
}
public class MyInterfaceClass implements Interface {
    private final int
               i;
    public MyInterfaceClass(int i) {
        this.i = i;
    }
    public int publicMethod() {
        return
               i;
    }
}

Convert to Instance Method

  • static 메서드를 인스턴스 메서드로 변환
  • 메소드명에 커서를 위치시키고 리팩토링

Before

public class MyClass {
     ClassA classA = new ClassA();
     ClassB classB = new ClassB();

     static public void greatMethod(ClassA classA, ClassB classB){
         System.out.println("classA = " + classA);
         System.out.println("classB = " + classB);
     }
     public void myMethod(){
         MyClass.greatMethod(classA, classB);
     }
}

After

public class MyClass {
    ClassA classA = new ClassA();
    ClassB classB = new ClassB();

    public void myMethod(){
        classB.greatMethod(classA);
    }
}

public class ClassB {
    public void greatMethod(ClassA classA) {
        System.out.println("classA = " + classA);
        System.out.println("classB = " + this);
    }
}

Encapsulate Fields

  • public 필드를 private로 캡슐화 및 getter/setter 생성
  • 필드명에 커서를 위치시키고 리팩토링

Before

public class Class {
    public String aString;
}

After

public class Class {
    private String aString;
    public void setaString(String aString) {
        this.aString = aString;
    }
    public String getaString() {
        return aString;
    }
}

Introduce Constants

  • 변수를 private static final 로
  • 변수에 커서를 위치시키고 리팩토링

Before

public class Class {
    public void method() {
        ArrayList list = new ArrayList();
        list.add("string");
        anotherMethod("string");
    }

    private void anotherMethod(String string) {
    }
}

After

public class Class {
    private static final String STRING = "string";

    public void method() {
        ArrayList list = new ArrayList();
        list.add(STRING);
        anotherMethod(STRING);
    }

    private void anotherMethod(String string) {
    }
}

Extract Interface

  • 인터페이스 추출

Before

// File AClass.java
class AClass {
    public static final double CONSTANT = 3.14;

    public void publicMethod() {
    }

    public void secretMethod() {

    }
}

After

// File AClass.java
class AClass implements AnInterface {
    public void publicMethod() {
    }

    public void secretMethod() {
    }

    // File AnInterface.java
    public interface AnInterface {
        double CONSTANT = 3.14;

        void publicMethod();
    }
}

Extract Method

  • 메서드 추출

Before

public void method() {
    int a=1;
    int b=2;
    int c=a+b;
    int d=a+c;
}

After

public void method() {
    int a=1;
    int b=2;
    int c=add(a,b);
    int d=add(a,c);
}
...
private int add(int a, int b) {
    return a+b;
}

Extract Super Class

  • 슈퍼 클래스로 추출

Before

// File Class.java
public class Class {
    public int varInt;
    private double varDouble;
    public static final int CONSTANT = 0;
    public void publicMethod() {
        ...
    }
    public void hiddenMethod() {
        ...
    }
    public void setVarDouble(double var) {
        this.varDouble = var;
    }
    public double getVarDouble() {
        return
                  varDouble;
    }
}

After

// File Class.java
public class Class extends SuperClass {
    public int varInt;
    public void publicMethod() {
    ...
    }
    public void hiddenMethod() {
    ...
    }
}

// NEW file SuperClass.java
public abstract class SuperClass {
    private double varDouble;
    public static final int CONSTANT = 0;
    public abstract void publicMethod();
    public void setVarDouble(double var) {
        this.varDouble = var;
    }
    public double getVarDouble() {
        return varDouble;
    }
}

Introduce Variable

  • 중복 변수를 필드로
  • 변수 선택 후 리팩토링

Before

public void method() {
    int a = 1;
...
    int b = a + anotherClass.intValue();
    int c = b + anotherClass.intValue();
}

After

public void method() {
    int a = 1;
...
    int number = anotherClass.intValue();
    int b = a + number;
    int c = b + number;
}

Introduce Parameter

  • 변수를 파라미터로 추출

Before

public class HelloWorldPrinter {
    public static void print() {
        System.out.println(generateText());
    }
    private static String generateText() {
        return "Hello, World!".toUpperCase();
    }
}

After

public class HelloWorldPrinter {
    public static void print() {
        System.out.println(generateText("Hello, World!"));
    }
    private static String generateText(String text) {
        return text.toUpperCase();
    }
}

Extract Delegate

  • 위임 클래스로 추출
  • Before
public class Foo {
    private String b;
    public String getInfo() {
        return ("(" + b + ")");
    }
...
}

public class Bar {
    Foo foo;
    String t2 = foo.getInfo();
...
}
  • After
public class Foo {
    private final Info info = new Info();
    public String getInfo() {
        return info.getInfo();
    }
...
}

public class Info {
    private String b;
    public Info() {}
    public String getInfo() {
        return ("(" + b + ")");
    }
}

public class Bar {
    Foo foo;
    String t2 = foo.getInfo();
...
}

Replace Method with Method Object

  • 메서드를 메서드 개체로 바꾸기

Replace Conditional Logic with Strategy Pattern

  • 조건부 논리를 전략 패턴으로 바꾸기

Generify

  • 일반화

Before

List list = new LinkedList();
list.add("string");

After

List<String> list = new LinkedList<>();
list.add("string");

Inline Constructor

  • 불필요한 생성자를 인라인

Before

public class Class {
    public int varInt;
    public Class() {
        this(0);
    }

    public Class(int i) {
        varInt=i;
    }

    public void method() {
        Class aClass=new Class();
        ...
    }
}

After

public class Class {
    public int varInt;
    public Class(int i) {
        varInt=i;
    }
    public void method() {
        Class aClass=new Class(0);
        ...
    }
} 

Inline Superclass

  • 불필요한 슈퍼클래스를 인라인

Before

public class Bar {
    ...
    int calculations1() { ... }
    int calculations2() { ... }
}

class Foo extends Bar {
    int someMethod() {
        ...
        if (something > calculations1()) {
            ...
            return calculations2();
        }
        ...
    }
}

After

class Foo {
    ...
    int someMethod() {
        ...
        if (something > calculations1()) {
            ...
            return calculations2();
        }
        ...
    }
    int calculations1() {...}
    int calculations2() {...}
}

Inline To Anonymous Class

  • 익명 클래스로 인라인

Before

import java.util.*;
public class Main {
    public class MyComparator implements Comparator<String> {
        @Override
        public int compare(String s1, String s2) {
            return 0;
        }
    }

    void sort(List<String> scores) {
        scores.sort(new MyComparator());
    }
}

After

import java.util.*;

public class Main {

    void sort(List<String> scores) {
        scores.sort((s1, s2) -> 0);
    }
}

Invert Boolean

  • 불린 결과값을 반대로 변환

Before

private double a;
...
public boolean method() {
    if (a > 15 && a < 100) {
        a = 5;
        return true;
    }
    return false;
}

After

private double a;
...
public boolean method() {
    if (a > 15 && a < 100) {
        a = 5;
        return false;
    }
    return true;
}

Make Static

  • inner class 또는 인스턴스 메서드를 static 으로

Before

class CallHierarchySample {
     private void foo(int i) { bar(i);}
     private void bar(int i) { baz(i);}
     private void baz(int i) { }
}

After

class CallHierarchySample {
    private static void foo(int i) { bar(i);}
    private static void bar(int i) { baz(i);}
    private static void baz(int i) { }
}

Migrate

  • 프로젝트에 사용된 버전을 전환

Copy Class

  • 클래스를 새로운 이름으로 복사

Move Method

  • 메서드를 다른 클래스로 이동

Pull Members Up

  • 클래스들이 동일한 필드/메서드를 가지고 있는 경우 필드/메서드를 슈퍼클래스/인터페이스로 이동

Before

// File Class.java
public class Class extends SuperClass {
    public void publicMethod() {

    }

    public void hiddenMethod() {
    }
}


// File SuperClass.java
public abstract class SuperClass {
    public abstract void publicMethod();
}

After

// File Class.java
public class Class extends SuperClass {
    public void publicMethod() {

    }
}

// File SuperClass.java
public abstract class SuperClass {
    public abstract void publicMethod();

    public void hiddenMethod() {

    }
}

Remove Middleman

  • 특정 클래스에서 위임 메서드에 대한 모든 호출을 위임된 필드에 직접 해당하는 호출로 변경

Before

public class Foo {
    Bar bar;
    public Foo getImpValue() {
        return bar.getImpValue();
    }
}

public class Bar {
    private Foo impValue1;
    public Bar(Foo impValue) {
        impValue1 = impValue;
    }
    public Foo getImpValue() {
        return impValue1;
    }
}

public class Client {
   Foo a;
   Foo impValue = a.getImpValue();
}

After

public class Foo {
    Bar bar;
    public Bar getbar() {
        return bar;
    }
}

public class Bar {
    private Foo impValue1;
    public Bar(Foo impValue) {
        impValue1 = impValue;
    }
    public Foo getImpValue(){
        return impValue1;
    }
}

public class Client {
   Foo a;
   Foo impValue = a.getbar().getImpValue();
}

Replace Constructor with Builder

  • 생성자를 빌더로 전환
  • 생성자를 숨길 수 있고, 새로 생성된 생성자 클래스 또는 기존 생성자 클래스에 대한 참조를 대체
  • 생성자의 필수값 설정도 가능

Before

public class apples {
    public static void main(String[] args) {
        variety varietyObject = new variety("Red Delicious");
        varietyObject.saying();
    }
}

// variety class

public class variety {
    private String string;

    // constructor

    public variety(String name) {
        string = name;
    }

    public void setName(String name) {
        string = name;
    }

    public String getName() {
        return string;
    }

    public void saying() {
        System.out.printf("On sale today : %s\n", getName());
    }
}

After

// variety builder is created

public class varietyBuilder {
    private String name;

    public varietyBuilder setName(String name) {
        this.name = name;
        return this;
    }

    public variety createVariety() {
        return new variety(name);
    }
}

// varietyBuilder added instead of constructor to the main class "apples.java"

public class apples {
    public static void main(String[] args) {
        variety varietyObject = new varietyBuilder().setName("Red Delicious").createVariety();
        varietyObject.saying();
    }
}

Replace Constructor with Factory Method

  • 생성자를 숨기고 클래스의 새 인스턴스를 반환하는 정적 메서드로 대체

Before

// File Class.java
public class Class {
    public Class(String s) {
        ...
    }
}

// File AnotherClass.java
public class AnotherClass {
    public void method() {
        Class aClass = new Class("string");
    }
}

After

// File Class.java
public class Class {
    private Class(String s) {
        ...
    }
    public static Class createClass(String s) {
        return new Class(s);
    }
}

// File AnotherClass.java
public class AnotherClass {
    public void method() {
        Class aClass = Class.createClass("string");
    }
}

Replace Inheritance with Delegation

  • 슈퍼클래스의 상속을 유지하면서 extends 제거
  • 슈퍼클래스의 메서드는 내부 클래스를 통해 호출

Before

// File Class.java
public class Class extends SuperClass {
    public int varInt;
    public void openMethod() {
        ...
    }
}

// File SuperClass.java
public abstract class SuperClass {
    public static final int CONSTANT=0;
    public abstract void openMethod();
    public void secretMethod() {
        ...
    }
}

After

// File Class.java
public class Class {
    public int varInt;
    private final MySuperClass superClass = new MySuperClass();
    public SuperClass getSuperClass() {
        return superClass;
    }
    public void openMethod() {
        superClass.openMethod();
    }
    private class MySuperClass extends SuperClass {
        public void openMethod() {
            ...
        }
    }
}

// File SuperClass.java UNCHANGED
public abstract class SuperClass {
    public static final int CONSTANT=0;
    public abstract void openMethod();
    public void secretMethod() {
        ...
    }
}

Replace Temp with Query

  • 변수의 초기화 식을 메서드로 추출
  • 변수의 선언이 제거되고 쿼리 메서드를 다른 메서드에서 사용

Before

public void method() {
    String str ="str";
    String aString = returnString().concat(str);
    System.out.println(aString);
}

After

public void method() {
    String str ="str";
    System.out.println(aString(str));
}
private String aString(String str) {
    return returnString().concat(str);
}

Type Migration

  • 타입 변경

Before

int f;
void bar(int i) {}
void foo() {
    bar(f);
}

After

String f;
void bar(String i) {}
void foo() {
    bar(f);
}

Wrap Return Value

  • 반환 값을 래퍼 클래스로 변경

Before

class Order {
    String customer;

    String getCustomer() {
        return customer;
    }
}

After

class Order {
    String customer;

    Wrapper getCustomer() {
        return new Wrapper(customer);
    }
}

public class Wrapper {
    private final String value;

    public Wrapper(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

Reference

IntelliJ IDE Code refactoring

반응형

'Web' 카테고리의 다른 글

[Troubleshooting] Enum Class(싱글톤)의 동시성 이슈  (0) 2022.11.21
[Vue.js] Vue.js 시작하기  (0) 2022.07.30
[NoSQL] MongoDB 탐구하기  (0) 2022.03.27
[Message Queue] Apach Kafka 탐구하기  (0) 2022.03.22
[우아한 Tech] 우아한 ATDD  (0) 2022.02.22
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday