개발자 피터
Peter's Dev Blog
개발자 피터
전체 방문자
오늘
어제
  • 분류 전체보기 (77)
    • 🧑🏻‍💻 Develop (13)
      • Devops (3)
      • Elasticsearch (3)
      • Design Pattern (1)
      • SQL (4)
      • Architecture (1)
      • APM (1)
    • 💻 Service (7)
      • E-ROOM (3)
      • Briefing (4)
    • 💡 Problem Solving (43)
      • Baekjoon (40)
      • Programmers (2)
    • 📚 Reading (12)
      • Tech (9)
      • Self-Help (3)
    • 💬 Etc (1)
    • 📈 Retrospective (1)

블로그 메뉴

  • 🌟 깃허브
  • 🏷️ 태그 클라우드
  • 📝 방명록

공지사항

인기 글

태그

  • 독서
  • 문자열
  • elasticsearch
  • java
  • 백트래킹
  • SQL
  • 그리디
  • 백준
  • MySQL
  • briefing
  • 구현
  • Programmers
  • 브루트포스
  • E-ROOM
  • boj

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
개발자 피터

Peter's Dev Blog

💻 Service/E-ROOM

Refactoring with SonarLint - Repository

2023. 7. 11. 17:10
728x90
반응형

SonarLint라는 툴이 권장하는 방향으로 코드 리팩토링을 하면서 리팩토링 규칙들을 기록하는 글입니다! 중복되는 규칙들은 한 번만 작성하였습니다.

💡 BuildingCustomRepositoryImpl

스크린샷 2023-07-10 오후 8.40.24.png

  • 반복되는 문자열 리터럴을 상수로 정의하라
    • private static final 키워드로 상수를 정의하여 코드에 반영했습니다.
    • final vs static final
      • final만 사용하면 해당 필드는 변경이 불가능하지만 클래스의 각 인스턴스마다 그 필드의 복사본이 생성됩니다. 이는 필요 이상으로 메모리를 사용하게 되므로, 특히 그 필드의 값이 모든 인스턴스에서 동일할 경우, 비효율적일 수 있습니다.
      • static final을 사용하면 해당 필드는 클래스 레벨에서 한번만 초기화되며 모든 인스턴스에서 공유하게 됩니다. 따라서 메모리 사용량이 줄어들고 효율성이 향상됩니다.
// Noncompliant Code
if (!isEmpty(pageable.getSort())) {
    for (Sort.Order order : pageable.getSort()) {
        Order direction = order.getDirection().isAscending() ? Order.ASC : Order.DESC;
        switch (order.getProperty()) {
            case "id":
                OrderSpecifier<?> orderId = QueryDslUtil.getSortedColumn(direction, building, "id");
                ORDERS.add(orderId);
                break;
            case "reviewCnt":
                OrderSpecifier<?> orderReviewCnt = QueryDslUtil.getSortedColumn(direction, building.buildingSummary, "reviewCnt");
                ORDERS.add(orderReviewCnt);
                break;
            case "avgScore":
                OrderSpecifier<?> orderScore = QueryDslUtil.getSortedColumn(direction, building.buildingSummary, "avgScore");
                ORDERS.add(orderScore);
                break;
            default:
                break;
        }
    }
} else {
    OrderSpecifier<?> orderId = QueryDslUtil.getSortedColumn(Order.DESC, building, "id");
    ORDERS.add(orderId);
}

// Compliant Solution
// 상수 정의
private static final String ID = "id";
private static final String REVIEW_CNT = "reviewCnt";
private static final String AVG_SCORE = "avgScore";

// 메소드내에 있는 로직 변경
if (!isEmpty(pageable.getSort())) {
    for (Sort.Order order : pageable.getSort()) {
        Order direction = order.getDirection().isAscending() ? Order.ASC : Order.DESC;
        switch (order.getProperty()) {
            case ID:
                OrderSpecifier<?> orderId = QueryDslUtil.getSortedColumn(direction, building, ID);
                ORDERS.add(orderId);
                break;
            case REVIEW_CNT:
                OrderSpecifier<?> orderReviewCnt = QueryDslUtil.getSortedColumn(direction, building.buildingSummary, REVIEW_CNT);
                ORDERS.add(orderReviewCnt);
                break;
            case AVG_SCORE:
                OrderSpecifier<?> orderScore = QueryDslUtil.getSortedColumn(direction, building.buildingSummary, AVG_SCORE);
                ORDERS.add(orderScore);
                break;
            default:
                break;
        }
    }
} else {
    OrderSpecifier<?> orderId = QueryDslUtil.getSortedColumn(Order.DESC, building, ID);
    ORDERS.add(orderId);
}
  • 제네릭을 사용할 때는 타입 매개변수를 명시적으로 제공하여라
    • 로직에 의해 여러 타입이 들어갈 수 있어서 와일드카드를 써주었습니다.
    • 설명
      • 제네릭 타입을 사용하면 타입의 안전성을 컴파일 타임에 보장할 수 있습니다.
      • 예를 들어, List과 같은 경우, 컴파일러는 이 리스트에 문자열만 추가할 수 있도록 검사합니다.
      • 그러나 제네릭을 원시 타입으로 사용하면, 이런 타입 검사를 받지 않고 런타임에 오류가 발생할 수 있습니다.
