fix(qa): QA 이슈 수정 및 룰렛 보상 초기 데이터 추가 - #106
Conversation
- 탈퇴한 사용자 매칭 안걸리게 처리 - 사전가입 이벤트 발행 비활성화 - 3회 제한의 800원짜리 매칭권 추가
- 탈퇴한 사용자 매칭 안걸리게 처리 - 사전가입 이벤트 발행 비활성화 - 3회 제한의 800원짜리 매칭권 추가
- 탈퇴 tombstone이 존재하는 회원을 매칭 후보에서 제외
- stale 후보가 남아 있어도 탈퇴 회원이 선택되지 않도록 보완
- 탈퇴 회원 후보 제외 통합 테스트 추가
- FREE 및 SPECIAL 룰렛 보상 초기 데이터 설정
- 보상별 확률 구간과 지급 수량 및 상품권 재고 설정
- 기존 보상 데이터 존재 시 초기화를 건너뛰도록 처리
| } | ||
|
|
||
| if (DISCOUNT_MATCHING_TICKET_CODE.equals(resolveProductCode(product)) && quantity != 1) { | ||
| throw new BusinessException(PaymentErrorCode.INVALID_ORDER_QUANTITY); | ||
| } | ||
|
|
There was a problem hiding this comment.
OCP 위반: 특정 상품 코드가 서비스 레이어에 하드코딩됨
DISCOUNT_MATCHING_TICKET_1 이라는 특정 상품 코드를 문자열 비교로 두 군데에 특례 처리하고 있습니다.
- L39-L41 — 상수 선언
- L65-L68 — 목록 노출 필터 (
purchaseCountPurchasable() || DISCOUNT_MATCHING_TICKET_CODE.equals(product.code())) - 여기(L79-L84) — 요청 수량 검증 (
DISCOUNT_MATCHING_TICKET_CODE.equals(...) && quantity != 1)
왜 문제인가: 이 서비스는 이미 "상품별 한정 판매 규칙"을 일반화해서 모델링하는 패턴이 있습니다 — Product 엔티티의 firstPurchaseOnly 플래그와, 그걸 소비하는 validatePurchaseCountLimit 의 제네릭 분기가 그 예입니다. 이번 변경은 그 패턴을 재사용하지 않고 특정 product code 문자열을 서비스 레이어에 직접 박아 넣는 새로운 특례를 추가했습니다. docs/code-review-guidelines.md 의 OCP 기준("조건문으로 분기되는 로직이 전략 패턴 등으로 분리 가능한지 검토합니다")에 해당하는 사례로, 다음에 "소진돼도 계속 노출", "1회 수량 제한" 같은 규칙을 가진 상품이 추가될 때마다 이 두 지점에 if (CODE.equals(...)) 분기가 계속 늘어나는 구조입니다.
개선 방향: Product 엔티티에 alwaysListedWhenExhausted(또는 유사한 이름) / maxQuantityPerOrder 같은 필드를 추가해 상품 데이터로 표현하고, ShopServiceImpl 은 특정 코드 문자열이 아니라 그 필드를 제네릭하게 검사하도록 바꾸는 것을 제안합니다. 필드 추가와 초기화 데이터(ShopDataInitializer) 변경이 함께 필요해 커밋 가능한 제안(suggestion block)으로 바로 반영하기는 어려워 설명으로만 남깁니다.
변경 사항
상품 구매
DISCOUNT_MATCHING_TICKET_1회원가입/프로필
signup이벤트 발행 비활성화매칭
isMatchable=false인 경우 매칭 결과를 생성하지 않도록 검증 추가withdrawn_membertombstone이 존재하는 회원을 후보 조회 단계에서 제외룰렛
RouletteRewardDataInitializer추가