Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ repositories {

dependencies {
testImplementation platform('org.junit:junit-bom:5.9.1')
testImplementation 'org.junit.jupiter:junit-jupiter'
testImplementation 'org.assertj:assertj-core:3.22.0'
testImplementation 'org.junit.jupiter:junit-jupiter:1.9.1'
testImplementation 'org.assertj:assertj-core:3.24.1'
}

test {
Expand Down
22 changes: 13 additions & 9 deletions src/main/java/calcproject/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,33 @@

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

import calcproject.engine.CalcExpressionTokenizer;
import calcproject.engine.Calculator;
import calcproject.models.CalcResultRecordModel;
import calcproject.repository.CalcResultRecordRepository;
import calcproject.repository.MemoryCalcResultRecordRepository;
import calcproject.service.CalcManager;
import calcproject.view.CalcInput;
import calcproject.view.CalcOutput;
import calcproject.view.console.CalcConsoleView;

public class Main {
public static void main(String[] args) {
Map<Integer, CalcResultRecordModel> calcMap = new HashMap<>();
int startIdx = 0;
CalcResultRecordRepository calcResultRecordRepository =
new MemoryCalcResultRecordRepository(calcMap, startIdx);
Scanner scanner = new Scanner(System.in);
CalcConsoleView calcConsoleView = new CalcConsoleView(scanner);
CalcExpressionTokenizer calcExpressionTokenizer = new CalcExpressionTokenizer();
Calculator calculator = new Calculator(calcExpressionTokenizer);

CalcManager calcManager = new CalcManager(calcResultRecordRepository, calcConsoleView, calcConsoleView,
calculator);
Map<Integer, CalcResultRecordModel> calcMap = new HashMap<>();
CalcResultRecordRepository calcResultRecordRepository =
new MemoryCalcResultRecordRepository(calcMap);

CalcConsoleView calcConsoleView = new CalcConsoleView();
CalcInput calcInput = calcConsoleView;
CalcOutput calcOutput = calcConsoleView;

CalcManager calcManager = new CalcManager(
calcResultRecordRepository, calcInput, calcOutput, calculator
);

calcManager.startCalcManager();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package calcproject.di.container;

import calcproject.engine.Calculator;
import calcproject.factory.CalcManagerViewFactory;
import calcproject.factory.CalcResultRecordRepositoryFactory;
import calcproject.repository.CalcResultRecordRepository;
import calcproject.service.CalcManager;
import calcproject.view.CalcInput;
import calcproject.view.CalcOutput;

public class CalcManagerDependencyInjectionContainer {
Copy link

Choose a reason for hiding this comment

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

DependencyInjectionContainer라는 네이밍은 너무 스프링 기술에 치중되어 있는 느낌이 드는데요,
실제로 스프링의 기술을 구현해서 사용하는 것이 아니라면, 다른 이름이 좋아보여요


private CalcResultRecordRepositoryFactory calcResultRecordRepositoryFactory;

private CalcManagerViewFactory calcManagerViewFactory;

private Calculator calculator;

public CalcManagerDependencyInjectionContainer(
CalcResultRecordRepositoryFactory calcResultRecordRepositoryFactory,
CalcManagerViewFactory calcManagerViewFactory,
Calculator calculator
) {
this.calcResultRecordRepositoryFactory = calcResultRecordRepositoryFactory;
this.calcManagerViewFactory = calcManagerViewFactory;
this.calculator = calculator;
}

public CalcManager createCalcManager() {
CalcResultRecordRepository calcResultRecordRepository =
calcResultRecordRepositoryFactory.createCalcResultRecordRepository();

CalcInput calcInput =
calcManagerViewFactory.createCalcInput();

CalcOutput calcOutput =
calcManagerViewFactory.createCalcOutput();

CalcManager calcManager = new CalcManager(
calcResultRecordRepository,
calcInput,
calcOutput,
this.calculator
);

return calcManager;
}
}
23 changes: 22 additions & 1 deletion src/main/java/calcproject/engine/CalcExpressionTokenizer.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
package calcproject.engine;

import java.util.ArrayList;
import java.util.List;

public class CalcExpressionTokenizer {
public List<String> tokenizeExpression(String expression) {
return null;
List<String> tokens = new ArrayList<>();
StringBuilder sb = new StringBuilder();

for (char element : expression.toCharArray()) {
if (Character.isDigit(element)) {
sb.append(element);
} else {
String numberString = sb.toString();
tokens.add(numberString);

sb.setLength(0);
tokens.add(Character.toString(element));
}
}

if (sb.length() > 0) {
String numberString = sb.toString();
tokens.add(numberString);
Comment on lines +24 to +25
Copy link

Choose a reason for hiding this comment

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

반복되는 코드가 나오는 것 같은데 공통 메서드로 추출하는 건 어떠신가요?

}

return tokens;
}
}
5 changes: 5 additions & 0 deletions src/main/java/calcproject/engine/Calculable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package calcproject.engine;

public interface Calculable {
public double calculate(double num1, double num2);
}
70 changes: 69 additions & 1 deletion src/main/java/calcproject/engine/Calculator.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package calcproject.engine;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class Calculator {
private CalcExpressionTokenizer calcExpressionTokenizer;
Expand All @@ -11,6 +13,72 @@ public Calculator(CalcExpressionTokenizer calcExpressionTokenizer) {

public double calculateExpression(String expression) {
List<String> tokens = calcExpressionTokenizer.tokenizeExpression(expression);
return Double.NaN;
List<String> postfixTokens = toPostfixNotation(tokens);
double calcResult = calculatePostfixNotation(postfixTokens);

return calcResult;
}

public List<String> toPostfixNotation(List<String> tokens) {
Stack<String> stack = new Stack<>();
List<String> postFixNotationTokens = new ArrayList<>();

for (String currentToken : tokens) {
if (isNumber(currentToken)) {
postFixNotationTokens.add(currentToken);
continue;
}
while (!stack.empty()) {
Operator currentOperator = Operator.opValueOf(currentToken);
Operator stackPeekOPerator = Operator.opValueOf(stack.peek());

if (stackPeekOPerator == Operator.UnSupportedOp) {
return List.of();
}

if (currentOperator.getPriority() > stackPeekOPerator.getPriority()) {
break;
}

postFixNotationTokens.add(stack.pop());
}

stack.add(currentToken);
}

while (!stack.empty()) {
postFixNotationTokens.add(stack.pop());
}

return postFixNotationTokens;
}

public double calculatePostfixNotation(List<String> postFixNotationTokens) {
Stack<Double> stack = new Stack<>();

for (String token : postFixNotationTokens) {

if (isNumber(token)) {
double num = Double.valueOf(token);
stack.push(num);
} else {
Operator operator = Operator.opValueOf(token);

double operand2 = stack.pop();
double operand1 = stack.pop();
Comment on lines +67 to +68
Copy link

Choose a reason for hiding this comment

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

stack이 비어있다면 어떻게 되나요?

double result = operator.calculate(operand1, operand2);
stack.push(result);
}
}

return stack.pop();
}

private boolean isNumber(String token) {
for (int i = 0; i < token.length(); i++) {
if (!Character.isDigit(token.charAt(i)))
return false;
}
return true;
}
}
44 changes: 44 additions & 0 deletions src/main/java/calcproject/engine/Operator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package calcproject.engine;

import java.util.Arrays;

public enum Operator {
Plus("+", 0, (a, b) -> a + b),
Minus("-", 0, (a, b) -> a - b),
Multiply("*", 1, (a, b) -> a * b),
Divide("/", 1, (a, b) -> a / b),
UnSupportedOp("", -1, (a, b) -> Double.NaN);
Copy link

Choose a reason for hiding this comment

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

반환 값으로 UnSupportedOp를 사용하게 되면 어떻게 되나요?


private String operator;
private int priority;
private Calculable calculable;

Operator(String operator, int priority, Calculable calculable) {
this.operator = operator;
this.priority = priority;
this.calculable = calculable;
}

public static Operator opValueOf(String op) {
return Arrays.stream(values())
.filter(
value -> value
.getOperator()
.equals(op)
)
.findAny()
.orElse(Operator.UnSupportedOp);
}

public String getOperator() {
return this.operator;
}

public int getPriority() {
return this.priority;
}

public double calculate(double num1, double num2) {
return this.calculable.calculate(num1, num2);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ public class MemoryCalcResultRecordRepository implements CalcResultRecordReposit
private Map<Integer, CalcResultRecordModel> calcMap;
Copy link

Choose a reason for hiding this comment

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

입력과 조회(모든 레코드) 두 가지 기능만 사용하고 있는데 굳이 Map을 쓰신 이유가 있나요?

private int lastIdx;

public MemoryCalcResultRecordRepository(Map<Integer, CalcResultRecordModel> calcMap, int startIdx) {
public MemoryCalcResultRecordRepository(Map<Integer, CalcResultRecordModel> calcMap) {
this.calcMap = calcMap;
this.lastIdx = startIdx;
this.lastIdx = 0;
}

@Override
Expand All @@ -27,7 +27,7 @@ public void saveCalcResultRecord(CalcResultRecordModel calcResultRecord) {
public List<CalcResultRecordModel> loadCalcResultRecords() {
return this.calcMap.values()
.stream()
.sorted(Comparator.comparing(calcModel -> calcModel.getId()))
.sorted(Comparator.comparing(CalcResultRecordModel::getId))
.collect(Collectors.toList());
}
}
2 changes: 1 addition & 1 deletion src/main/java/calcproject/service/CalcManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,4 @@ private void executeCmd(Command cmd) {
break;
}
}
}
}
2 changes: 1 addition & 1 deletion src/main/java/calcproject/view/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public enum Command {

public static Command valueOf(int choiceNum) {
return Arrays.stream(values())
.filter(value -> value.equals(choiceNum))
.filter(value -> value.getCmdIdx() == choiceNum)
Copy link

Choose a reason for hiding this comment

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

비교하는 메서드를 따로 만드는건 어떨까요?

.findAny()
.orElse(CALCULATE.EXIT);
Copy link

Choose a reason for hiding this comment

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

CALCULATE.EXIT는 사용자 의도로 인해 종료한다는 느낌인데요
강제종료를 의도하신거라면 TERMINATE는 어떠신가요?

}
Expand Down
16 changes: 7 additions & 9 deletions src/main/java/calcproject/view/console/CalcConsoleView.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,19 @@
public class CalcConsoleView implements CalcInput, CalcOutput {
private Scanner scanner;

public CalcConsoleView(Scanner scanner) {
this.scanner = scanner;
public CalcConsoleView() {
this.scanner = new Scanner(System.in);
}

@Override
public Command getCmd() {
Copy link

Choose a reason for hiding this comment

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

getCommand로 명시적으로 작성해주세요

System.out.println(Messages.INPUT_GUIDE_MESSAGE);
System.out.print(Messages.INPUT_CHOICE_MESSAGE);
System.out.println(Messages.INPUT_GUIDE_MESSAGE.getMessage());
System.out.print(Messages.INPUT_CHOICE_MESSAGE.getMessage());

int choiceNum = this.scanner.nextInt();
this.scanner.nextLine();

Command command = Command.valueOf(choiceNum);
return command;
return Command.valueOf(choiceNum);
}

@Override
Expand All @@ -51,13 +50,12 @@ public void showRecord(List<CalcResultRecordModel> calcResultRecordModelList) {
private String calcRecordToFormattedStr(CalcResultRecordModel calcRecord) {
String expression = calcRecord.getExpression();
double calcResult = calcRecord.getCalcResult();
String formattedStr = expression + " = " + calcResult;
return formattedStr;
return expression + " = " + calcResult;
}

@Override
public void showExitMessage() {
System.out.println(Messages.EXIT_MESSAGE);
System.out.println(Messages.EXIT_MESSAGE.getMessage());
}

}
42 changes: 0 additions & 42 deletions src/test/java/MemoryCalcResultRecordRepositoryTest.java

This file was deleted.

Loading