// Noncompliant Code
public List<OrderSpecifier> getAllOrderSpecifiers(Pageable pageable) {
    List<OrderSpecifier> ORDERS = new ArrayList<>();
        ...
    return ORDERS;
}

// Compliant Solution
public List<OrderSpecifier<?>> getAllOrderSpecifiers(Pageable pageable) {
    List<OrderSpecifier<?>> ORDERS = new ArrayList<>();
        ...    
        return ORDERS;    
}
  • 산술 피연산자는 변수에 할당전에 타입을 캐스트 해라
    • 피연산자 1을 1L로 변경해주었습니다.
    • 설명
      • 예를 들어, 기본적으로, 정수 연산의 결과는 항상 정수입니다. 즉, 정수 간의 나눗셈을 수행하면, 그 결과는 소수점 이하를 버린 정수가 됩니다.
      • 이를 float나 double에 할당하면, 이 정수 값이 float나 double로 자동 타입 변환이 이루어지지만, 소수점 이하의 정보는 이미 연산 과정에서 손실된 상태입니다.
      • 이러한 문제를 해결하려면, 연산을 수행하기 전에 적어도 한 쪽 피연산자를 최종 결과 타입으로 캐스트(형변환)해야 합니다.
// Noncompliant Code
@Override
public List<Building> searchBuildings(String params, List<Double> cursorIds, Pageable pageable) {
    return searchBuildingsQuery(cursorIds, pageable).andThen(customOrderBy(pageable)).apply(params)
            .limit(pageable.getPageSize() + 1)
            .fetch();
}

// Compliant Solution
@Override
public List<Building> searchBuildings(String params, List<Double> cursorIds, Pageable pageable) {
    return searchBuildingsQuery(cursorIds, pageable).andThen(customOrderBy(pageable)).apply(params)
            .limit(pageable.getPageSize() + 1L)
            .fetch();
}
  • 지역 변수와 메소드 파라미터 명은 ^[a-z][a-zA-Z0-9]*$ 정규식에 맞게 지어라
    • 대문자로 되어있던 지역변수를 소문자로 변경했습니다.
// Noncompliant Code
List<OrderSpecifier<?>> ORDERS = new ArrayList<>();

// Compliant Solution
List<OrderSpecifier<?>> orders = new ArrayList<>();

 

💡 ReviewCustomRepositoryImpl

스크린샷 2023-07-11 오후 4.45.32.png

  • switch 문에 default 절을 추가하라.
    • default 절에서는 id에 대해 내림차순 정렬하도록 추가했습니다.
// Noncompliant Code
switch (order.getProperty()) {
    case "id":
        OrderSpecifier<?> orderId = QueryDslUtil.getSortedColumn(direction, review, "id");
        ORDERS.add(orderId);
        break;
    case "likeCnt":
        OrderSpecifier<?> orderLikeCnt = QueryDslUtil.getSortedColumn(direction, review.reviewSummary, "likeCnt");
        ORDERS.add(orderLikeCnt);
        break;
    case "score":
        OrderSpecifier<?> orderReviewCnt = QueryDslUtil.getSortedColumn(direction, review.reviewToReviewCategoryList, "score");
        ORDERS.add(orderReviewCnt);
}

// Compliant Solution
switch (order.getProperty()) {
    case "id":
        OrderSpecifier<?> orderId = QueryDslUtil.getSortedColumn(direction, review, "id");
        ORDERS.add(orderId);
        break;
    case "likeCnt":
        OrderSpecifier<?> orderLikeCnt = QueryDslUtil.getSortedColumn(direction, review.reviewSummary, "likeCnt");
        ORDERS.add(orderLikeCnt);
        break;
    case "score":
        OrderSpecifier<?> orderReviewCnt = QueryDslUtil.getSortedColumn(direction, review.reviewToReviewCategoryList, "score");
        ORDERS.add(orderReviewCnt);

}
728x90
반응형
저작자표시 (새창열림)

'💻 Service > E-ROOM' 카테고리의 다른 글

Refactoring with SonarLint - Service  (0) 2023.07.10
Refactoring with SonarLint - Controller  (0) 2023.07.07
    '💻 Service/E-ROOM' 카테고리의 다른 글
    • Refactoring with SonarLint - Service
    • Refactoring with SonarLint - Controller
    개발자 피터
    개발자 피터
    Backend Engineer 🔥

    티스토리툴바