Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3d4ec74
docs(guide): list of implementation functions and TDD case
oereo Feb 23, 2021
59160fa
docs(guide): add TDD case
oereo Feb 24, 2021
fd2266a
feat: java-calculator basic structure design and implementation
oereo Feb 25, 2021
25e3e7a
feat: add a method to initialize and rerun the calculator
oereo Feb 25, 2021
3f697e6
feat: add exception message list
oereo Feb 25, 2021
a0723cc
refactor: fix message format in ErrorException and Message class
oereo Feb 25, 2021
9aab010
refactor: delete unused parameter in OperatorSetting class
oereo Feb 25, 2021
f53fdf9
Merge pull request #1 from oereo/feature/java-calculator
oereo Feb 25, 2021
ef52572
refactor: delete the userInputData class
oereo Feb 25, 2021
9199b85
refactor: reset variable names that don't fit naming
oereo Feb 25, 2021
860bcd7
refactor: rename variable name [exception]
oereo Feb 25, 2021
b6d6340
Merge pull request #2 from oereo/fix/java-calculator
oereo Feb 25, 2021
529f7e4
feat: add TDD basic format and test case for calculator class
oereo Feb 25, 2021
52021fa
Merge pull request #3 from oereo/fix/java-calculator-TDD
oereo Feb 25, 2021
02edb1f
refactor: fix exception handling part divided by 0
oereo Feb 25, 2021
c3b416c
feat: add comments to those classes and methods
oereo Feb 25, 2021
fc69dd8
Merge pull request #4 from oereo/feature/java-calculator-comment
oereo Feb 26, 2021
825f9c8
feat: add invalid test case
oereo Feb 26, 2021
8081d30
Merge pull request #5 from oereo/feature/java-calculator-TDD-invalid
oereo Feb 26, 2021
2e4c9ce
refactor: Calculator 객체 멤버변수로 변경
songpang Mar 26, 2021
d3be60f
refactor: Test코드 수정
songpang Mar 26, 2021
7d05e50
refactor: 변수 접근자 설정
songpang Mar 26, 2021
2cc067f
refactor: 사용하지 않는 method 삭제
songpang Mar 26, 2021
ac1d609
refactor: method 로직 분리
songpang Mar 26, 2021
74de276
refactor: 에러처리
songpang Mar 26, 2021
f76879f
refactor: Interface 이름 변경
songpang Mar 26, 2021
ec31a1b
refactor: 사용하지 않는 test code 제거
songpang Mar 26, 2021
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
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ repositories {
}

dependencies {
implementation 'junit:junit:4.12'
implementation 'junit:junit:4.12'
implementation 'org.testng:testng:7.1.0'
testCompile('org.junit.jupiter:junit-jupiter:5.6.0')
testCompile('org.assertj:assertj-core:3.15.0')
}
Expand Down
2 changes: 2 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
rootProject.name = 'java-calculator'

61 changes: 61 additions & 0 deletions src/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Java-Calculator

Create a string calculator and write test code for it

## Contributor
- oereo

## Branch structure

### oereo branch
* from `oereo/java-calculator[oereo branch]` to `biforest/java-calculator [oereo branch]`

### java-calculator-structure branch
* Feature branch : Branch to develop the function ex)feature/java-calculator
* Fix branch : Branch to fix the function ex)fix/java-calculator

## TDD
### Failure case
#### (1) When divided by 0
```console
연산을 입력해주세요 : 2/0 // error
```
#### (2) When two or more operation symbols appear in a row
```console
연산을 입력해주세요 : 2++0 // error
```
#### (3) When the operation symbol appears at the beginning
```console
연산을 입력해주세요 : +2+0 // error
```
#### (4) When special characters other than operation symbols are entered
```console
연산을 입력해주세요 : 2^4 // error
```
#### (5) When characters excluding numbers and operators are entered
```console
연산을 입력해주세요 : 2ㄱㄴ4*4 // error
```
#### (6) When the formula ends with an operation symbol
```console
연산을 입력해주세요 : 2-1* // error
```
## Structure
#### 1. Class
- Calculator class
- `+ class`
- `- class`
- `* class`
- `/ class`
- Input class
- Output class
- `Error message` output
- `Calculation result` output
- Error exception class
- Precautions : only use `try ~ catch`
- Init class
- When an error occurs, reset after outputting an error message
- Reset and input when pressing any key value
Comment on lines +45 to +58

Choose a reason for hiding this comment

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

겉멋을 잔뜩 부려놓으셨는데 나쁘지않네요~


#### 2. Algorithm
- DFS, Node
14 changes: 14 additions & 0 deletions src/main/java/calculator/AddOperation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package calculator;

public class AddOperation implements Operation {
@Override
public String operationName() {
return "+";
}

@Override
public int calculation(int beforeNumber, int afterNumber) {
int Result = beforeNumber + afterNumber;
return Result;
}
}
11 changes: 11 additions & 0 deletions src/main/java/calculator/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package calculator;


