-
Notifications
You must be signed in to change notification settings - Fork 0
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
[문자열 덧셈 계산기] 조건희 미션 제출합니다 #2
base: main
Are you sure you want to change the base?
Changes from all commits
dd4b867
dac220d
9c52493
2e7cd6d
0fe1bba
dedece8
061b121
fc10e29
2fc1483
3a094f5
5f2ea86
b9b2316
fdb0c7c
a033f18
bef0412
93e9eaa
0ea8127
000c1f8
338341c
1f14323
50c64a7
93954de
a9ee173
48eaf2d
c7a6f7f
5e7a559
955ccb6
358957c
2af965b
ba18632
31920dd
71f7fed
e9e5596
f5514b5
9a99a54
40b3489
8451b22
98313ec
5897fa6
0ea7745
a4d6f60
ce6ed73
831a58f
c145fc0
c677162
9ed071b
f4a9c3d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,58 @@ | ||
# java-calculator-precourse | ||
# java-calculator-precourse | ||
|
||
# Project Directory | ||
calculator | ||
┣ config | ||
┃ ┗ Configuration.java | ||
┣ constant | ||
┃ ┗ CalConst.java | ||
┣ controller | ||
┃ ┗ CalculatorController.java | ||
┣ dto | ||
┃ ┗ CheckSeparatorDto.java | ||
┣ service | ||
┃ ┣ separator | ||
┃ ┃ ┗ Separator.java | ||
┃ ┣ validator | ||
┃ ┃ ┗ Validator.java | ||
┃ ┗ CalculatorService.java | ||
┣ view | ||
┃ ┣ InputView.java | ||
┃ ┗ OutputView.java | ||
┗ Application.java | ||
|
||
## 구현할 기능 목록 | ||
|
||
1. 문자열을 입력 받는 기능 | ||
2. 문자열에 추가 구분자 입력이 있는지 확인하는 기능 | ||
3. 문자열을 구분자를 기준으로 나누는 기능 | ||
4. 구분자로 나눠진 문자열에 숫자 외의 다른 문자가 있는지 확인하는 기능 있으면 IllegalArgumentException | ||
5. 나눠진 숫자를 더하는 기능 | ||
|
||
## 테스트 필요 하다 생각 되는 것들 | ||
|
||
- [x] 문자열을 아무 것도 주지 않았을 때 | ||
- [x] 추가 구분자로 숫자를 줬을 때 | ||
- [x] 소수 넣어 보기(추가 구분자로 .을 줬을 때와 아닐 때) | ||
- [x] 역슬래시(이스케이프 문자를 구분자로 줬을 때) | ||
- [x] 구분자 사이에 숫자가 없을 때 | ||
|
||
## 확인 필요 | ||
|
||
### 1. 커스텀 구분자가 여러 개라면? | ||
현재 만들어진 로직은 커스텀 구분자가 한 개인 경우만을 받고 있으나 그렇지 않을 수도 있음. | ||
Comment on lines
+40
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1번은 진짜 생각도 못 했네요 ㄷㄷㄷ 만약 커스텀 구분자가 여러 개라면 |
||
만약에 //와 \n 사이에 두 개가 들어가면 그건 따로 떨어뜨려서 구분을 해야하나? | ||
//ea\n1ea2ea3ea 이 주어지면 ea로 묶어서 구분자로 사용해야 하나? | ||
|
||
### 2. 커스텀 구분자에 숫자가 들어온다면? | ||
당연히 계산기라면 커스텀 구분자에 숫자가 들어오면 안되긴 함. | ||
커스텀 구분자에 숫자가 들어오는 경우 IllegalArgumentException 해야하는가? | ||
아니면 구분자로 인식하고 계산시켜야 하는가? | ||
지금은 계산하도록 만들어둠. | ||
|
||
### 3. 아무 입력도 하지 않았다면? | ||
입력이 없으면 0을 출력하도록 했음. 근데 IllegalArgumentException 해야하는지? | ||
|
||
### 4. 구분자 사이에 숫자가 없다면? | ||
현재는 사이에 숫자가 없다면 0으로 인식하고 계산을 진행하도록 하였음. | ||
이것도 throw 해야하는 경우인가? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,13 @@ | ||
package calculator; | ||
|
||
import calculator.config.Configuration; | ||
import calculator.controller.CalculatorController; | ||
|
||
public class Application { | ||
private static final Configuration CONFIGURATION = Configuration.getInstance(); | ||
|
||
public static void main(String[] args) { | ||
// TODO: 프로그램 구현 | ||
CalculatorController calculatorController = CONFIGURATION.getCalculatorController(); | ||
calculatorController.input(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package calculator.config; | ||
|
||
import calculator.controller.CalculatorController; | ||
|
||
public class Configuration { | ||
private static final Configuration CONFIGURATION = new Configuration(); | ||
private final CalculatorController calculatorController = new CalculatorController(); | ||
|
||
private Configuration() { | ||
} | ||
|
||
public static Configuration getInstance() { | ||
return CONFIGURATION; | ||
} | ||
|
||
public CalculatorController getCalculatorController() { | ||
return calculatorController; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package calculator.constant; | ||
|
||
public enum CalConst { | ||
MINIMUM_LENGTH_IF_EXIST_CUSTOM_SEPARATOR(5), | ||
START_INDEX_OF_CALCULATING(5), | ||
END_INDEX_OF_CUSTOM_SEPARATOR(3), | ||
INDEX_OF_CUSTOM_SEPARATOR(2), | ||
; | ||
|
||
private final int value; | ||
|
||
CalConst(int value) { | ||
this.value = value; | ||
} | ||
|
||
public int value() { | ||
return value; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package calculator.controller; | ||
|
||
import calculator.service.CalculatorService; | ||
import calculator.view.InputView; | ||
import calculator.view.OutputView; | ||
|
||
public class CalculatorController { | ||
private final CalculatorService calculatorService; | ||
private final InputView inputView; | ||
private final OutputView outputView; | ||
|
||
public CalculatorController() { | ||
this.inputView = new InputView(); | ||
this.outputView = new OutputView(); | ||
this.calculatorService = new CalculatorService(); | ||
} | ||
|
||
public void input() { | ||
String s = inputView.inputString(); | ||
inputView.close(); | ||
int addedResult = calculatorService.add(s); | ||
output(addedResult); | ||
} | ||
|
||
private void output(int i) { | ||
outputView.outputInteger(i); | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package calculator.dto; | ||
|
||
public class CheckSeparatorDto { | ||
private String inputString; | ||
private String customSeparator = null; | ||
|
||
public String getInputString() { | ||
return inputString; | ||
} | ||
|
||
public void setInputString(String inputString) { | ||
this.inputString = inputString; | ||
} | ||
|
||
public String getCustomSeparator() { | ||
return customSeparator; | ||
} | ||
|
||
public void setCustomSeparator(String customSeparator) { | ||
this.customSeparator = customSeparator; | ||
} | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 현재 CalculatorService에서 원본 문자열에 대한 파싱 작업을 같이 하고 계신 것으로 보입니다! 저 같은 경우에는 계산 기능과 문자열 가공 기능을 다른 클래스로 분리해봤습니다. 아무래도 우리가 실제 계산기를 사용할 때 문자열이 아닌 숫자만을 입력하는 것처럼, 계산기의 본 기능은 "계산"이고, "계산을 위해 숫자를 분리해내는 일"은 다른 클래스가 가져야 할 책임이라고 생각했기 떄문입니다! 살짝 참고해주시면 좋을 것 같습니다...! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 딱 외부에서 사용할 메서드만 public으로 선언하시고, 나머지 하위 메서드들은 private으로 선언하신 게 인상깊네요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
동감합니다..! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package calculator.service; | ||
|
||
import calculator.dto.CheckSeparatorDto; | ||
import calculator.service.separator.Separator; | ||
import calculator.service.validator.Validator; | ||
|
||
public class CalculatorService { | ||
private final Validator validator = new Validator(); | ||
private final Separator separator = new Separator(); | ||
|
||
|
||
/** | ||
* 덧셈 로직을 순차적으로 진행한다. | ||
*/ | ||
public int add(String inputString) { | ||
CheckSeparatorDto checkSeparatorDto = new CheckSeparatorDto(); | ||
checkSeparatorDto.setInputString(inputString); | ||
separator.checkCustomSeparator(checkSeparatorDto); | ||
String[] separatedString = separator.separate(checkSeparatorDto); | ||
|
||
validator.hasNaN(separatedString); | ||
return sumSeparatedStringArr(separatedString); | ||
} | ||
|
||
/** | ||
* 문자열을 int 형으로 바꾼 뒤 합한다. | ||
* | ||
* @param separatedStringArr 숫자로만 이루어진 문자열 배열을 입력한다. | ||
* @return 합한다. | ||
*/ | ||
private int sumSeparatedStringArr(String[] separatedStringArr) { | ||
int sum = 0; | ||
for (String separatedString : separatedStringArr) { | ||
if (!separatedString.isEmpty()) { | ||
sum += Integer.parseInt(separatedString); | ||
} | ||
} | ||
return sum; | ||
} | ||
Comment on lines
+31
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for문 대신 stream문을 사용할 수도 있습니다! 지금은 간단한 로직이라 별 차이가 안 나지만, 나중에 for문 안에 있는 로직이 복잡해지면 stream 사용을 고려해보셔도 좋을 것 같아요 😀 private int sumSeparatedStringArr(String[] separatedStringArr) {
return Arrays.stream(separatedStringArr)
.filter(s -> !s.isEmpty()) // 빈 문자열 필터링
.mapToInt(Integer::parseInt) // 문자열을 정수로 변환
.sum(); // 합계 계산
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
가독성도 그렇고 stream 이 직관적인 면이 있어서 보기 이쁘다고 생각을 해요. 코틀린에서는 stream 문이 워낙 편해서 자주 썼었는데 자바는 좀 손에 안익더라고요... 그래도 써보려고 노력은 해봐야죠. 조언 감사합니다! |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package calculator.service.separator; | ||
|
||
import calculator.constant.CalConst; | ||
import calculator.dto.CheckSeparatorDto; | ||
|
||
public class Separator { | ||
|
||
/** | ||
* 커스텀 구분자가 있는지 확인한다. 만약 있다면, checkSeparatorDto.customSeparator 에 null 대신 커스텀 구분자를 넣는다. 또한, | ||
* checkSeparatorDto.inputString 에 커스텀 구분자를 확인하는 부분을 제거한 문자열을 넣는다. | ||
* | ||
* @param checkSeparatorDto inputString 만 set 되어 있는 dto. | ||
*/ | ||
public void checkCustomSeparator(CheckSeparatorDto checkSeparatorDto) { | ||
String inputString = checkSeparatorDto.getInputString(); | ||
String customSeparator; | ||
|
||
if (inputString.length() >= CalConst.MINIMUM_LENGTH_IF_EXIST_CUSTOM_SEPARATOR.value() | ||
&& inputString.startsWith("//") | ||
&& inputString.startsWith("\\n", CalConst.END_INDEX_OF_CUSTOM_SEPARATOR.value())) { | ||
customSeparator = String.valueOf(inputString.charAt(CalConst.INDEX_OF_CUSTOM_SEPARATOR.value())); | ||
inputString = inputString.substring(CalConst.START_INDEX_OF_CALCULATING.value()); | ||
|
||
checkSeparatorDto.setCustomSeparator(customSeparator); | ||
checkSeparatorDto.setInputString(inputString); | ||
} | ||
} | ||
|
||
/** | ||
* 문자열을 구분자를 이용해 나눈다. | ||
* | ||
* @param checkSeparatorDto 커스텀 구분자(or null)와 커스텀 구분자 확인 부분을 제거한 문자열을 넣은 Dto. | ||
* @return 구분자를 이용해 나눠진 문자열을 반환한다. 이 문자열에는 숫자 외의 문자가 존재할 수 있다. 계산에 이용하려면 추가적인 확인 과정이 필요하다. | ||
*/ | ||
public String[] separate(CheckSeparatorDto checkSeparatorDto) { | ||
String customSeparator = checkSeparatorDto.getCustomSeparator(); | ||
String inputString = checkSeparatorDto.getInputString(); | ||
|
||
if (customSeparator == null) { | ||
return inputString.split("[:,]"); | ||
} | ||
if (customSeparator.equals("\\")) { | ||
return inputString.split("[:," + customSeparator.repeat(2) + "]"); | ||
} | ||
return inputString.split("[:," + customSeparator + "]"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package calculator.service.validator; | ||
|
||
import java.util.Arrays; | ||
|
||
public class Validator { | ||
|
||
/** | ||
* 숫자가 아닌 문자열이 있는지 확인한다. 만약 있다면 IllegalArgumentException 으로 처리한다. | ||
* | ||
* @param separatedStringArr 숫자 외의 문자가 있는지 확인하고 싶은 문자열을 입력한다. | ||
*/ | ||
public void hasNaN(String[] separatedStringArr) { | ||
if (Arrays.stream(separatedStringArr) | ||
.flatMapToInt(String::chars) | ||
.anyMatch(it -> it < '0' || it > '9')) { | ||
throw new IllegalArgumentException("입력한 문자열에 구분자, 숫자 외의 문자가 존재합니다."); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package calculator.view; | ||
|
||
import camp.nextstep.edu.missionutils.Console; | ||
|
||
public class InputView { | ||
public String inputString() { | ||
System.out.println("덧셈할 문자열을 입력해주세요."); | ||
return Console.readLine(); | ||
} | ||
|
||
public void close() { | ||
Console.close(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package calculator.view; | ||
|
||
public class OutputView { | ||
public void outputInteger(int i) { | ||
System.out.println("결과 : " + i); | ||
} | ||
} |
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.
예외 케이스를 되게 다양하게 짜신 것 같습니다 👍
특히
소수 넣어 보기
같은 경우는 생각을 더 해보게 되는 것 같아요. 덧셈 계산기라는 특성상 추후 발전을 시킨다면 소수도 계산을 할 수 있어야 할텐데, 이 때 어떤 기준으로 소수를 분리할 지에 대해 고민이 되네요!좋은 생각거리를 주셔서 감사합니다 🔥