-
Notifications
You must be signed in to change notification settings - Fork 1.1k
[문자열 덧셈 계산기] 한임경 미션 제출합니다. #1103
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
base: main
Are you sure you want to change the base?
Conversation
- 객체지향 설계(ValidationStrategy)를 포함한 최종 책임 및 역할 목록 명시 - BigInteger 도입 등 주요 난관 극복 과정 요약 - 최종 기능 요구 사항 정리
| System.out.println("예상치 못한 오류가 발생했습니다."); | ||
| throw e; | ||
| } finally { | ||
| inputHandler.close(); |
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.
input을 위에서 입력받고 넘기는데 close를 가장 뒤에서 처리한 이유가 궁금합니다.
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.
저의 설계의 실수인 것 같습니다!
제 코드를 다시 보니까 입력을 받고, 받은 입력을 바로 사용하는데 저는 예외 발생 여부와 상관 없이 InputHandler.close() 자원 해제를 보장 받고 싶었습니다.
그런데 Application.main에서 입력을 받고 바로 종료하는 구조인데 매번 close()를 호출하는게 비효율적이라고 느껴졌네요
try-catch 문에 inputHandler 객체를 넣었으면 finally 문이 필요 없었을 것 같네요 피드백 감사합니다!
| package calculator; | ||
|
|
||
|
|
||
| public class DelimiterInfo { |
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.
구분자에 대한 내용을 패키지로 한번 더 묶으면 가독성이 좋아질 것 같아요.
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.
Info같은 경우 전부 객체를 생성할 필요없이 클래스 래벨에서 처리할 수 있을 것 같아요
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.
좋은 피드백 감사합니다!
구분자 관련 부분은 말씀처럼 패키지로 한번 더 묶으면 가독성이 훨씬 좋아질 것 같네요!
공통으로 사용하는 기능이나 상수만 있다면 굳이 New로 매번 객체를 생성할 필요가 없겠네요
오히려 코드의 가독성을 떨어트리고 성능도 좋지 않겠네요
다음 2주차 미션때 개선 해보도록 하겠습니다!
| } | ||
|
|
||
| @Test | ||
| @DisplayName("5. 커스텀 구분자를 사용하여 합계를 계산한다.") |
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.
실패 케이스도 같이 테스트를 하면 좋을 것 같습니다.
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.
감사합니다!!
이번 테스트 케이스에 거의 처음 접근하다보니
미숙했네요
다음 2주차때 개선해보도록 하겠습니다
|
전체적으로 인터페이스와 이를 구현한 클래스로 나눈 것이 요구사항 변경에 대해서 유연하게 처리할 수 있을 것 같아 좋았습니다. 1주차 미션 고생하셨습니다. |
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.
좋은 코드 잘 보고 가요! 수고 많으셨어요!!
다음 주차도 파이팅입니다.🔥
| @@ -1,7 +1,32 @@ | |||
| package calculator; | |||
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.
패키지 구조를 더 나눠서 클래스들을 모아놓는다면 더 직관적으로 구조가 잘 보일 것 같습니다! 어떻게 생각하시나요??
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.
감사합니다 2주차때 적용해보도록 하겠습니다!
|
|
||
| DelimiterInfo info = delimiterParser.parse(input); | ||
|
|
||
| String[] parts = info.getNumbersString().split(info.getDelimiterRegex()); |
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.
info를 받아와서 getDelimiter를 하는 것 대신 Delimiter 자체에서 split을 처리하는 방향에 대해서는 어떻게 생각하시나요??
그렇게 하면 Info 없이도 처리가 가능하고 getter를 없앨 수 있어서 더 명확해질 것 같다고 생각해요!
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.
확실히 그렇게 하면 코드가 더 직관적이어서 보기 편할 것 같네요
좋은 의견 감사합니다.
| throw new IllegalArgumentException("커스텀 구분자 선언 후 반드시 줄 바꿈(\\n)을 해야합니다."); | ||
| } | ||
|
|
||
| String customDelimiter = sanitizedInput.substring(2, delimiterEndIndex); |
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.
만일 여기서 customDelimiter가 ""거나, 숫자라면 정상 작동하는지 궁금합니다!!
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.
2로 되어있는 부분도 하드코딩되어있어서 요구사항 변경에 대응이 안될 것 같습니다. length 등 함수를 통해서 하는 것이 더 좋을 것 같습니다.
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 class NumberParser { | ||
|
|
||
| public BigInteger parse(String token) { |
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.
BigInteger쓰면 오버플로우를 방지할 수 있겠네요!
배워갑니다!!!
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.
파일 한 곳에 여러 기능들이 몰려있는 느낌입니다..! 클래스의 인스턴스 생성, Caclulator의 동작 메서드 등 다양하게 역할을 분배해도 좋을 것 같습니다.
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.
감사합니다! 2주차때 적용해보도록 하겠습니다 ㅎㅎ
| public void validate(List<BigInteger> numbers) { | ||
| StringBuilder negativeNumbers = new StringBuilder(); | ||
|
|
||
| for (BigInteger number : numbers) { |
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.
for문을 사용하는 것 보다 stream을 사용해보는 게 어떨까요? stream 자체적인 filter 함수를 통해 if문을 대체할 수 있어 가독성 부분에서 좋아질 것 같습니다!
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.
stream 사용에 미숙해서 for문으로 돌려버렸네요 ... 이번 2주차 미션때 미숙한 저의 실력을 더 발전시키고자
사용해보도록 하겠습니다 감사합니다!
| } | ||
| } | ||
|
|
||
| if (negativeNumbers.length() > 0) { |
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.
14번째 줄에 똑같은 함수가 존재하는데, 그곳에 exception을 던져도 될 것 같습니다
| throw new IllegalArgumentException("커스텀 구분자 선언 후 반드시 줄 바꿈(\\n)을 해야합니다."); | ||
| } | ||
|
|
||
| String customDelimiter = sanitizedInput.substring(2, delimiterEndIndex); |
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.
커스텀구분자가 2문자 이상으로 들어오면, 커스텀 구분자가 2문자로 들어오게 되나요?
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.
아닙니다. 2문자로 고정되지 않습니다!!
제시된 코드는 //와 \n 사이의 모든 문자열을 커스텀 구분자로 정확하게 추출합니다. 구분자가 2문자 이상(예: $$, ***, abcde)이더라도 그 길이 그대로 추출됩니다!
시작: substring(2, ...)는 //를 건너뛰고 구분자 첫 글자부터 시작합니다
종료: delimiterEndIndex는 \n의 위치이며, substring은 이 위치 직전까지 자릅니다
따라서 시작과 끝 경계 사이에 있는 문자는 길이에 관계없이 모두 구분자가 됩니다.
혹시 제가 의도한 바를 잘못 이해해서 대답했다면 다시 말씀해주세요
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.
아 제가 잘못 질문했네요!
커스텀 구분자가 2문자 이상으로 들어오면 똑같이 커스텀 구분자가 2글자 이상으로 들어오는지 궁금했습니다 -> 위 답변에 이미 해결됐네요!
| try { | ||
| return new BigInteger(trimmedToken); | ||
| } catch (NumberFormatException e) { | ||
| throw new IllegalArgumentException("숫자 이외의 문자열이 포함되어 변환할 수 없습니다: " + trimmedToken); |
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.
Exception 상황 -> Validate하는 상황이라 예외 상황이 발생할 때 따로 메서드로 분리하면 좋을 것 같습니다.
validate만 하는 클래스를 생성해서 static으로 메서드를 생성한뒤 필요한 순간에만 불러오게 하는 건 어떨까요?
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.
단일책임원칙에 어긋나는 코드인 것 같네요
좋은 의견 감사합니다!
| String finalDelimiterRegex = BASIC_DELIMITER_REGEX; | ||
| String numbersToSplit; | ||
|
|
||
| if (sanitizedInput.startsWith("//")) { |
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.
커스텀 구분자를 하드코딩으로 처리하였는데 이도 위와 마찬가지로 상수로 빼두는 것이 좋을 것 같습니다.
커스텀 구분자를 변경해달라는 요청에 대응할 수 있도록
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.
startWith대신 정규표현식으로 한번에 커스텀 구분자 영역을 추출해보는 것도 고려해보면 좋을 것 같습니다.
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.
하드코딩 된 것이 많네요
oops
피드백 감사합니다
|
|
||
| public class DefaultDelimiterParser implements DelimiterParser { | ||
|
|
||
| private static final String BASIC_DELIMITER_REGEX = "[,:]"; |
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.
정규표현식 입력을 실수할 수도 있으니, 기본 구분자는 리스트로 만들어두고, 이를 정규표현식 패턴으로 만들어주는 함수를 구현하는 것도 고려해볼 수 있을 것 같습니다.
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.
리스트로 만들면 확실히 구분자가 추가 되거나 변경되어도 리스트만 수정하면 좋겠네요 감사합니다!
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.
변수명에 대해 몇 가지 궁금한 점이 있습니다!
-
finalDelimiterRegex에서final을 붙이신 이유가 궁금해요.
변수명에 final을 명시하는 것보다는 실제로final키워드를 사용하거나,
delimiters또는delimiterPattern같은 이름이 더 명확할 것 같습니다. -
numbersToSplit은 "분리할 숫자들"이라는 동사구 형태인데,
아직 분리되지 않은 문자열이라 의미가 혼란스러워 보여요.
inputText,numberString같은 명사형이 더 자연스럽지 않을까요?
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.
객체를 나누는것에 많은 고민을 한게 눈에 보여서 좋았습니다! 추가로 꼼꼼하게 코드를 보시고 만드신것 같아서 저도 조금 배웠던것 같습니다!
| } finally { | ||
| inputHandler.close(); | ||
| } | ||
| } |
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.
close있는걸 확인 못했는데 꼼꼼한게 너무 좋네요! 심지어 final에 넣으셔서 catch와 try의 정상과 비정상흐름에 적절히 닫힐 수 있게 만드시 부분 너무 좋네요!
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.
ㅎㅎ 감사합니다 !!
|
|
||
| for (BigInteger number : numbers) { | ||
| if (number.compareTo(BigInteger.ZERO) < 0) { | ||
| if (negativeNumbers.length() > 0) { |
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.
위 처럼 작성하신 이유는 부정문 때문일까요!?
if(!negativeNumbers.isEmtpy()){
}
위 처럼 isEmtpy로 좀더 읽기 편하게 만들 수도 있을 것 같습니다!(개인적인 의견입니다)
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.
부정문 때문에 사용을 했습니다
생각을 해보니 이렇게 사용하면 다른 사람이 대충 보면
객체인지, 일반 변수인지 헷갈릴수도도 있겠네요
피드백 감사합니다!
| try { | ||
| DelimiterParser delimiterParser = new DefaultDelimiterParser(); | ||
| NumberParser numberParser = new NumberParser(); | ||
| ValidationStrategy validationStrategy = new CollectAllValidator(); | ||
|
|
||
| Calculator calculator = new StringCalculator(delimiterParser, numberParser, validationStrategy); | ||
|
|
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.
제 개인 적인 생각을 적자면 StringCalculator 생성이 상당히 복잡해 보이네요!
개인적인 생각으로는 StringCalculator의 생성 책임을 Factory같은 생성전용 객체로 옴겨보는건 어떨까요?
그렇게 되면 이 코드는
Calculator calculator = CalculatorFactory.createStringCaclulator();
위 처럼 사용 할 수 있을 것 같아요!
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.
객체를 생성하는것도 책임이라고 생각하지 못했던 것 같아요
따로 검색해보니 팩토리 디자인 패턴이라는 것도 있네요
저의 식견을 넓혀주셔서 감사합니다 ㅎㅎ
| if (sanitizedInput.startsWith("//")) { | ||
| int delimiterEndIndex = sanitizedInput.indexOf("\n"); | ||
|
|
||
| if (delimiterEndIndex == -1) { | ||
| throw new IllegalArgumentException("커스텀 구분자 선언 후 반드시 줄 바꿈(\\n)을 해야합니다."); | ||
| } | ||
|
|
||
| String customDelimiter = sanitizedInput.substring(2, delimiterEndIndex); | ||
| finalDelimiterRegex += "|" + Pattern.quote(customDelimiter); | ||
|
|
||
| numbersToSplit = sanitizedInput.substring(delimiterEndIndex + 1); | ||
| } else { | ||
| numbersToSplit = sanitizedInput; | ||
| } |
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.
early return을 사용해보는 건 어떨까요!?
if (sanitizedInput.startsWith("//")) {
int delimiterEndIndex = sanitizedInput.indexOf("\n");
if (delimiterEndIndex == -1) {
throw new IllegalArgumentException("커스텀 구분자 선언 후 반드시 줄 바꿈(\\n)을 해야합니다.");
}
String customDelimiter = sanitizedInput.substring(2, delimiterEndIndex);
String delimiterRegex += BASIC_DELIMITER_REGEX + "|" + Pattern.quote(customDelimiter);
String numbersToSplit = sanitizedInput.substring(delimiterEndIndex + 1);
return new DelimiterInfo(delimiterRegex,numbersToSplit);
}
return new DelimiterInfo(BASIC_DELIMITER_REGEX,numbersToSplit);
이런식으로 하면 좀더 잘 보이지 않을까 싶습니다!
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.
코드가 너무 이뻐졌네요
감사합니닷... !!
No description provided.