Skip to content

Kangdaeho Chapter 02. 문자열 계산기 구현 - #2

Open
kangdaeho99 wants to merge 34 commits into
java-web-programming-nextstep-study:mainfrom
kangdaeho99:kangdaeho
Open

kangdaeho99 wants to merge 34 commits into
java-web-programming-nextstep-study:mainfrom
kangdaeho99:kangdaeho

Conversation

@kangdaeho99

Copy link
Copy Markdown

No description provided.

javajigi and others added 30 commits September 16, 2015 09:28
개발 환경 설정 및 요구사항 문서 추가.
…/feature/clean-ignore

github에 올라간 iml 제거 및 ignore에서 프로젝트명 관계없이 iml 제외되도록 변경
@dh0304

dh0304 commented Jul 7, 2024

Copy link
Copy Markdown
Contributor

[제안] 시작하기 전에 내가 구현해야할 기능목록에 대해서 먼저 생각해보고 적는 습관을 들여보는게 어떨까 싶어요
저도 예전에는 안적었는데 요즘에는 어떤 기능을 구현할 때 적는 습관을 들이니까 정리가 되고 내가 코드를 작성하다가 내가 지금 뭐하는거지? 할때가 있는데 내가 해야할 것을 다시 한번 상기시켜주는 역할을 도와주더라구요.

@dh0304 dh0304 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1주차 고생하셨습니다!

Comment thread kangdaeho/build.gradle Outdated
}