public class Application {
public static void main(String[] args) {

// Declare calculator object and start calculation

Choose a reason for hiding this comment

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

곳곳에 주석을 잘 작성해주셨네요!
주석도 좋지만, 좋은 코드는 주석 없이 이해가 되는 코드에요.
주석을 제거하는 대신 변수명과 메소드명을 통해 의미가 잘 드러나도록 하는것이 베스트에요.

그렇다면 주석이 필요 없냐? 그건 또 아닙니다.
팀 문화의 탄생 - 우아한형제들 기술블로그에 나오는 내용인데 한번쯤 생각해보면 좋을것같아요

보통 코드에 주석 다는 것을 죄악으로 보는 경우가 있는데, 이는 코드가 “무엇을 하는지”에 관한 주석일 경우에는 그렇습니다. “무엇”은 위에서 처럼 변수나 메소드 네이밍으로 충분히 주석없이 처리가 가능한 경우가 많습니다.
하지만 “왜 하는지”는 다른 문제입니다. 도대체 고객에게 줄 돈에서 500원을 더하는데 상수의 이름을 봐도 그래서 왜 더하는지 모르겠습니다.
현실 비즈니스의 세계는 결코 논리적이지 않습니다. 온갖 황당한 이유로 코드가 꼬이기 마련이며, 거기에 명확한 이유를 적어두지 않으면 나중에 다른 개발자가 보고서 ‘이건 왜이러지? 버그아냐?’ 하고 다른 사람들에게 왜 그랬는지 물어보게 되고, 그걸 개발한 개발자조차도 왜 그랬는지는 이미 까먹었고, 버그였나보다 하고 코드를 삭제했더니 갑자기 고객 센터 전화기에 불이나기 시작합니다. 사실은 다 이유가 있었습니다.
주석으로 항상 왜를 적어둡니다. 코드와 최대한 가까운 거리에 이유를 적어두는 것이 좋습니다. 최소한 관련 사항이 명시된 문서 링크라도 달아두어야 합니다(@see javadoc tag 사용).
주석보다 더 나은 방법은 500원을 더하는 테스트 코드를 명확히 작성해두고, 테스트코드 메소드명 혹은 설명(description)에 이유를 적어두는 것입니다.

Calculator calculator = new Calculator();
calculator.calculation();
}
}
46 changes: 46 additions & 0 deletions src/main/java/calculator/ArithmeticExpressionStack.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package calculator;


interface Stack{

Choose a reason for hiding this comment

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

스택, 큐 같은 자료구조는 대부분의 언어에 기본적으로 내장되어있습니다.
내장된 API를 사용하지 않고 구현하는 것은 오히려 비효율을 유발해요.
협업을 할 때 내장된 API는 자바 개발자들이 학습하지만 이 경우 현수님이 짠 코드를 추가로 분석해야하기 때문이에요.
자바 컬렉션의 Stack을 사용하는 식으로 변경해보세요

boolean isEmpty();
String pop();
void clear();
}
Comment on lines +4 to +8
Copy link
Member

Choose a reason for hiding this comment

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

저는 인터페이스는 여러 클래스가 동일한 기능을 하도록 기준을 잡아주는 역할을 하는것으로 알고있는데 이 구조를 사용하는 클래스는 ArithmeticExpressionStack 클래스 하나인데 인터페이스를 사용하신 이유가 무엇인가요?

Copy link
Member Author

Choose a reason for hiding this comment

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

이후 코드 확장성 측면을 생각하여 인터페이스를 사용했습니다.


