Skip to content
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주차 과제 : 계산기 구현 미션 제출합니다. #147

Open
wants to merge 26 commits into
base: kju2405
Choose a base branch
from

Conversation

kju2405
Copy link

@kju2405 kju2405 commented Jun 9, 2023

📌 과제 설명

  1. 계산기능을 수행하는 Calculate, 사용자로 부터 입력을 받는 Input, 사용자에게 보여주는 Output, 계산 기록을 저장하는 Repository 패키지를 각각 만들었습니다.
  2. 기존에 구현한 코드를 보다 더 객체지향적인 코드로 변경하려고 노력하였습니다.
  3. 예제와 같이 올바르게 입력된 상황이라는 가정하에 구현하였고 그 외의 예외처리에 대해서는 아직 하지 않았습니다. 구조가 잡힌다면 바로 구현하도록 하겠습니다.

👩‍💻 요구 사항과 구현 내용

✅ 피드백 반영사항

Main.java

  • "변수의 불변성을 보장해주세요"-> private static int choice; 로 처리하였는데 이렇게 하는 방법이 맞는지 궁금합니다.
  • "인터페이스가 아니라 구현체를 직접 사용하는게 적절한지 생각해보세요" -> 추상화에 의존하기 위하여 코드를 수정하였습니다.
  • "계산 한 번 할 때마다 계산기를 계속 생성해야할까요?" -> 처음 한번만 생성되게끔 하였습니다.
  • "비슷한 기능을 하는 메소드들을 다른 객체로 추출하는 건 어떨까요?" -> 다른 객체로 추출하였습니다.

Calculate.java

  • "계산기의 기능을 다시 고민해보면 좋을 것 같네요" / "조금 더 추상화가 필요하다고 할 수 있겠네요 ㅎㅎ! 기능에 따라 여러 역할로 객체를 나누어 보는 건 어떨까요?" -> 계산기 구현체에서는 식을 입력받고 결과값을 반환하는것 외의 기능은 보이지 않게끔 수정하였습니다.

ExpressionRepository.java

  • "복수형을 반환하면 getRecords()가 좀 더 좋아보이네요" -> 수정하였습니다!
  • "요구사항 그대로 값을 저장하는 것도 좋지만,추후에 출력되어야 할 값이 바뀔 경우를 고려해보는 건 어떨까요?" -> 이 부분은 조금 더 고민해보겠습니다😭

UserInterfaceImpl.java

  • "값을 가져오는 것과, 값을 출력하는 기능은 여러 기능을 한 번에 수행하는 것 처럼 보여요. " -> 기능 분리하였습니다.

✅ PR 포인트 & 궁금한 점

CalOrderImpl.java파일에서 calculateMultiplyDivide 메서드와 calculatePlusMinus메서드를 어떻게 테스트할 수 있을까? 고민하며 리펙토링을 해보려 하였습니다. 하지만 지금 로직을 테스트하기 좋게 어떻게 고칠까에 대한 답은 내리지 못하였습니다. 그래서 이렇게 테스트 코드를 작성하는것은 비효율적인가? 라는 생각을 가지며 테스트 코드를 작성하였습니다. 작성하는 과정에서 테스트코드를 위해 calculateMultiplyDivide메서드의 반환타입을 String으로 변경한것이 찝찝하긴 합니다.

제가 궁금한점은.. 계산하는 로직 부분을 어떻게 고치는게 좋을지 잘 모르겠습니다.....

Comment on lines 4 to 5
public abstract void calPriorityFirst();
public abstract void calPrioritySecond();

Choose a reason for hiding this comment

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

interface의 메서드는 기본적으로 추상 메서드이기 때문에 abstract가 없어도 됩니다.

int choice = 0;