dependencies {
implementation 'junit:junit:4.13.1'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[제안] 책에서는 Junit4를 썼는데 Junit5 써보는게 어때요?
Junit4는 예전 버전이예요
스프링부트로 프로젝트 생성해도 기본적으로 Junit5 인걸로 알고 있어요
테스트 배워보는 김에 AssertJ도 같이 공부해보면 더 좋을 것 같아요.
Junit5 공식문서에 서드파트 라이브러리인 AssertJ 사용을 권장합니다.

the JUnit team recommends the use of third-party assertion libraries such as AssertJ, Hamcrest, Truth, etc.

@kangdaeho99 kangdaeho99 Jul 13, 2024 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

넵 JUnit 5를 사용해보면서, JUnit과는 차이점이 있네요

먼저 의존성은 아래처럼 가져왔어요~!
dependencies {
implementation 'org.junit.jupiter:junit-jupiter:5.8.1'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}

또 JUnit5의 테스트 메서드를 사용하려면, Jupiter API를 Import해서 사용합니다

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
위에 Jupiter API를 Import해서 사용해요.

또, 사용하면서 느꼈던 차이점은 JUnit4에서 @before가 JUnit5에서는 @beforeeach 로 바뀌었네요

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Junit5의 테스트 메서드 대신 assertj 로 테스트 툴을 바꿔봤네요

먼저 의존성은 아래처럼 가져왔어요~!
testImplementation 'org.assertj:assertj-core:3.21.0'

assertJ의 테스트메서드가 junit5보다 직관적이네요

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[질문] Calculator의 삭제는 깜빡하신거죠?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

넵 그렇습니다! ㅎㅎ;

int add(String text){
//빈 문자열 또는 null값을 입력할 경우 0을 반환한다.
if(text == null || text.isEmpty()){
return 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[질문] null이거나 빈 문자열일 경우 0을 반환한 이유가 있을까요?

2.3.1 요구사항에는 빈 문자열 또는 null 에 대해서 어떻게 처리하라고 나와있지 않았어요.
2.3.2 힌트에는 빈 문자열과 null에 대해서 0을 반환해야 한다 라는 조건이 나와있죠.

(실무를 접해보지 않았지만,,,박재성님 말로는) 실무에서는 요구조건 사항을 디테일 하게 주지 않아요.
만약에 빈 문자열, null일 경우 0을 반환하면 안되는 상황이 있을까요?
그렇다면, 0을 반환하지 않고 어떤 방식을 사용해야할까요?

위 내용은 "좋은 코드 나쁜 코드" 에서도 다루는 내용이예요 아마 클린코드에서도 다룰 것 같네요

@kangdaeho99 kangdaeho99 Jul 13, 2024 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

[질문] null이거나 빈 문자열일 경우 0을 반환한 이유가 있을까요?
[답변 1.] 힌트까지 보고 개발을 진행했는데, 힌트에 나온 내용을 그대로 사용했어요

[질문] 만약에 빈 문자열, null일 경우 0을 반환하면 안되는 상황이 있을까요?
[답변 2.]. 만약, 이 프로그램이 실제로 사용자의 입력에 따라 어떤 점수를 계산하는데, 사용자가 아무 입력도 하지 않았는데 0을 반환되는 상황을 생각해봤어요.
해당 상황에서 "0을 반환하면 안되는 상황이 있을까?"에 대해서 질문을 받았을떄, 만약 계산기에 add 외에도 divide 가 추가되었을떄 divide by zero ArithmeticException 이 발생할 수 있을 것 같아요

[질문] 그렇다면, 0을 반환하지 않고 어떤 방식을 사용해야할까요?
[답변 3.]throw new IllegalArgumentException("Input cannot be null or empty"); 와 같이 Exception을 발생시키는 방안이 있을 것 같아요!

// 구분자로 사용한다. 예를 들어 "//;\n1;2;3"과 같이 입력할 경우 커스텀 구분자는 세미콜론(;) 이며, 결과값은 6이 반환되어야 한다.
//문자열 계산기에 음수를 전달하는 경우 RuntimeException으로 예외처리해야 한다.
if(text.startsWith("//")){
Matcher m = Pattern.compile("//(.)\n(.*)").matcher(text);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[질문] "//" 과 "//(.)\n(.*)"는 하드 코딩이네요.
하드 코딩을 하지 말아야하는 이유에 대해서 공부해볼만 할 것 같아요.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

[답변] 가장 큰 이유는 요구사항 변경(새로운 기능 추가나 수정)시에 유지보수의 어려움이네요.
예시로 만약, 요구사항이 변경되어서 "//(.)\n(.)" 가 "&&(.)&n(.)" 로 변경된다면 이 //(.)\n(.*)" 를 사용하던 모든 클래스들을 직접 변경시켜줘야한다는 점이 문제인 것 같아요.

// 구분자로 사용한다. 예를 들어 "//;\n1;2;3"과 같이 입력할 경우 커스텀 구분자는 세미콜론(;) 이며, 결과값은 6이 반환되어야 한다.
//문자열 계산기에 음수를 전달하는 경우 RuntimeException으로 예외처리해야 한다.
if(text.startsWith("//")){
Matcher m = Pattern.compile("//(.)\n(.*)").matcher(text);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[제안] Macher 타입의 변수를 m 이라고 적어놨네요. 변수명을 누가봐도 알기 쉽게 지어보는 것이 어떨까요?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

[답변] 넵, customDelimiterMatcher 로 수정하면 커스텀구분자 Matcher 변수명으로 하면 이해하기 쉬울 것 같아요! 더 좋은 네이밍 있으면 공유 부탁드립니다!!

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringCalculator {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[질문] 2.3.3 추가 요구사항에 "메서드가 한 가지 책임만 가지도록 구현한다"
라고 나와있어요
한가지 책임이 무엇을 의미하고, 어떻게 한가지 책임만 가지도록 할 수 있을까요?
한번에 너무 많은 것을 리팩토링 하려고 하지말고, 위의 내용을 생각해보면서 지금 코드에서 어떻게 하면 책임을 줄일 수 있을까 생각해보는 것이 도움이 될 것 같아요.

"객체지향 생활 체조" 에 대해서 검색해보는 것도 추천드립니다.

@kangdaeho99 kangdaeho99 Jul 13, 2024 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

[답변] 한가지 책임이란, 하나의 메소드가 하나의 목적을 위해 존재하는거라고 생각했어요.
우선 각 메소드 당 한가지 책임만 가지도록 리팩토링해봤습니다!
validateInput(String text)의 책임: 입력 문자열의 유효성을 검사합니다.
sumWithCustomDelimiter(String text)의 책임: 커스텀 구분자를 사용하는 문자열을 처리합니다.
sumWithDefaultDelimiter(String text)의 책임: 기본 구분자를 사용하는 문자열을 처리합니다.

객체지향 생활체조 9가지 원칙에 대해서 찾아보았는데, 상당히 인상적이네요. 우선은 각 메소드 당 한가지 책임만 가지는걸 중점으로 해서 리팩토링해봤습니다!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants