Skip to content

BE 코드 컨벤션

Jo Hyeong-Ik edited this page Jul 19, 2024 · 1 revision

코드 컨벤션

⭐️ InteliiJ 코드 스타일은 wooteco 컨벤션을 따른다.

  • 부가적으로, 클래스 선언 후 개행을 필수로 추가한다.

⭐️ 함수 매개변수 final은 필드에 한하여 허용한다.

⭐️ public 에서 파생된 메서드들은 문맥 근처에 둔다.

  • 주변에 모아 둠 : 논리적인 흐름을 파악하고 싶을 때 굳, private 함수를 재사용 한다면, 그 위치를 어디에 두어야 하는가?
    • 구현 관점에서 조금 버벅이겠지만 구현에 문제는 없을듯
    • 디버깅 관점에서 break point 찾아가니까 문제 없을듯
    • 코드 리뷰 관점에서도 문제 없음
    • 질문
      • 그럼 위 → 아래 호출 순서에 따라 분리된 메서드 순서대로 정리하는지
  • 접근 제어자 기준으로 큰 순으로 몰아두고 반환값을 같은 것끼리 모아둔다.

⭐️ 코드 라인이 한 줄에 120자를 넘긴 경우

⭐️ 1. 메서드 파라미터

아래는 가장 기본의 형태이다. 120자가 안넘어가는 경우이다.

public ReservationService(ReservationRepository reservationRepository) {
}

120자가 넘어가서 괄호에서 개행을 진행했는데, 만약 120자가 안넘어가면 추가 개행하지 않는다.

public ReservationService(
        ReservationRepository reservationRepository, ReservationTimeRepository reservationTimeRepository
) {
}

만약 120자를 넘어갈 시, 모든 파라미터들에 대해 개행을 한다.

public ReservationService(
        ReservationRepository reservationRepository,
        ReservationTimeRepository reservationTimeRepository,
        ThemeRepository themeRepository,
        MemberRepository memberRepository,
        ReservationWaitingRepository reservationWaitingRepository, 
        PaymentService paymentService
) {
}

⭐️ 2. 메서드 체이닝

  • 기본적으로 1개의 체인을 제외한 나머지는 줄바꿈을 한다.
    • stream()은 용인한다.
public List<String> convertToString(int[] array) {
    return Arrays.stream(array)
         .map()
         .filter()
         .toList();
}

⭐️ 3. 함수 호출 시

List<ReservationTime> bookedTimes = reservationTimeRepository.findReservedTimeByThemeAndDate(
               request.getDate(), 
               request.getThemeId()
);

⭐️ 4. 비교 연산자가 여럿일 경우

private boolean isAllRight() {
	  return isJazz() 
			  && isPedro() 
			  || isMark()
}

⭐️ 패키지 구조

MVC 패키지 구조를 상위 패키지로 가져가되, 패키지 하위를 도메인 별로 나눈다.

https://www.inflearn.com/questions/16046/프로젝트-폴더-구조와-강의-일정에-관하여-질문이-있습니다

project
- controller
  - blog
  - member
- service
  - blog
	  - dto
  - member
	  - dto
- domain
  - blog
  - member

⭐️ Response를 내려줄 때 컬렉션을 감싼 개별적인 Dto 대신, 제네릭 T 타입 Result로 추상화하는 것에 대하여

→ 컬렉션 단일 필드만 반환하는데 제네릭 타입이 일치하지 않아서 최종적으로 감싼 응답 Dto를 만드는게 너무 번거롭다. → 그게 많아지게 되면 xxxDto 를 감싸기만 한 xxxDtos 클래스가 너무 많아져서 관리가 불가능해지고 별로 좋지 않다고 생각 → 그래서 기존 xxxDtos를 추상화한 Result 클래스를 만들어서 이것을 활용해보자 → 컨트롤러에서 변환하기

public class xxxController {
	
	private Result<xxx> memberV2() {
		...
		return new Result(xxx);
	}
}
@Data
@AllArgsConstructor
class Result<T> {
	private T data;
}

⭐️ 정적 팩토리 메서드

  • enum, record, utils 이외의 클래스에서는 사용을 금한다.
  • 인자 1개는 from, 2개 부터 of 네이밍

⭐️ 테스트

메서드 네이밍 컨벤션은 camelCase로 나타낸다

  • @DisplayName() 컨벤션
    • ~하면 ~한다.
  • 테스트 데이터 어떻게 할건지

Mock vs Fake

  • 알아서 잘 사용하되 Mock을 남발하지 말자
  • 외부 시스템은 Mock이 좋을지도..?
  • Fixture, SQL

테스트는 각각 아래와 같이 구현한다

  • controller
    • RestAssured를 이용하여 구현한다
  • service
    • 통합테스트로 구현한다.
  • repository
    • 직접 짠 쿼리만 테스트 한다.
  • domain
    • 기본적으로 모두 테스트 한다.

⭐️ 어노테이션 순서

@DisplayName()
@Test
public void test() {
}

@Table("tbl_name")
@Entity
public class Entity {
   
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "reservation_time_id") // @JoinColumn을 명시하자.
    private ReservationTime reservationTime;
     
    private int age;
    private String name;
    
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Reservation other = (Reservation) o; // other로 명명
        return Objects.equals(id, other.id);
    }
	  
	  @Override
    public int hashCode() {
        return Objects.hashCode(id);
    }
}

https://hyeon9mak.github.io/omit-join-column-when-using-many-to-one

⭐️ 검증은 DTO와 도메인 모두 하되 아래의 제약을 따른다.

  • dto : 형식 값 (ex. 이메일 형식, null 체크 등)
  • 도메인 : 좀 더 로직과 가까운.. (ex 로또 번호는 서로 같을 수 없다.)

⭐️ 인스턴스 메서드 위치 및 명명

Controller

  • CRUD 순으로 메서드를 선언한다.
  • CREATE: create
    • reservationService.create()
  • READ: find
  • UPDATE:
  • DELETE: delete

Service

  • CRUD 순으로 메서드를 선언한다.
  • CREATE: create
  • READ: findAllByXXX, find
  • UPDATE:
  • DELETE: deleteByXXX, delete

DTO

  • xxxRequest, xxxResponse로 명명한다.
  • 의미만 분명하게 부탁드립니다.
  • 예시
    • ReservationCreateRequest
    • PopularThemeRequest
    • ${Domain}${Something}${Request/Response}

고민 중

컨벤션 철회 목록

😇 단, import는- naver 컨벤션 활용한다.

  • static import는 테스트 코드에서만 사용한다.

  • 아래 순서로 import를 작성한다.

    import static java.*
    <blank line>
    import static javax.*
    <blank line>
    import static all other imports
    <blank line>
    import java.*
    <blank line>
    import javax.*
    <blank line>
    import all other imports