while (true) {
choice = getChoice();

Choose a reason for hiding this comment

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

변수의 불변성을 보장해주세요

choice = getChoice();
System.out.println();
if (choice == 1) {
new UserInterfaceImpl().showRecord();

Choose a reason for hiding this comment

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

인터페이스가 아니라 구현체를 직접 사용하는게 적절한지 생각해보세요

new UserInterfaceImpl().showRecord();
} else {
String expression = typeExpression();
new Calculate(expression).calculate();

Choose a reason for hiding this comment

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

계산 한 번 할 때마다 계산기를 계속 생성해야할까요?


import java.util.Stack;

public class Calculate implements CalOrder{

Choose a reason for hiding this comment

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

계산기의 기능을 다시 고민해보면 좋을 것 같네요

Copy link
Author

Choose a reason for hiding this comment

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

주말인데 불구하고 리뷰 남겨주셔서 감사합니다!😄
남겨주신 리뷰 확인하며 수정하는도중에 궁금한 사항이 생겨서요.
혹시 나누기 연산을 시행했을때의 기능 말씀이신지 아니면 전체적으로 효율적이지 못한(?) 계산기 수행 로직이라 전체적인 변경이 필요한지 궁금해서요!
감사합니다!

Choose a reason for hiding this comment

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

기본적으로 계산기는 사칙연산을 연산 규칙에 맞춰서 제공해주는 기계라고 봐야해요.
그렇다면 사용자가 마음대로 연산 규칙을 변경해서는 안되겠죠??
사용자가 연산 순서를 바꾸고 싶다면 계산기를 바꾸는게 아니라 연산 식을 새롭게 입력하는 걸 생각해보시면 될 것 같아요.

그렇게 하려면 수식입력, 계산 두 기능만 외부 오픈을 하고 그 외의 모든 내용은 내부적으로 감춰줘야해요.
계산기라는 객체를 실제 계산기라고 봤을 때 수식입력, 계산 외에 다른 기능이 외부에 보인다면 잘못 사용될 여지가 있겠네요.

Copy link
Author

Choose a reason for hiding this comment

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

아하 자세하게 설명해주셔서 감사합니다!
말씀해주신 부분 생각해서 수정해보도록 하겠습니다!

Copy link

Choose a reason for hiding this comment

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

조금 더 추상화가 필요하다고 할 수 있겠네요 ㅎㅎ!
기능에 따라 여러 역할로 객체를 나누어 보는 건 어떨까요?

@kju2405 kju2405 self-assigned this Jun 11, 2023
Copy link

@ICCHOI ICCHOI left a comment

Choose a reason for hiding this comment

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

안녕하세요 재웅님! 리뷰가 늦어졌네요 :(
전체적으로 로직이 잘 들어나는 점은 좋았어요!
하지만 좀 더 객체지향적으로 리팩토링 해보시면 더 좋겠다는 생각이 들었습니다 ;)


import java.util.Stack;

public class Calculate implements CalOrder{
Copy link

Choose a reason for hiding this comment

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

조금 더 추상화가 필요하다고 할 수 있겠네요 ㅎㅎ!
기능에 따라 여러 역할로 객체를 나누어 보는 건 어떨까요?

Comment on lines 15 to 17
public List<String> getRecord() {
return store;
}
Copy link

Choose a reason for hiding this comment

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

복수형을 반환하면 getRecords()가 좀 더 좋아보이네요


@Override
public void save(String expression, int result) {
store.add(expression + " = " + result);
Copy link

Choose a reason for hiding this comment

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

요구사항 그대로 값을 저장하는 것도 좋지만,
추후에 출력되어야 할 값이 바뀔 경우를 고려해보는 건 어떨까요?

Comment on lines 24 to 35
public static int getChoice() {
Scanner scanner = new Scanner(System.in);

System.out.println("1. 조회\n2. 계산\n");
System.out.print("선택 : ");
return scanner.nextInt();
}

public static String typeExpression() {
Scanner scanner = new Scanner(System.in);
return scanner.nextLine();
}
Copy link

Choose a reason for hiding this comment

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

비슷한 기능을 하는 메소드들을 다른 객체로 추출하는 건 어떨까요?

Comment on lines 9 to 12
public void showRecord() {
List<String> record = repository.getRecord();
record.forEach(System.out::println);
}
Copy link

Choose a reason for hiding this comment

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

값을 가져오는 것과, 값을 출력하는 기능은 여러 기능을 한 번에 수행하는 것 처럼 보여요.

@kju2405 kju2405 marked this pull request as draft June 13, 2023 23:20
@kju2405 kju2405 marked this pull request as ready for review June 14, 2023 06:20
Copy link

@ICCHOI ICCHOI left a comment

Choose a reason for hiding this comment

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

재웅님! 수고하셨습니다.
전체적으로 절차지향적으로 짜여있는 부분이 많은 거 같아요.
객체지향 생활체조 원칙을 공부해보시고 이 원칙을 지키면서 수정해보시면 좋을 것 같아요.

Comment on lines 12 to 26
public Calculate calculate(){
return new CalculateImpl(new CalOrderImpl());
}
public Repository repository(){
return new ExpressionRepository();
}
public Input input(){
return new UserInput();
}
public Show show(){
return new ShowText();
}
public PreProcess preProcess() {
return new PreProcessImpl();
}
Copy link

Choose a reason for hiding this comment

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

Config를 통해 객체를 생성하면 어떤 장점이 있나요?

Comment on lines 6 to 7
void calMultiplyDivide();
int calPlusMinus();
Copy link

Choose a reason for hiding this comment

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

Suggested change
void calMultiplyDivide();
int calPlusMinus();
void calculateMultiplyDivide();
int calculatePlusMinus();

메소드 이름이 길어지더라도 명시적으로 작성해주세요!


import java.util.List;

public class ShowText implements Show{
Copy link

Choose a reason for hiding this comment

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

클래스 이름은 명사로 만들어주세요


while (true) {
choice = getChoice();
show.showMenu();
choice = input.inputChoice();
System.out.println();
if (choice == 1) {
Copy link

Choose a reason for hiding this comment

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

choice 1이 어떤 동작인지 어떻게 알 수 있을까요?


while (true) {
choice = getChoice();
show.showMenu();
choice = input.inputChoice();
System.out.println();
Copy link

Choose a reason for hiding this comment

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

이것도 출력을 담당하는 객체에서 수행하면 좋을 것 같아요!

Copy link
Author

Choose a reason for hiding this comment

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

멘토님, 리뷰 감사드립니다!
혹시 show.showMenu()부분을 말씀하시는걸까요???

Copy link

Choose a reason for hiding this comment

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

System.out.println();으로 하드코딩 되어 있는 부분입니다 :)

Copy link
Author

@kju2405 kju2405 Jun 15, 2023

Choose a reason for hiding this comment

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

아하 감사합니다🙇‍♂️

@@ -35,7 +20,7 @@ public void calPriorityFirst() {
}

@Override
public void calPrioritySecond() {
public int calPlusMinus() {
Copy link

Choose a reason for hiding this comment

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

이 메서드를 어떻게 테스트 할 수 있을까? 라는 질문을 하면서 리팩토링을 해보시면 좋을 것 같아요.

Comment on lines 7 to 8
Stack<String> expressionStack = new Stack<>();
@Override
Copy link

Choose a reason for hiding this comment

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

Suggested change
Stack<String> expressionStack = new Stack<>();
@Override
Stack<String> expressionStack = new Stack<>();
@Override

Comment on lines 9 to 17
public Stack<String> expressionToStack(String expression) {
this.expression = expression;
String[] expressionArr = expression.split(" ");
expressionStack.clear();
for (String inputVal : expressionArr) {
expressionStack.add(inputVal);
}
return expressionStack;
}
Copy link

Choose a reason for hiding this comment

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

너무 요구사항과 강하게 결합 되어 있는 것 같아서, 재사용성을 고려해보는 것도 좋을 거 같아요 :)

Scanner scanner = new Scanner(System.in);
@Override
public int inputChoice() {
return scanner.nextInt();
Copy link

Choose a reason for hiding this comment

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

inputChoice()라는 메서드명과 실제로 하고 있는 일이 조금 달라보여요.

Copy link

@devcourse-ray devcourse-ray left a comment

Choose a reason for hiding this comment

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

인창님께서 대부분 리뷰를 남겨주셔서 거의 중복되는 내용이라 따로 더 남기지는 않았어요
리뷰 내용에 맞춰서 수정 후에 다시 확인할게요~

Comment on lines 40 to 54
public void multiply(int idx) {
result = Integer.parseInt(expressionStack.get(idx - 1)) * Integer.parseInt(expressionStack.get(idx + 1));
expressionStack.add(idx - 1, String.valueOf(result));
expressionStack.remove(idx);
expressionStack.remove(idx);
expressionStack.remove(idx);
}

public void divide(int idx) {
result = Integer.parseInt(expressionStack.get(idx - 1)) / Integer.parseInt(expressionStack.get(idx + 1));
expressionStack.add(idx - 1, String.valueOf(result));
expressionStack.remove(idx);
expressionStack.remove(idx);
expressionStack.remove(idx);
}

Choose a reason for hiding this comment

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

내부에서만 사용하는 메소드는 접근제어자 설정을 잘 해줘야해요

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants