본문 바로가기

Programming/리팩토링

[리팩토링 기술-1] 중복코드를 처리하는 리팩토링

👀 중복코드의 단점 

 

1. 비슷한 코드인지, 완전히 동일한 코드인지 주의깊게 살펴봐야 한다.

 

2. 코드 변경 시 통일한 모든 곳의 코드를 변경해야 한다.

 

 

 

✍ 사용할 수 있는 리팩토링 기술

1. 함수 추출하기 

 

- 동일한 코드를 여러 메소드에서 사용하는 경우 사용한다.

 

- 무슨 일을 하는 코드인지 알아내려고 노력해야 하는 코드라면,

해당 코드를 함수로 분리하고 

함수 이름으로 "무슨 일을 하는지" 표현할 수 있다. ( = 의도를 드러낼 수 있다. ) 

 

Berfore

 

* printParticipants()

: 깃헙 커넥션을 만들고 -> 리포지토리를 읽어오고 -> 이슈를 찾아서 -> 이슈에서 코멘트를 돌면서

-> 참석한 사람들의 이름을 담아주고 -> 담은 userName을 출력하는 내용이다.

 

import org.kohsuke.github.GHIssue;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GitHub;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

public class StudyDashboard {

    private void printParticipants(int eventId) throws IOException {
        // Get github issue to check homework
        GitHub gitHub = GitHub.connect();
        GHRepository repository = gitHub.getRepository("whiteship/live-study");
        GHIssue issue = repository.getIssue(eventId);

        // Get participants
        Set<String> participants = new HashSet<>();
        issue.getComments().forEach(c -> participants.add(c.getUserName()));

        // Print participants
        participants.forEach(System.out::println);
    }

    private void printReviewers() throws IOException {
        // Get github issue to check homework
        GitHub gitHub = GitHub.connect();
        GHRepository repository = gitHub.getRepository("whiteship/live-study");
        GHIssue issue = repository.getIssue(30);

        // Get reviewers
        Set<String> reviewers = new HashSet<>();
        issue.getComments().forEach(c -> reviewers.add(c.getUserName()));

        // Print reviewers
        reviewers.forEach(System.out::println);
    }

    public static void main(String[] args) throws IOException {
        StudyDashboard studyDashboard = new StudyDashboard();
        studyDashboard.printReviewers();
        studyDashboard.printParticipants(15);
    }
}

 

 

 

 

[  After 

 

- 인텔리제이 기준으로 Refractor -> extract method 기능을 활용하여

중복되는 코드들을 메소드로 추출하였다.

또한 메소드 이름으로 해당 코드가 무슨 일을 하는지 명시하였기 때문에 주석을 없앴다.

(ex) getGhIssue(), getUserNames(), print()

 

 

 

 


2. 코드 정리하기 (slide Statements) 

 

- 관련있는 코드끼리 묶여있어야 코드를 더 쉽게 이해할 수 있다.

 

- 함수에서 사용할 변수를 미리 상단에 정의하기보다,

해당 변수를 사용하는 코드 바로 위에 선언하자.

 

- 관련있는 코드끼리 묶은 다음 함수추출하기를 사용해 더 깔끔하게 분리할 수도 있다.

 

 

 

[ 예시 ] 

 

아래 빨간 박스처럼 위에 변수를 미리 다 선언하면

- 관련된 코드를 한 뭉치로 보기 어렵고 

- 이게 어디 선언됐었지? 하고 다시 위를 올려다 보는 경우가 발생할 수 있고

- 중복되는 코드인지 헷갈릴 수도 있다. 

 

 

 


3. 메소드 올리기 (Pull Up Method)

 

- 상속구조에서 발생할 수 있으며, 하위클래스에서 상위클래스로 중복된 메소드를 올리는 방법이다.

 

- 비슷하지만 일부 값만 다른 경우라면,

"함수 매개변수화하기" 리팩토링을 적용한 이후에 이 방법을 사용할 수 있다.

 

- 하위 클래스에 있는 코드가 상위클래스가 아닌

하위클래스 기능에 의존하고 있다면

"필드 올리기"를 적용한 이후에 이 방법을 적용할 수 있다.

 

- 두 메소드가 비슷한 절차를 따르고 있다면,

"템플릿 메소드 패턴" 적용을 고려할 수 있다.

 

 

[  Berfore 

 

- 각 자식 클래스에서 printUsernames 함수는 비슷한 동작을 수행하는 중복 코드이다.

- 자식 클래스에서의 반복되는 중복 코드의 수정은 일괄 수정이 어렵다.

 

import java.io.IOException;

public class Dashboard {

    public static void main(String[] args) throws IOException {
        ReviewerDashboard reviewerDashboard = new ReviewerDashboard();
        reviewerDashboard.printReviewers();

        ParticipantDashboard participantDashboard = new ParticipantDashboard();
        participantDashboard.printParticipants(15);
    }
}

 

import org.kohsuke.github.GHIssue;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GitHub;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

public class ParticipantDashboard extends Dashboard {

    public void printParticipants(int eventId) throws IOException {
        // Get github issue to check homework
        GitHub gitHub = GitHub.connect();
        GHRepository repository = gitHub.getRepository("whiteship/live-study");
        GHIssue issue = repository.getIssue(eventId);

        // Get participants
        Set<String> participants = new HashSet<>();
        issue.getComments().forEach(c -> participants.add(c.getUserName()));

        // Print participants
        participants.forEach(System.out::println);
    }
}

 

import org.kohsuke.github.GHIssue;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GitHub;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

public class ReviewerDashboard extends Dashboard {

    public void printReviewers() throws IOException {
        // Get github issue to check homework
        Set<String> reviewers = new HashSet<>();
        GitHub gitHub = GitHub.connect();
        GHRepository repository = gitHub.getRepository("whiteship/live-study");
        GHIssue issue = repository.getIssue(30);

        // Get reviewers
        issue.getComments().forEach(c -> reviewers.add(c.getUserName()));

        // Print reviewers
        reviewers.forEach(System.out::println);
    }
}

 

 

[  After 

 

인텔리제이의 Refactor -> Pull Members Up 기능을 통해

하위클래스의 동일한 부분을 메소드로 추출한 후 -> 상위클래스로 올린다. 

 

 

 

 

 

 

 

 

 

출처 : 인프런 강의 (백기선 - 코딩으로 학습하는 리팩토링)