public class ArithmeticExpressionStack implements Stack {
private int stackSize;
private int flag;
private String stack[];

public ArithmeticExpressionStack(String[] equation, int stackSize){
clear();
flag = 0;
this.stackSize = stackSize;
stack = equation;
}

public String pop(){
if(isEmpty()){
return "스택이 존재하지 않습니다.";
}
else{
return stack[flag++];
}
}

public boolean isEmpty(){
return (flag == this.stackSize);
}

public void clear(){
if(!isEmpty()){
flag = -1;
this.stackSize = stackSize;
}
}

public int getStackSize(){
return this.stackSize;
}

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

import java.util.Scanner;


public class Calculator {
private Message message = new Message();

/**
* calculation method
* 1. getEquation - Receives numeric expression in string format entered by user
* 2. Put numeric expressions on the stack
* 3. Passing the stack to the operatorSetting method
*
* return type : void
*/
public void calculation(){
String[] equation_list = getEquation();
ArithmeticExpressionStack arithmeticExpressionStack = new ArithmeticExpressionStack(equation_list, equation_list.length);
OperatorSetting(arithmeticExpressionStack);

}

/**
* OperatorSetting method
* 1. Pop each operator and number onto the stack.
* 2. Perform error exception check and calculate
* 3. After the calculation process is complete, call init() to determine whether to return the calculator
*
* return type : void
*/
public void OperatorSetting(ArithmeticExpressionStack arithmeticExpressionStack) {
ErrorException exceptionCheck = new ErrorException();
String firstString = arithmeticExpressionStack.pop();
// Error checking when converting string to int
int cumulativeResult = exceptionCheck.NumericalError(firstString);

for(int i = 0; i<(arithmeticExpressionStack.getStackSize())/2;i++){
String operator = arithmeticExpressionStack.pop();
String secondString = arithmeticExpressionStack.pop();
int secondNumber = exceptionCheck.NumericalError(secondString);

// calculated value are continuously accumulated
cumulativeResult = chooseOperatorAndCalculate(cumulativeResult, operator, secondNumber);
}

if(cumulativeResult != 0){
message.calculationResult(cumulativeResult);
}

// Whether to re-execute after calculation
init();
}

/**
* chooseOperatorAndCalculate method
* 1. Pop each operator and number onto the stack.
* 2. Perform error exception check and calculate
* 3. After the calculation process is complete, call init() to determine whether to return the calculator
*
* return type : int
*/
public int chooseOperatorAndCalculate(int firstNumber, String operator, int SecondNumber){
AddOperation addOperation = new AddOperation();
SubOperation subOperation = new SubOperation();
MultiplyOperation multiplyOperation = new MultiplyOperation();
DivideOperation divideOperation = new DivideOperation();
int result = 0;

// When the operator is equal to "+"
if (operator.equals(addOperation.operationName())){
result = addOperation.calculation(firstNumber, SecondNumber);
}

// When the operator is equal to "-"
else if (operator.equals(subOperation.operationName())){
result = subOperation.calculation(firstNumber, SecondNumber);
}

// When the operator is equal to "*"
else if (operator.equals(multiplyOperation.operationName())){
result = multiplyOperation.calculation(firstNumber, SecondNumber);
}

// When the operator is equal to "/"
else if (operator.equals(divideOperation.operationName())){
result = divideOperation.calculation(firstNumber, SecondNumber);
}

// Raise error when a symbol that does not correspond to the arithmetic operations(+, -, *, /) comes
else{
try {
throw new Exception();
} catch (Exception e) {
e.getMessage();
message.exceptionResult("NOT_OPERATOR");
}
}

return result;
}

/**
* init method
* - Input "1" to redo calculator.
* - Input another key to exit
*
* return type : void
*/
public void init(){
Scanner scanner = new Scanner(System.in);
System.out.println("계산을 계속 진행하시려면 1, 멈추시려면 임의의 다른키를 눌러주세요");
String value = scanner.nextLine();

if(value.equals("1")){
calculation();
}
else{
System.exit(0);
}
}

/**
* getEquation method
* - Method to receive user input data
*
* return type : void
*/
String[] getEquation() {
String value = inputValues();
String[] values = value.split(" ");
return values;
}

private String inputValues() {
Scanner scanner = new Scanner(System.in);
System.out.print("수식을 입력해주세요 : ");
String value = scanner.nextLine();
return value;
}


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

public class DivideOperation implements Operation {
@Override
public String operationName() {
return "/";
}

@Override
public int calculation(int beforeNumber, int afterNumber) {
Message message = new Message();
try{
int Result = beforeNumber / afterNumber;
return Result;
}
catch (ArithmeticException e){
message.exceptionResult("INVALID_DIVIDE");
}
return 0;
}
}
23 changes: 23 additions & 0 deletions src/main/java/calculator/ErrorException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package calculator;

public class ErrorException {
Message message = new Message();

/**
* NumericalError method
* - Raise error when string is not converted to int
*
* return type : void
*/
public int NumericalError(String number) {
int numberConverted = 0;
try {
numberConverted = Integer.parseInt(number);
} catch (NumberFormatException e) {
message.exceptionResult("INVALID_EQUATION");
Calculator calculator = new Calculator();
calculator.init();
}
return numberConverted;
}
}
32 changes: 32 additions & 0 deletions src/main/java/calculator/Message.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package calculator;

import java.util.HashMap;

/**
* Message class
* - message output class
*
* return type : void
*/
public class Message {
HashMap<String, String> exceptionMessageList = new HashMap<String, String>();

// Result output method when operation is normally performed
public void calculationResult(int result){
System.out.print("결과 : ");
System.out.println(result);
}

// Error message list management method
private void exceptionMessageList(){
exceptionMessageList.put("NOT_OPERATOR", "사칙연산 기호에 해당하지 않는 기호가 존재합니다.");
exceptionMessageList.put("INVALID_EQUATION", "잘못된 연산식입니다.");
exceptionMessageList.put("INVALID_DIVIDE", "0으로 나눌수가 없습니다.");
}

// Error message output method
public void exceptionResult(String exceptionKeyword){
exceptionMessageList();
System.out.println(exceptionMessageList.get(exceptionKeyword));
}
}
14 changes: 14 additions & 0 deletions src/main/java/calculator/MultiplyOperation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package calculator;

public class MultiplyOperation implements Operation {
@Override
public String operationName() {
return "*";
}

@Override
public int calculation(int beforeNumber, int afterNumber) {
int Result = beforeNumber * afterNumber;
return Result;
}
}
Loading