Skip to content
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
# java-calculator-precourse
# java-calculator-precourse

# 기능 목록
*MVC에 따라 구현해 기능목록 외의 커밋 존재

1. 콘솔 입출력 관리 : Console
2. 구분자 인식 기능 : SeparatorRecognizeService
- 기본 구분자 인식
- 커스텀 구분자 저장 및 인식
3. 수 변환 및 합산 기능 : NumberProcessService
- 수 변환
- 트리거에 따라 저장된 변환 수 합산
4. 메인 예외처리 기능
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.gradle.jvmargs=-Dfile.encoding=UTF-8
2 changes: 1 addition & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0'
}
rootProject.name = 'java-calculator'
rootProject.name = 'java-calculator'
15 changes: 14 additions & 1 deletion src/main/java/calculator/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
package calculator;

import calculator.controller.CalculatorController;
import calculator.service.SeparatorRecognizeService;
import calculator.view.CalculatorView;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
new Application().run();
}

public void run(){
CalculatorView calculatorView = new CalculatorView();
SeparatorRecognizeService separatorRecognizeService = new SeparatorRecognizeService();
CalculatorController controller = new CalculatorController(calculatorView, separatorRecognizeService);

controller.input();
controller.calculate();
}
}
54 changes: 54 additions & 0 deletions src/main/java/calculator/Model/CalculatorModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package calculator.Model;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CalculatorModel {
private ModelObserver observer;
private int resultNum;
private String inputLine;
private List<String> separatorList;
private String separatorCheckRegex;
private final Pattern customCheckPattern = Pattern.compile("//(.*?)\\\\n");

public CalculatorModel(String inputLine){
this.resultNum = 0;
this.inputLine = inputLine;
this.separatorList = new ArrayList<>(List.of(":", ","));
}

public static CalculatorModel setInputLine(String inputLine) {
return new CalculatorModel(inputLine);
}

public void stripInputLine(String regex) {
inputLine = inputLine.replaceFirst(regex, "");
}

public String[] getSplittedInputLine() {
return inputLine.split(separatorCheckRegex);
}

public void setObserver(ModelObserver observer){
this.observer = observer;
}

public Matcher getCustomCheckMatcher(){
return customCheckPattern.matcher(inputLine);
}

public void addSeparator(String separator){
separatorList.add(separator);
}

public void generateSeparatorCheckRegex(){
separatorCheckRegex = String.join("|", separatorList);
}

public void setResultNum(int resultNum) {
this.resultNum = resultNum;
observer.onCalculateFinished(resultNum);
}
}
5 changes: 5 additions & 0 deletions src/main/java/calculator/Model/ModelObserver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package calculator.Model;

public interface ModelObserver {
void onCalculateFinished(int result);
}
30 changes: 30 additions & 0 deletions src/main/java/calculator/controller/CalculatorController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package calculator.controller;

import calculator.service.SeparatorRecognizeService;
import calculator.view.CalculatorView;


public class CalculatorController {

private CalculatorView calculatorView;

private SeparatorRecognizeService separatorRecognizeService;


public CalculatorController(CalculatorView calculatorView, SeparatorRecognizeService separatorRecognizeService){
this.calculatorView = calculatorView;
this.separatorRecognizeService = separatorRecognizeService;
}

public void input(){

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분은 Controller의 역할 보다는 View의 역할에 가까운 것 같아요

@daeGULLL daeGULLL Feb 9, 2025

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 그렇게 생각했습니다..그런데 view는 기능을 가진 채 존재만 하고 뭔가 실제로 조작할때는 컨트롤러를 사용한다고 글을 읽어서 고민하다 컨트롤러 내부에 해당 함수를 만들었었습니다..! view 이놈도 뭔가 조작? 기능을 가져도 되는건가요? 인터넷에 올라온 글들만 봐선 MVC 패턴을 잘 이해를 못하겠드라구요ㅠㅠ @moongua404

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

뷰에 비지니스로직이 포함되면 안되는 것은 맞지만 자료형 변환, 때로는 최소한의 타입 검사 등을 포함시키는 경우도 있는 것으로 알고있습니다.
제가 이 코드를 해석하기에는 입출력 장치만을 가져와 console.print("덧셈할 문자열을 입력해 주세요.");, rawArg = console.read(); 등 입출력의 역할을 Controller가 가져간 것 같다고 이해했습니다

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

뷰에 비지니스로직이 포함되면 안되는 것은 맞지만 자료형 변환, 때로는 최소한의 타입 검사 등을 포함시키는 경우도 있는 것으로 알고있습니다.
제가 이 코드를 해석하기에는 입출력 장치만을 가져와 console.print("덧셈할 문자열을 입력해 주세요.");, rawArg = console.read(); 등 입출력의 역할을 Controller가 가져간 것 같다고 이해했습니다

String inputLine = calculatorView.read();
separatorRecognizeService.setInput(inputLine);
separatorRecognizeService.addObserver(calculatorView);
}

public void calculate(){
separatorRecognizeService.specialDetect();
separatorRecognizeService.normalDetect();
}

@moongua404 moongua404 Feb 8, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코드보다 순서논리회로(?)를 보는 것 같아요...

