https://techblog.woowahan.com/2614/
코드리뷰 적응기(feat. 파일럿 프로젝트) | 우아한형제들 기술블로그
{{item.name}} 안녕하세요. 결제정산개발팀의 권세희입니다. 저는 정산업무를 맡게 되었는데, 정산은 데이터 정합성과 트랜잭션, 도메인 주도 개발, Entity 간의 연관 관계, 대용량 데이터 처리가 핵
techblog.woowahan.com
포스팅을 보고 나도 이런 습관이 있나, 고쳐야할게 있나 생각하며 정리해보기로 했다
자세한 설명은 포스팅에 있고 나는 결론적으로 정리할 생각
Entity
- Lombok @Data 기능 쓰지 말 것, 무분별한 Setter X
- Naming LocalDateTime 타입일 경우 작명 시 SampleDateTime, LocalDate 타입이면 SampleDate (직관적이게)
- Entity에는 LocalDateTIME 값 그대로 두고 DTO 에서 포맷할것
- DETELE 여부는 Boolean 값으로
- 연관관계는 하단에 표시해서 가독성을 높임
- Entity에서는 @NoArgsContructor을 사용해야함. JPA에서는 proxy생성을 위해 기본 생성자를 반드시 필요, AccessLevel.PROTECTED로 설정하여 JPA에서의 Entity 클래스 생성만 허용
동적 QueryDsl
이건 예제를 보는게 나을 것 같아서 추가
(아 AS-IS) 나를 보는 것 같아서 슬펐다ㅜㅠ
AS-IS
public class SalesRepositoryImpl extends QuerydslRepositorySupport implements SalesRepositoryCustom {
...
public BooleanBuilder addSearchBuilder(BooleanBuilder builder, QSales sales, SearchType searchType, String searchText) {
if (!StringUtils.isEmpty(searchText)) {
if (SearchType.OWNER_ID.equals(searchType)) {
Long ownerId = Long.valueOf(searchText);
builder.and(sales.owner.id.eq(ownerId));
} else if (SearchType.OWNER_NAME.equals(searchType)) {
builder.and(sales.owner.name.contains(searchText));
} else if (SearchType.SHOP_NAME.equals(searchType)) {
builder.and(sales.owner.shopName.contains(searchText));
}
}
return builder;
}
...
}
TO-BE
DTO로 받아서 깔끔하게 처리해주기
Querydsl의 BooleanExpression을 null값으로 리턴하면 where 조건문에서 제거됨
public class SalesAdminRepositoryImpl extends QuerydslRepositorySupport implements SalesAdminRepositoryCustom {
...
private BooleanExpression conditionalOwnerId(SalesSearchRequestDto dto) {
if (dto.isEmptySearchType() || dto.isNotOwnerId()) {
return null;
}
if (dto.isEmptySearchText()) {
return null;
}
return sales.owner.id.eq(Long.valueOf(dto.getSearchText()));
}
private BooleanExpression conditionalOwnerName(SalesSearchRequestDto dto) {
if (dto.isEmptySearchType() || dto.isNotOwnerName()) {
return null;
}
if (dto.isEmptySearchText()) {
return null;
}
return sales.owner.name.eq(dto.getSearchText());
}
private BooleanExpression conditionalShopName(SalesSearchRequestDto dto) {
if (dto.isEmptySearchType() || dto.isNotShopName()) {
return null;
}
if (dto.isEmptySearchText()) {
return null;
}
return sales.owner.shopName.eq(dto.getSearchText());
}
...
}
@Autowired 지양
생성자의 인자가 많아지는 경우에 final을 받는 파라미터를 생성자로 만들어주는 @RequiredArgsConstructor을 사용해도 됩니다. 다만 이때는 인자의 추가나 순서 변경시 생성자 클래스가 변경되는 점에 주의해야합니다.
친절한 테스트 코드
@Test
public void PaymentType별_금액_집계() throws Exception {
//given
savePayment(PaymentType.CARD, 15000L, sales);
savePayment(PaymentType.CARD, 13000L, sales2);
savePayment(PaymentType.POINT, 5000L, sales);
savePayment(PaymentType.POINT, 8000L, sales2);
savePayment(PaymentType.COUPON, 9000L, sales2);
JobParameters jobParameters =
new JobParametersBuilder()
.addString("aggregateDate", localDateToString(sumDate))
.toJobParameters();
//when
JobExecution jobExecution = jobTestUtils.getJobTester(JOB_NAME).launchJob(jobParameters);
//then
List<PaymentTypeSum> list = paymentTypeSumRepository.findAll();
assertThat(jobExecution.getStatus(), is(BatchStatus.COMPLETED));
assertThat(getPaymentTypeSum(list, PaymentType.CARD), is(28000L));
assertThat(getPaymentTypeSum(list, PaymentType.POINT), is(13000L));
assertThat(getPaymentTypeSum(list, PaymentType.COUPON), is(9000L));
}
테스트 코드를 짤 때 JUnit에서는 강제하지 않지만 given, when, then 주석을 달고 명확하게 작성해야 합니다.
//given 은 테스트에 필요한 상황, //when 은 테스트하려는 일의 동작, //then 은 when에서 발생한 일의 결과
DTO 잘 사용하기
정말 나도 많이 설계할 때 헷갈렸던 부분, 통일 할 수 있는 걸 최대한 통일시켜보려고 하니 그렇게 하지않는게 좋다고 한다
(엄청 큰 프로젝트이면 더더욱 중요) 작은 프로젝트여도 목적에 따라 DTO를 만들어주는게 좋다고 한다
- Dto는 사용에 따라 최대한 쪼개야 합니다. 예를 들어 하나의 Entity를 용도에 따라 보여주는 부분이 다를 때, 화면에서의 리스트 컬럼과 엑셀 다운로드 시 보여줄 컬럼들이 다를 때 필드가 1-2개 달랐지만 하나의 Dto로 사용했었습니다. 각각의 목적에 따라 Dto를 만들어야 합니다.
- 또한, Dto는 용도와 레벨에 맞는 곳에 위치해야 합니다. 저는 dto란 패키지를 만들고 그 안에 모든 dto를 두었었습니다. 하지만 어느 dto는 controller 단까지, 어느 dto는 서비스 레벨까지 사용할 수 있습니다. 이런 용도와 레벨에 맞게 위치시켜야 합니다.
두번째 용도마다 위치 하는 건 또 몰랐네ㅠㅠ 나도 이 부분 적용해봐야겠다
'Web > tip' 카테고리의 다른 글
[REST API] 직관적 네이밍 연습 (0) | 2023.03.04 |
---|---|
[exception] 한눈에 보는 Exception Class (0) | 2023.02.27 |
[pattern] 내가 보려고 쓰는 예제 (0) | 2023.02.26 |
[IntelliJ] 유용한 디버깅 단축키 정리 MAC ⌨️ (0) | 2023.02.23 |
[Mac Git] 내가 보려고 정리한 명령어들 (0) | 2023.01.07 |