-
Notifications
You must be signed in to change notification settings - Fork 171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[5기 - 정의진] SpringBoot Part1 Weekly Mission 제출합니다. #897
Conversation
################ # <타입> : <제목> 의 형식으로 제목을 아래 공백줄에 작성 # 제목은 50자 이내 / 변경사항이 "무엇"인지 명확히 작성 / 끝에 마침표 금지 # 예) feat : 로그인 기능 추가 # 바로 아래 공백은 지우지 마세요 (제목과 본문의 분리를 위함) ################ # 본문(구체적인 내용)을 아랫줄에 작성 # 여러 줄의 메시지를 작성할 땐 "-"로 구분 (한 줄은 72자 이내) ################ # 꼬릿말(footer)을 아랫줄에 작성 (현재 커밋과 관련된 이슈 번호 추가 등) # 예) Close prgrms-be-devcourse#7 ################ # feat : 새로운 기능 추가 # fix : 버그 수정 # docs : 문서 수정 # test : 테스트 코드 추가 # refact : 코드 리팩토링 # style : 코드 의미에 영향을 주지 않는 변경사항 # chore : 빌드 부분 혹은 패키지 매니저 수정사항 ################
################ # <타입> : <제목> 의 형식으로 제목을 아래 공백줄에 작성 # 제목은 50자 이내 / 변경사항이 "무엇"인지 명확히 작성 / 끝에 마침표 금지 # 예) feat : 로그인 기능 추가 # 바로 아래 공백은 지우지 마세요 (제목과 본문의 분리를 위함) ################ # 본문(구체적인 내용)을 아랫줄에 작성 # 여러 줄의 메시지를 작성할 땐 "-"로 구분 (한 줄은 72자 이내) ################ # 꼬릿말(footer)을 아랫줄에 작성 (현재 커밋과 관련된 이슈 번호 추가 등) # 예) Close prgrms-be-devcourse#7 ################ # feat : 새로운 기능 추가 # fix : 버그 수정 # docs : 문서 수정 # test : 테스트 코드 추가 # refact : 코드 리팩토링 # style : 코드 의미에 영향을 주지 않는 변경사항 # chore : 빌드 부분 혹은 패키지 매니저 수정사항 ################
Voucher 필드 게터 추가
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
간단하게 질문 남겼어요 고생하셨어요 :)
|
||
import static java.text.MessageFormat.format; | ||
|
||
public class FixedAmountVoucher implements Voucher { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inteface로 구현하는게 좋을까요?
현재 중복코드들이 있는것 같은데요.
이런 경우 상속 또는 조합 방식이 더 어울려 보여요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Voucher
를 추상클래스로 변경했습니다. 확실히 중복되어 있던 코드가 사라져서 더 깔끔해 진 것 같습니다! 조언 감사합니다:)
if (amount <= 0) { | ||
throw new IllegalArgumentException(format("{0}: 할인 금액은 0 보다 커야 합니다.", amount)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
validate는 따로 메서드를 빼서 의미를 전달하면 어떨까요?
아울러 amount의 값을 int 이상의 값을 입력하면 어떻게 될까요?
import static java.text.MessageFormat.format; | ||
|
||
public class PercentDiscountVoucher implements Voucher { | ||
private static final Logger logger = LoggerFactory.getLogger(FixedAmountVoucher.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private static final Logger logger = LoggerFactory.getLogger(FixedAmountVoucher.class); | |
private static final Logger logger = LoggerFactory.getLogger(PercentDiscountVoucher.class); |
if (percent <= 0) { | ||
throw new IllegalArgumentException(format("{0}: 할인율은 0% 이하일 수 없습니다.", percent)); | ||
} | ||
|
||
if (percent > 100) { | ||
throw new IllegalArgumentException(format("{0}: 할인율은 100%를 초과할 수 없습니다.", percent)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
별건 아니지만, 하나로 합칠수 있지 않을까요?
public String getInfo() { | ||
|
||
return format("id: {0}, 고객명: {1} ", id, name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public String getInfo() { | |
return format("id: {0}, 고객명: {1} ", id, name); | |
public String getInfo() { | |
return format("id: {0}, 고객명: {1} ", id, name); |
try (BufferedReader reader = Files.newBufferedReader(Paths.get(path), StandardCharsets.UTF_8)) { | ||
reader.readLine(); // skip header | ||
reader.lines() | ||
.map(s -> s.split("[;,]")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
상수화를 하면 어떨까요?
} | ||
|
||
public List<User> findAll() { | ||
return blacklist; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
불변으로 return하면 어떨까요?
unmofiedList라는 키워드를 한번 찾아보세요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Collections.unmodifiableList()
를 사용해서 변경했습니다!
|
||
@Profile("dev") | ||
@Repository | ||
public class JSONFileVoucherRepository implements VoucherRepository, DisposableBean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(질문)
DisposableBean 해당 빈을 왜 구현하신걸까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저희 프로그램은 프로그램이 종료될 때, 캐시되어 있던 Voucher
정보를 파일에 저장합니다!
그래서 프로그램이 종료되면서 빈이 사라질 때, 자동으로 파일 저장기능을 수행하도록 하기 위해 DisposableBean
을 구현했습니다.
파일 저장 기능을 일반 인스턴스 메서드로 빼서 서비스 쪽에서 프로그램을 종료할 때, 해당 로직을 호출하는 형식으로 변경하는 것이 나을까요?
사실 파일에 저장하는 것과 관련해서는 파일 저장을 프로그램 종료 시 가 아닌 프로그램 중간중간에 해야할 것 같다는 생각이 드는데, 어떤 방식이 좋을까요? 저희가 생각했던 방식은
- 프로그램이 종료될 때 한번에 저장 (현재)
- 바우처 Create 요청이 올 때마다 저장
- 적절한 주기(ex. 1시간, 1일 간격)에 저장
이 있습니다! 2번은 오버헤드가 있을 것같고, 3번이 가장 적절해 보이는데 추후 3번 방식으로 변경해도 괜찮을까요?
} | ||
|
||
ObjectReader objectReader = objectMapper.readerForListOf(LoadedJSONVoucher.class); | ||
List<LoadedJSONVoucher> loadedList; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좀더 의미잇는 단어를 쓰면 어떨까요?
loadedVouchers 같은 의미로요. List라는 단어는 포괄적으로 사용하는 단어니깐요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
jsonVouchers
로 변수명 변경했습니다!
import java.util.Objects; | ||
|
||
public final class Console { | ||
private static final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
혹시 Scanner대신 BufferedReader를 쓰신 이유가 따로 있나요
그냥 질문입니닷.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저는 주로 Scanner을 쓰고, 현우님은 주로 BufferedReader를 써서 별 고민없이 BufferedReader을 썼던 것 같습니다.. 찾아보니 Scanner와 BufferedReader의 차이에는
- 버퍼 사이즈 (Scanner: 1KB, BufferedReader: 8KB)
- Input 형식 (Scanner: nextInt() 등의 메서드로 다양한 type 지원, BufferedReader: only String)
- Thread safe (Scanner: thread safe X, BufferedReader: thread safe O)
가 있는 것 같습니다.
🙋🏻♀️ 동기화 이슈로 BufferedReader를 쓰는게 적합해 보이는데, 그대로 BufferedReader를 써도 될까요?
메서드 역할을 구체적으로 명시
기존 상위 모듈인 CommandType 이넘과 VoucherApplication을 application 패키지로 이동 VoucherApplication 이름을 ConsoleApplication으로 변경
기존 loadedList -> loadedVouchers
👩💻요구 사항과 구현 내용
바우처 관리 Command-line Application
요구사항
구현 내용
VoucherManagementSystemApplication
VoucherApplication
Console
클래스를 이용해 사용자 입력을 받고 적절한 Service를 호출CommandType
Enum
Console
VoucherService
Repository
메서드 호출BlacklistService
BlacklistRepository
에게 요청을 전달VoucherRepository
MemoryVoucherRepository
VoucherRepository
구현 클래스JSONFileVoucherRepository
VoucherRepository
구현 클래스LoadedJSONVoucher
VoucherType
필드에 맞는 바우처 인스턴스를 반환Voucher
VoucherType
FixedAmountVoucher
Voucher
구현 클래스PercentDiscountVoucher
Voucher
구현 클래스User
✅ PR 포인트 & 궁금한 점
프로젝트를 진행하면서 클래스와 메서스, 변수명을 정하는 것이 고민이었습니다.
ex)
LoadedJSONVoucher
,VoucherManagementSystemApplication
,VoucherApplication
,selectCommand
(메서드명)🙋🏻♂️ 현재 네이밍이 적절하게 되어있는지, 그리고 추천하는 네이밍 방식이 있을지 궁금합니다!
VoucherApplication
의 실행 방식으로(1) 재귀적인 메서드 호출 (현재)
(2) while 문으로 루프를 도는 것
을 고민했는데, 어떤 방식을 사용하는 것이 좋았을까요?
현재 저희 어플리케이션에서는 바우처 종류에 상관없이 바우처 정보를 하나의 파일에 저장하고 있습니다. 그렇기 때문에
JSONFileVoucherRepository
에서는 바우처 데이터를 불러올 때 모든 종류의 바우처 정보를 가지고 있는LoadedJSONVoucher
클래스로 매핑해서 가져오는데 이 부분을 어떻게 개선할 수 있을지 궁금합니다!❗ (문제점) 바우처 종류가 늘어날수록
LoadedJSONVoucher
클래스가 갖고 있어야 할 필드가 늘어남🙋🏻♂️ 바우처 종류에 따라 파일을 분리해서 저장하는 것이 좋을까요?
🙋🏻♂️ 비슷하게 만약 RDB로 관리한다면 모든 종류의 바우처를 하나의 테이블로 관리하는게 좋은 방식일까요?
바우처 정보를 파일에 언제 저장하면 좋을지 궁금합니다!
(1) 프로그램이 종료될 때 한번에 저장 (현재)
(2) 바우처 Create 요청이 올 때마다 저장
(3) 적절한 주기(ex. 1시간, 1일 간격)에 저장
블랙리스트 관련 비즈니스 로직을
UserService
에 넣는 것이 좋을지, 아니면 별도의BlacklistService
(현재)에 넣는 것이 좋을지 궁금합니다!