  1. 의존성이 개념적으로 분리되지 않은 것 같습니다. 가령 여기서 동작 원리를 이해하려면 detectResult의 getDetected를 이해해야하는데 이걸 이해하려면 normalDetect 등의 메서드를 봐야하고,,,
  2. 역할도 분리가 명확히 되지 않은 것 같습니다. process에 복잡한 내부 로직이 연산자 추출, 연산 등 다양한 역할이 섞여있는 것 같습니다
  3. API로 대체 가능한 기능들이 꽤나 많습니다.
  4. 휴먼 에러가 발생하기 쉽울 것 같습니다. 인덱스를 통해 접근하는 것 부터 각 부분이 어떠한 기능을 하는지 파악하기 어려워 다른 사람이 코드를 다룰 때 실수가 많이 발생할 수 있을 것 같습니다.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

확실히 약간 파일들끼리 꼬리의 꼬리를 무는 형태처럼 보여서 코드를 읽는 것 뿐만 아니라 작성하는데도 자세히, 조심히 봐야 할 것 같아요...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이때부터 시간이 촉박해 생각나는대로 그대로 쓰다보니 슨서논리회로가 되버린게 맞을겁니다 허허 API를 좀더 알아봐 잘 대체하고 잘 분리시켜보도록 하겠습니당


}
48 changes: 48 additions & 0 deletions src/main/java/calculator/service/SeparatorRecognizeService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package calculator.service;

import calculator.Model.CalculatorModel;
import calculator.Model.ModelObserver;
import calculator.util.NumberProcessUtil;

import java.util.regex.Matcher;

public class SeparatorRecognizeService {

private CalculatorModel calculatorModel;

public void setInput(String inputLine){
calculatorModel = CalculatorModel.setInputLine(inputLine);
}

public void addObserver(ModelObserver view){
calculatorModel.setObserver(view);
}

public void specialDetect(){
Matcher customCheckMatch = calculatorModel.getCustomCheckMatcher();

//커스텀 구분자를 전부 추출
while(customCheckMatch.find()){
String extracted = customCheckMatch.group(1);
//구분자 목록에 커스텀 구분자 추가
calculatorModel.addSeparator(extracted);
//입력받은 문자열에서 해당 부분 제거
calculatorModel.stripInputLine("//" + extracted + "\\\\n");
}
}

public void normalDetect(){
int tempNum = 0;
calculatorModel.generateSeparatorCheckRegex();

String[] splittedInputLine = calculatorModel.getSplittedInputLine();
for(String i : splittedInputLine){
tempNum += NumberProcessUtil.stringToInt(i);
}

calculatorModel.setResultNum(tempNum);
}


}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 코드들을 정규표현식을 활용해서 구현한다면 길이를 확 줄일 수 있어 보이고 더 효율적일 것 같습니다!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞아요 정규표현식 얘기가 이번 과제 통틀어서 많더라구요 한번 공부해서 줄여보겠습니다 감사합니다!!

16 changes: 16 additions & 0 deletions src/main/java/calculator/util/MessageConstants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package calculator.util;

public enum MessageConstants {
INPUT_GUIDE("덧셈할 문자열을 입력해 주세요."),
RESULT_GUIDE("결과 : ");

private final String message;

MessageConstants(String message) {
this.message = message;
}

public String getMessage() {
return this.message;
}
}
18 changes: 18 additions & 0 deletions src/main/java/calculator/util/NumberProcessUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package calculator.util;

import java.util.List;

public class NumberProcessUtil {
public static int stringToInt(String arg){
if(arg == null || !arg.matches("\\d+")) throw new IllegalArgumentException("Invalid number format");
return Integer.parseInt(arg);
}

public static String intToString(int num){
return String.valueOf(num);
}

public static int addAll(List<Integer> targetList){
return targetList.stream().mapToInt(Integer::intValue).sum();
}
}
17 changes: 17 additions & 0 deletions src/main/java/calculator/view/CalculatorView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package calculator.view;

import calculator.Model.ModelObserver;
import calculator.util.MessageConstants;

public class CalculatorView implements ModelObserver {

public String read(){
System.out.println(MessageConstants.INPUT_GUIDE.getMessage());
return camp.nextstep.edu.missionutils.Console.readLine();
}

@Override
public void onCalculateFinished(int result){
System.out.println(MessageConstants.RESULT_GUIDE.getMessage() + result);
}
}
8 changes: 8 additions & 0 deletions src/test/java/calculator/ApplicationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ class ApplicationTest extends NsTest {
);
}

@Test
void 여러개_테스트(){
assertSimpleTest(()-> {
run("1://;\\n1;2");
assertThat(output()).contains("결과 : 4");
});
}

@Override
public void runMain() {
Application.main(new String[]{});
Expand Down