Java 리펙토링 #1. Mysterius Name

Koboolean·2024년 6월 28일

Java

목록 보기
2/3

참고사항

해당 포스팅은 인프런 백기선님의 '리팩토링'을 학습 후 정리한 내용입니다.


Sec1) 냄새 1. 이해하기 힘든 이름

(Mysterius Name)

  • 함수, 변수, 클래스, 모듈의 이름 등 모두 어떤 역할을 하는지 어떻게 쓰이는지 직관적으로 정의되어있다면 해당 코드를 보지 않아도, 쉽게 이해할 수 있을것이다. 이처럼 깔끔한 코드에서 가장 중요한 것이 바로 "좋은 이름" 이다.

Sec2) 예제코드

  • 다음의 예제코드를 리펙토링 해보도록 하자.
public class StudyDashboard {

    private Set<String> usernames = new HashSet<>();

    private Set<String> reviews = new HashSet<>();

    private void studyReviews(GHIssue issue) throws IOException {
        List<GHIssueComment> comments = issue.getComments();
        for (GHIssueComment comment : comments) {
            usernames.add(comment.getUserName());
            reviews.add(comment.getBody());
        }
    }

    public Set<String> getUsernames() {
        return usernames;
    }

    public Set<String> getReviews() {
        return reviews;
    }

    public static void main(String[] args) throws IOException {
        GitHub gitHub = GitHub.connect();
        GHRepository repository = gitHub.getRepository("whiteship/live-study");
        GHIssue issue = repository.getIssue(30);

        StudyDashboard studyDashboard = new StudyDashboard();
        studyDashboard.studyReviews(issue);
        studyDashboard.getUsernames().forEach(System.out::println);
        studyDashboard.getReviews().forEach(System.out::println);
    }
}

Sec3) 사용할 수 있는 리펙토링 기술

1. 함수선언 변경하기 (Change Function Declaration)

  • 메서드명은 기본적으로는 동사로 시작한다. 다른 타입으로 전환하는 메서드나 빌더 패턴을 구현한 클래스의 메서드에는 전치사를 쓸 수 있다.
  • 좋은 이름을 작성하는 일 예로는 함수에 주석을 직관적으로 작성한 다음, 주석을 함수의 이름으로 만들어보는 것이다.
    	```
    	/** 
    * 덧셈을 수행하여 결과를 리턴하는 함수
    * @param x
    * @param y
    * @return int
    */
    public int getSumResult(int x, int y){
    return x+y;
    }
    	```
  • 함수의 매개변수는 함수 내부의 문맥을 결정한다.
    • 예로 전화번호 포메팅 함수로 어떤 타입으로 받을 것인지, 함수 내부에 많은 정보를 줄것인지, 필요한 것만 줄것인지 등
    • 함수의 매개변수는 의존성을 결정한다.
      • 예로 Payment 만기일 계산 함수, Payment에 종속된다면 Payment타입을, date속성만 필요하다면 date만 넘겨줄것인지 등
    • Intellij에서 함수명 한번에 변경하기 (Shift + F6)

      * 이름 변경을 누르면 선택한 함수명을 변경할 수 있게된다.

    • Intellij에서 함수 시그니처 변경하기 (Ctrl + F6 타입, 이름, 매개변수 예외 등 수정)

2. 변수 이름 변경하기 (Rename Variable)

  • 더 많이 사용되는 변수일 수록 그 이름이 더욱 중요해진다.

    • 람다식에서 사용하는 변수 vs 함수의 매개변수
  • 다이나믹 타입을 지원하는 언어에서는 타입을 이름에 넣기도 하지만, 클린코드에서는 이러한 코드는 클린하지 않은 변수 명으로 정하고 있다.

	strServerValue = "local";
	intServerValue = 1;
  • 여러 함수에 걸쳐 쓰이는 필드 이름에는 더 많이 고민하고 이름을 짓는다.

3. 필드 이름 바꾸기 (Rename Field)

	private Set<String> usernames = new HashSet<>();
  • 해당 코드는 리뷰어의 username들을 가져오는 Set 컬렉션이기 때문에 usernames로 작성했지만, 조금더 직관적으로 reviwers라고 명시해 줄 수 있을 것이다.
	private Set<String> reviewers = new HashSet<>();
  • Record 자료 구조의 필드 이름은 프로그램 전반에 걸쳐 참조될 수 있기 때문에 매우 중요하다.

    Record 자료 구조: 특정 데이터와 관련있는 필드를 묶어놓은 자료 구조

  • 자바 14 버전부터 지원. (record 키워드)
  • final와 같이 immutable하다.
  • 자바에서는 Getter와 Setter 메소드 이름도 필드의 이름과 비슷하게 간주할 수 있다.
  • 관련있는 데이터를 담아두는 데이터 클래스이다.
public class SampleRecord {
   private final String name;
   private final Integer age;
   private final Address address;
 
   public SampleRecord(String name, Integer age, Address address) {
      this.name = name;
      this.age = age;
      this.address = address;
   }
 
   public String getName() {
      return name;
   }
 
   public Integer getAge() {
      return age;
   }
 
   public Address getAddress() {
      return address;
   }
}
  • 위와 같은 코드가 있다고 가정하자.
    • 해당 클래스는 모든 인스턴스 필드를 초기화하는 생성자를 가지고 있다.
    • 모든 필드는 final로 정의되어 있다.
    • 각각 필드의 getter를 가지고 있다.
    • 이러한 클래스 같은 경우 record 타입의 클래스로 변경할 수 있다.
public record SampleRecord(
   String name,
   Integer age,
   Address address
) {}

Sec4) 리펙토링 후의 예제코드

public class StudyDashboard {

    private Set<StudyReview> studyReviews = new HashSet<>();

    /**
     * 스터디 리뷰 이슈에 작성되어 있는 리뷰어 목록과 리뷰를 읽어옵니다.
     * @throws IOException
     */
    private void loadReviews() throws IOException {
        GitHub gitHub = GitHub.connect();
        GHRepository repository = gitHub.getRepository("whiteship/live-study");
        GHIssue issue = repository.getIssue(30);

        List<GHIssueComment> reviews = issue.getComments();
        for (GHIssueComment review : reviews) {
            studyReviews.add(new StudyReview(review.getUserName(), review.getBody()));
        }
    }

    public Set<StudyReview> getStudyReviews() {
        return studyReviews;
    }

    public static void main(String[] args) throws IOException {
        StudyDashboard studyDashboard = new StudyDashboard();
        studyDashboard.loadReviews();
        studyDashboard.getStudyReviews().forEach(System.out::println);
        studyDashboard.getStudyReviews().forEach(System.out::println);
    }
}

public record StudyReview(String reviewer, String review){
}

Sec5) 참조

Google Java Naming Guide

profile
WEB 개발자의 끄적끄적 개발일기

0개의 댓글