- 
                Notifications
    You must be signed in to change notification settings 
- Fork 155
[4기 - 김범우] 1~2주차 과제 : 계산기 구현 미션 제출합니다. #154
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: beomukim
Are you sure you want to change the base?
Changes from 7 commits
fac4137
              c6aa838
              6c74d03
              856cad6
              e8a7b09
              344e591
              844bad2
              6f0ad7b
              8ea8204
              81b1bc2
              8aace2e
              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 | 
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| # | ||
| # https://help.github.com/articles/dealing-with-line-endings/ | ||
| # | ||
| # Linux start script should use lf | ||
| /gradlew text eol=lf | ||
|  | ||
| # These are Windows script files and should use crlf | ||
| *.bat text eol=crlf | ||
|  | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # Compiled class files | ||
| *.class | ||
|  | ||
| # Log files | ||
| *.log | ||
|  | ||
| # IntelliJ IDEA files | ||
| .idea/ | ||
|  | ||
| # Eclipse files | ||
| .classpath | ||
| .project | ||
| .settings/ | ||
|  | ||
| # Build output | ||
| build/ | ||
| out/ | ||
|  | ||
| # Dependency directories | ||
| .lib/ | ||
| libs/ | ||
|  | ||
| # Gradle specific | ||
| .gradle/ | ||
| gradle/ | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| /* | ||
| * This file was generated by the Gradle 'init' task. | ||
| * | ||
| * This generated file contains a sample Java application project to get you started. | ||
| * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle | ||
| * User Manual available at https://docs.gradle.org/8.1.1/userguide/building_java_projects.html | ||
| */ | ||
|  | ||
| plugins { | ||
| // Apply the application plugin to add support for building a CLI application in Java. | ||
| id 'application' | ||
| } | ||
|  | ||
| repositories { | ||
| // Use Maven Central for resolving dependencies. | ||
| mavenCentral() | ||
| } | ||
|  | ||
| dependencies { | ||
| // Use JUnit Jupiter for testing. | ||
| testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1' | ||
|  | ||
| // This dependency is used by the application. | ||
| implementation 'com.google.guava:guava:31.1-jre' | ||
| testImplementation 'org.assertj:assertj-core:3.21.0' | ||
| // JUnit 5 | ||
| testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2' | ||
| testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2' | ||
| } | ||
|  | ||
| // Apply a specific Java toolchain to ease working on different environments. | ||
| java { | ||
| toolchain { | ||
| languageVersion = JavaLanguageVersion.of(11) | ||
| } | ||
| } | ||
|  | ||
| application { | ||
| // Define the main class for the application. | ||
| mainClass = 'java.calculator.App' | ||
| } | ||
|  | ||
| tasks.named('test') { | ||
| // Use JUnit Platform for unit tests. | ||
| useJUnitPlatform() | ||
| } | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package example; | ||
|  | ||
| import example.calculator.CalculatorController; | ||
| import example.calculator.model.Calculator; | ||
| import example.calculator.view.Input; | ||
| import example.calculator.view.Output; | ||
|  | ||
| public class Main { | ||
| public static void main(String[] args) { | ||
| CalculatorController calculatorController = new CalculatorController(new Input(), new Output(), | ||
| new Calculator()); | ||
| calculatorController.start(); | ||
| } | ||
| } | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| package example.calculator; | ||
|  | ||
| import example.calculator.model.Calculator; | ||
| import example.calculator.view.Output; | ||
| import example.calculator.view.Input; | ||
|  | ||
| public class CalculatorController { | ||
| private Input input; | ||
| private Output output; | ||
| private Calculator calculator; | ||
|  | ||
| public CalculatorController(Input input, Output output, Calculator calculator) { | ||
| this.input = input; | ||
| this.output = output; | ||
| this.calculator = calculator; | ||
| } | ||
|  | ||
| public void start() { | ||
| while (true) { | ||
| output.printMenu(); | ||
| int choice = input.getIntInput(); | ||
|  | ||
| switch (choice) { | ||
| case 1: | ||
| output.printCalculationHistory(calculator.getCalculationHistory()); | ||
| break; | ||
| case 2: | ||
| handleCalculation(); | ||
| break; | ||
| default: | ||
| System.out.println("잘못된 선택입니다. 다시 선택해주세요."); | ||
|          | ||
| } | ||
| } | ||
| } | ||
|  | ||
| private void handleCalculation() { | ||
| input.getStringInput(); | ||
|  | ||
| System.out.print("수식을 입력하세요: "); | ||
|          | ||
| String expression = input.getStringInput(); | ||
|  | ||
| String[] tokens = expression.split("\\s+"); | ||
| double result = calculator.handleCalculation(tokens, expression); | ||
|  | ||
| output.printResult(result); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| package example.calculator.model; | ||
|  | ||
| import example.calculator.model.operation.Addition; | ||
| import example.calculator.model.operation.CalculationOperation; | ||
| import example.calculator.model.operation.Division; | ||
| import example.calculator.model.operation.Multiplication; | ||
| import example.calculator.model.operation.Subtraction; | ||
| import java.util.ArrayList; | ||
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
|  | ||
| public class Calculator { | ||
| private Map<String, CalculationOperation> calculationOperations; | ||
| private List<String> calculationHistory; | ||
| 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. 
 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. 네. 단일 책임 원칙(Single Responsibility Principle)을 따르는 것이 좋을 거 같은데 생각을 못했네요 🥲 | ||
|  | ||
| public Calculator() { | ||
| calculationOperations = new HashMap<>(); | ||
| calculationOperations.put("*", new Multiplication()); | ||
| calculationOperations.put("/", new Division()); | ||
| calculationOperations.put("+", new Addition()); | ||
| calculationOperations.put("-", new Subtraction()); | ||
| 
      Comment on lines
    
      +21
     to 
      +24
    
   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. 
 | ||
|  | ||
| calculationHistory = new ArrayList<>(); | ||
| } | ||
|  | ||
| public List<String> getCalculationHistory() { | ||
| return calculationHistory; | ||
| } | ||
|  | ||
| public double calculate(double a, double b, String operator) { | ||
| CalculationOperation operation = calculationOperations.get(operator); | ||
| if (operation == null) { | ||
| throw new IllegalArgumentException("Invalid operator: " + operator); | ||
| } | ||
|  | ||
| return operation.calculate(a, b); | ||
| } | ||
|  | ||
| private void addToCalculationHistory(String expression) { | ||
| calculationHistory.add(expression); | ||
| } | ||
|  | ||
| public double handleCalculation(String[] tokens, String expression) { | ||
| 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. 
 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. expression은 문자열 그대로 히스토리에 저장하기 위해 받고, tokens는 계산에 필요한 값들을 명확하게 표현하기 위해 따로 분리하였습니다! 따로 분리하는 것이 가독성이 좋아 보여 이렇게 사용했습니다 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. expression이 history를 저장하는 데만 사용하고 있어서, 가독성 측면에서 어떤게 좋은지 공감이 되질 않네요. token은 내부에서 split 하여 사용하는 것이 좋아보입니다 | ||
| List<String> operators = new ArrayList<>(); | ||
| List<Double> operands = new ArrayList<>(); | ||
|  | ||
| for (String token : tokens) { | ||
| if (token.matches("[+\\-*/]")) { | ||
|          | ||
| operators.add(token); | ||
| } else { | ||
| operands.add(Double.parseDouble(token)); | ||
| } | ||
| } | ||
|  | ||
| double result = getResult(operators, operands); | ||
|  | ||
| String calculationExpression = expression.replaceAll("\\s+", ""); | ||
| addToCalculationHistory(calculationExpression + " = " + result); | ||
| return result; | ||
| } | ||
|  | ||
| private double getResult(List<String> operators, List<Double> operands) { | ||
| calculateOperations(operands, operators, "*", "/"); | ||
| calculateOperations(operands, operators, "+", "-"); | ||
|  | ||
| return operands.get(0); | ||
| } | ||
|  | ||
| private void calculateOperations(List<Double> operands, List<String> operators, String... targetOperators) { | ||
| for (String targetOperator : targetOperators) { | ||
| for (int i = 0; i < operators.size(); i++) { | ||
| String operator = operators.get(i); | ||
| if (operator.equals(targetOperator)) { | ||
| 
      Comment on lines
    
      +73
     to 
      +76
    
   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. 다른 분들의 객체지향 생활 체조 관련 리뷰 참고 해주세요! | ||
| double operand1 = operands.get(i); | ||
| double operand2 = operands.get(i + 1); | ||
| double result = calculate(operand1, operand2, operator); | ||
|  | ||
| operands.set(i, result); | ||
| operands.remove(i + 1); | ||
| operators.remove(i); | ||
| i--; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package example.calculator.model; | ||
|  | ||
| public enum Menu { | ||
| 조회(1), | ||
| 계산(2); | ||
|          | ||
|  | ||
| private final int value; | ||
| 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. 
 | ||
|  | ||
| Menu(int value) { | ||
| this.value = value; | ||
| } | ||
|  | ||
| public int getValue() { | ||
| return value; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package example.calculator.model.operation; | ||
|  | ||
| public class Addition implements CalculationOperation { | ||
| @Override | ||
| public double calculate(double a, double b) { | ||
| return a + b; | ||
| } | ||
|  | ||
| @Override | ||
| public String getOperator() { | ||
| return "+"; | ||
| } | ||
| } | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package example.calculator.model.operation; | ||
|  | ||
| public interface CalculationOperation { | ||
| double calculate(double a, double b); | ||
| 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. double 타입은 연산이 부정확 할 수 있어요 | ||
|  | ||
| String getOperator(); | ||
| } | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package example.calculator.model.operation; | ||
|  | ||
| public class Division implements CalculationOperation { | ||
| @Override | ||
| public double calculate(double a, double b) { | ||
| if (b != 0) { | ||
| return a / b; | ||
| } else { | ||
| throw new IllegalArgumentException("Cannot divide by zero."); | ||
| } | ||
| } | ||
|  | ||
| @Override | ||
| public String getOperator() { | ||
| return "/"; | ||
| } | ||
| } | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package example.calculator.model.operation; | ||
|  | ||
| public class Multiplication implements CalculationOperation { | ||
| @Override | ||
| public double calculate(double a, double b) { | ||
| return a * b; | ||
| } | ||
|  | ||
| @Override | ||
| public String getOperator() { | ||
| return "*"; | ||
| } | ||
| } | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package example.calculator.model.operation; | ||
|  | ||
| public class Subtraction implements CalculationOperation { | ||
| @Override | ||
| public double calculate(double a, double b) { | ||
| return a - b; | ||
| } | ||
|  | ||
| @Override | ||
| public String getOperator() { | ||
| return "-"; | ||
| } | ||
| } | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package example.calculator.view; | ||
|  | ||
| import java.util.Scanner; | ||
|  | ||
| public class Input { | ||
| private Scanner scanner; | ||
|  | ||
| public Input() { | ||
| scanner = new Scanner(System.in); | ||
| } | ||
|  | ||
| public int getIntInput() { | ||
| return scanner.nextInt(); | ||
| } | ||
|  | ||
| public String getStringInput() { | ||
| return scanner.nextLine(); | ||
| } | ||
| } | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package example.calculator.view; | ||
|  | ||
| import example.calculator.model.Menu; | ||
| import java.util.List; | ||
|  | ||
| public class Output { | ||
| public void printCalculationHistory(List<String> calculationHistory) { | ||
| for (String history : calculationHistory) { | ||
| System.out.println(history); | ||
| } | ||
| } | ||
|  | ||
| public void printMenu() { | ||
| System.out.println(Menu.조회.getValue() + ". " + Menu.조회); | ||
| System.out.println(Menu.계산.getValue() + ". " + Menu.계산); | ||
|          | ||
| } | ||
|  | ||
| public void printResult(double result) { | ||
| System.out.println("결과: " + result); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package example.calculator.model; | ||
|  | ||
| import static org.assertj.core.api.Assertions.assertThat; | ||
|  | ||
| import java.util.stream.Stream; | ||
| import org.junit.jupiter.params.ParameterizedTest; | ||
| import org.junit.jupiter.params.provider.Arguments; | ||
| import org.junit.jupiter.params.provider.MethodSource; | ||
|  | ||
| public class CalculatorTest { | ||
|  | ||
| @ParameterizedTest | ||
| @MethodSource("testData") | ||
| public void testCalculate(double operand1, double operand2, String operator, double expected) { | ||
| Calculator calculator = new Calculator(); | ||
| double result = calculator.calculate(operand1, operand2, operator); | ||
| assertThat(result).isEqualTo(expected); | ||
| } | ||
|  | ||
| private static Stream<Arguments> testData() { | ||
| return Stream.of( | ||
| Arguments.of(1, 2, "+", 3), | ||
| Arguments.of(1, 2, "-", -1), | ||
| Arguments.of(2, 3, "*", 6), | ||
| Arguments.of(4, 2, "/", 2) | ||
| ); | ||
| 
      Comment on lines
    
      +20
     to 
      +26
    
   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. 👍 | ||
| } | ||
| } | ||
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.
true, 1, 2는 변수명으로 의미있는 이름을 부여해주세요