-
Notifications
You must be signed in to change notification settings - Fork 156
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
[4기-구범모] 1~2주차 과제 : 계산기 구현 미션 제출합니다. #144
base: BeommoKoo-dev2
Are you sure you want to change the base?
[4기-구범모] 1~2주차 과제 : 계산기 구현 미션 제출합니다. #144
Conversation
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.
추가 리뷰 남겼습니다. 확인해주세요
src/main/java/domain/Command.java
Outdated
public String[] commandArr; | ||
public int[] numberArr; | ||
public Operator[] optArr; | ||
public int optCount; |
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.
private
으로 변경이 필요해 보입니다!
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.
private로의 변경 이유는, 클라이언트 코드에서 함부로 command의 내용을 갖고오거나, 변경을 막기 위함일까요??
src/main/java/domain/Command.java
Outdated
public String makeHistory(int result) { | ||
return String.join(" ", this.commandArr) + " = " + result; | ||
} |
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.
Command가 history 생성 책임을 가지는 이유가 뭔가요?
src/main/java/domain/Menu.java
Outdated
|
||
private final int menuNum; | ||
private final String menuName; | ||
public static int menuCount = 3; |
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.
public static int menuCount = 3; | |
public static final int MENU_COUNT = 3; |
Operator PM; | ||
Operator MD; |
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.
Operator PM; | |
Operator MD; | |
private Operator PM; | |
private Operator MD; |
private void stackPush(int number, Stack<Integer> st) { | ||
if(st.isEmpty()) { | ||
st.push(number); | ||
return; | ||
} | ||
int top = st.peek(); | ||
st.pop(); | ||
st.push(MD.calculateOpt(top, number)); | ||
} |
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.
stack에 push 하는 것 외 다른 일도 하는 것 같네요. 이름을 변경해줄 필요가 있을 것 같습니다
int[] numberArr = command.numberArr; | ||
Operator[] optArr = command.optArr; | ||
|
||
Stack<Integer> st = new Stack<>(); |
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.
자바는 일반적으로 변수명을 줄이지 않습니다.
Stack<Integer> st = new Stack<>(); | |
Stack<Integer> stack = new Stack<>(); |
src/main/java/service/Operator.java
Outdated
public boolean decideToCalculate() { | ||
if(this == PLUS || this == MINUS) | ||
return true; | ||
return false; | ||
} |
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.
decideToCalculate
는 PLUS, MINUS인 경우만 true를 반환하고 있는데, MULTIPLY, DIVIDE인 경우에는 false를 반환하고 있네요. 메서드 이름만 보면 곱하기 나누기는 연산을 지원하지 않는 것 같아요.
public class PrintOutMessage { | ||
|
||
public static final String EXIT_MESSAGE = "EXIT calculate .."; | ||
public static final String EMPTY_MESSAGE = "Repository is EMPTY!!"; | ||
|
||
} |
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.
상수 클래스를 사용한 이유가 있나요. 두 메시지 모두 각각 한 클래스에서만 사용 하네요
|
||
while(true) { | ||
try { | ||
output.printMenu(Menu.values()); |
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.
말씀해주신 피드백을 반영하여, 기존과 동일하게 printMenu의 책임은 output에 있지만, 인자로 Menu.values를 넣어주어 menu ENUM이 관여하도록 했습니다.
private String[] commandArr; | ||
private int[] numberArr; | ||
private Operator[] optArr; | ||
private int optCount; | ||
|
||
public Command(String[] commandArr) { | ||
this.commandArr = commandArr; | ||
this.optCount = commandArr.length / 2; | ||
this.numberArr = new int[optCount + 1]; | ||
this.optArr = new Operator[optCount]; | ||
|
||
parseComamand(); | ||
} | ||
|
||
public String[] getCommandArr() { | ||
return commandArr; | ||
} | ||
|
||
public int[] getNumberArr() { | ||
return numberArr; | ||
} | ||
|
||
public Operator[] getOptArr() { | ||
return optArr; | ||
} | ||
|
||
public int getOptCount() { | ||
return optCount; | ||
} |
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.
말씀하신 Command의 필드들을 private으로 지정하고, 그에 맞게 getter / setter 메소드를 만들어 주었습니다.
public String getHistory() { | ||
return history; | ||
} | ||
} |
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.
기존에는 Command에서 history를 만드는 책임이 있었지만, 그럴 필요가 없다는 피드백을 수긍하여 History 클래스를 만들어 주고, Controller 클래스에서 한줄로 입력받은 수식(commandArr)와 계산결과로 나온 result를 합쳐 하나의 history를 만들 수 있도록 변경했습니다.
|
||
import java.util.List; | ||
|
||
public interface HistoryRepository { |
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.
승훈님이 말씀해주신 대로, History를 저장하는 저장소이므로, HistoryRepository로 인터페이스의 이름을 수정했고,
그에따라 구현체 클래스명도 MapHistoryRepository로 변경하였습니다.
return result; | ||
} | ||
|
||
private void calculateAndPush(int number, Stack<Integer> stack) { |
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.
기존에는 stackPush라는 네이밍을 했었는데, 메소드 내에서 push뿐만이 아닌 연산도 하므로 메소드명을 수정했습니다.
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.
메서드가 두 가지 일을 하고 있는 것 같아요. calculate와 push가 분리되면 좋겠네요
return optName; | ||
} | ||
|
||
public boolean isPlusOrMinus() { |
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.
승훈님의 피드백을 수긍하여 메소드명 수정했습니다.
private static final String EXIT_MESSAGE = "EXIT calculate .."; | ||
public static final String EMPTY_MESSAGE = "Repository is EMPTY!!"; |
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.
기존의 util 패키지에서 모아뒀던 상수들을 ConsoleOutput클래스로 옮겨주었습니다.
} | ||
|
||
@Override | ||
public void showHistory(List<History> historyList) { |
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.
MapHistoryRepository에서 반환된 historyList 내의 history를 출력하도록 메소드를 수정했습니다.
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.
- showHistory의 파라미터를 HistoryRepository로 전달하여, 해당 Repository 내의 History를 모두 출력하려 했으나, 결국 Output과 Repository는 서로 정보를 몰라야 한다고 생각하여(MVC패턴 기준) historyList를 dto느낌으로 인자로 넣어주었습니다.
- 하지만 List형식을 받아서 history를 출력한다면 기존의 Map으로 저장했던 history를 출력하는 것보다 성능상 안좋을까요?? (모든 history를 출력하는건 List이든 Map이든 O(n)이지만, map이 key값으로 접근하는 것이므로 List보단 메모리접근? 쪽에서 빠를것 같다는 생각이 듭니다.)
- 만약 성능상 List가 더 안좋다 하더라도, Output과 Repository는 서로의 정보를 몰라야 되기 때문에 1번의 오버헤드정도는 감수해야 하는 것일까요??
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.
범모님 리뷰 남겼습니다.
Scanner 자원 회수는 ConsoleInput에서 이루어지고 있는 것 같은데요?
java-calculator.iml
Outdated
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.
요것도 .gitignore에 추가해주세요
break; | ||
|
||
case CALCULATEMENU: | ||
Command command = new Command(input.getLineAndParse()); |
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.
And를 사용하고 있는 것으로 보아, 메서드가 두 가지 일을 하고 있는 것 같아요
public class History { | ||
private String history; | ||
|
||
public History(String[] commandArr, int result) { |
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.
단순 String 배열보다는 Command 타입을 받는 것이 좋아보이네요
|
||
public void run() { | ||
|
||
while(true) { |
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.
의미있는 이름을 가진 변수를 사용하면 좋겠네요.
private Operator PM; | ||
private Operator MD; |
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.
인스턴스 변수로 선언되지 않고, 지역 변수로 충분할 것 같아요. 그리고 자바 네이밍 규칙을 준수해주세요. 상수를 제외한 변수의 이름은 카멜 케이스로 작성해주세요
private static List<String> toStringArray(Operator[] operators) { | ||
return Arrays.stream(operators) | ||
.map(Operator::getOptName) | ||
.collect(Collectors.toList()); | ||
} |
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.
이 메서드가 Operator에 위치할 필요가 있을까요?
|| Integer.parseInt(menuCandidate) < 0) { | ||
throw new IllegalArgumentException(printError("MENU")); | ||
} | ||
return getMenu(Integer.parseInt(menuCandidate)); |
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.
사용자의 입력을 받고 반환만 해주고, 메뉴 객체는 클라이언트 코드에서 해줘도 좋을 것 같아요
|
||
class CalculatorTest { | ||
|
||
static Calculator calculator; |
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.
접근 제어자를 추가해주세요
static Command command; | ||
static int[] compNumArr; | ||
static Operator[] compOptArr; | ||
static Calculator calculator; | ||
|
||
@BeforeAll | ||
public static void setting() { | ||
command = new Command(stringToArray("1 + 2 + 3")); | ||
compNumArr = new int[] {1, 2, 3}; | ||
compOptArr = new Operator[] {Operator.PLUS, Operator.PLUS}; | ||
calculator = new Calculator(); | ||
} |
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.
멤버가 테스트전 딱 한번만 초기화 되므로 다른 테스트에 영향을 줄 것 같아요 @BeforeEach
를 사용하도록 변경하는 것이 좋겠네요
계산기 과제2
리뷰 반영사항
.idea/
폴더는 intelliJ를 이용하면서 만들어지는 폴더인데 gitignore 처리를 해주시면 좋을 것 같아요! → .idea, .gradle 폴더를 .gitignore처리하였습니다.입력을 받기 위한 준비, 출력, 출력해야할 것들에 대한 정보를 가지고 있는 등! 역할을 나눠보시면 좋을 것 같아요! → Controller라는 클래스로 view에 대한 정보를 갖고 있는 객체, 비즈니스 로직(계산)을 처리하는 service객체들을 갖고 있고, view와 service간에 서로의 정보를 모르도록 분리했습니다.
이런 부분도 역할로 보고 분리하시면 좋을 것 같아요! → Input, Output 인터페이스를 만들어 두고, 구현체로써 ConsoleInput, ConsoleOutput을 만들어 주었습니다. 이는 나중에 input, output형식이 달라질 경우 인터페이스를 상속받아 다른 구현체로 갈아끼기에 유연한 구조라고 생각했습니다.
Calculator
에서 사칙 연산자 Enum을 잘 사용하고 계시네요. 그렇다면 어떤 문자 s가 사칙 연산자인지 확인하는 로직은 Enum이 가지고 있어야 하지 않을까요? 자바의 Enum은 단순한 상수의 열거 타입이 아니에요. 완벽한 싱글톤 인스턴스입니다. 따라서 활용도가 매우 높아요 아래 링크를 확인해보고 수정해주세요 → Input으로 입력될 때 해당 연산자가 맞는 연산자인지 판단했습니다.Memorizer
의 역할은 입력 받은 사칙 연산과 그 결과를 저장 및 조회하는 역할인 것 같아요. 그렇다면 결과를 화면에 출력하는 것은Memorizer
의 역할이 아니에요. 결과를 저장, 조회 하는 행위만 할 수 있도록 해주세요 → Output view에서 출력을 담당하고 싶었지만, 동시에 Output 인터페이스의 showHistory()메소드에서 다형성(showHistory의 인자로 들어가는 Repository의 다형성)을 이용하고 싶었기에 인자로 들어가는 repository에서 출력을 하도록 하고, Output view에서는 repository의 출력 함수를 감싸주는 역할만 했습니다.궁금한 점 : 프로그램 종료시 ConsoleOutput 클래스에서 자원회수를 했습니다.(scanner.close) 자원생성의 주체는 ConsoleInput클래스가 담당했는데, 자원정리를 타 클래스인 ConsoleOutput클래스에서 해주어도 되나요 ? 아니면 exitProgram()하기 전에 ConsoleInput클래스에서 자원회수를 담당하는 것이 좋을까요??