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

[럿고] 자동차 경주 미션 제출합니다. #104

Merged
merged 44 commits into from
Feb 18, 2020

Conversation

ksy90101
Copy link

안녕하세요. 이번 리뷰 잘 부탁드리겠습니다!!
이번에 하면서 궁금한게 많아서 리뷰 해주시면 DM으로 많이 물어보겠습니다. 양해 부탁드려요 ㅠㅠ

YebinK and others added 29 commits February 11, 2020 15:49
경우 해당 숫자 반환 테스트
Copy link

@phs1116 phs1116 left a comment

Choose a reason for hiding this comment

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

안녕하세요, 럿고! 리뷰어 화투입니다.
요구사항 반영 및 테스트 작성 매우 잘해주셨어요.
피드백 추가했는데 참고 부탁드릴게요. :)
궁금하신 점 있으시면 코멘트나 혹은 DM 주세요! :)

if (text == null || text.isEmpty()) {
return 0;
}
if (text.contains("-")) {
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.

아직 이런 부분이 부족하네요..! 신경쓰겠습니다 감사합니다!

return 0;
}
if (text.contains("-")) {
throw new RuntimeException("message");
Copy link

Choose a reason for hiding this comment

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

이펙티브 자바 아이템 75. 예외의 상세 메시지에 실패 관련 정보를 담으라 참고하세요. :)

Copy link
Author

Choose a reason for hiding this comment

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

놓친 부분이네요.... 고쳐놓겠습니다!


private static int splitAndSum(String text) {

Matcher m = Pattern.compile("//(.)\n(.*)").matcher(text);
Copy link

Choose a reason for hiding this comment

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

이펙티브 자바 아이템6 불필요한 객체 생성을 피하라 참고,
Pattern 객체는 생성 비용이 비싸고 재사용이 가능한 객체입니다. 필드로 빼서 사용하시는게 좋습니다. :)

Copy link
Author

Choose a reason for hiding this comment

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

말씀하신 부분을 한번 읽어 보고, 생성 비용이 비싸고 재사용이 가능한 객체는 무엇이 있는지에 대해서 공부를 해봐야 겠습니다. 감사합니다!

String[] tokens = m.group(2).split(customDelimiter);
return sum(tokens);
}
String[] numbers = text.split(",|:");
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.

넵. 고치겠습니다!

Comment on lines 21 to 29
public String getCurrentPosition() {
StringBuilder currentPosition = new StringBuilder(name.getName());
currentPosition.append(" : ");

for (int i = 0; i < position; i++) {
currentPosition.append(POSITION_MARK);
}
return currentPosition.toString();
}
Copy link

Choose a reason for hiding this comment

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

getter를 사용하시려면 객체의 상태 그대로를 전달하는게 좋을 것 같네요. :)
뷰에 종속적인 내용이다보니 출력 용 데이터는 도메인 객체가 아닌 View단에서 처리하는게 좋을 것 같습니다.

Copy link
Author

Choose a reason for hiding this comment

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

MVC 패턴에 대해서 공부가 필요하겠네요 ㅠㅠ 감사합니다!

Comment on lines 22 to 26
public void moveCars() {
for (Car car : cars) {
car.movePosition(createRandomValue());
}
}
Copy link

Choose a reason for hiding this comment

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

해당 공개된 메서드는 테스트하기 매우 어려워 보이는데요.
이는 Random이라는 컨트롤 하기 어려운 부분 때문으로 보입니다.
테스트를 위해서 테스트 하기 어려운 부분은 인터페이스로 추상화하는 방법을 많이 사용하곤 합니다.
랜덤이 아닌 특정 값을 돌려주는 인터페이스를 만들고, 랜덤을 사용해서 돌려주는 구현체,
원하는 값을 순서대로 돌려주는 구현체가 있을 수 있겠죠. :)
후자를 Cars에 주입해주면 테스트가 용이하겠죠?

혹은 구현 자체를 다르게 보실수 있을 것 같아요.
랜덤값을 돌려주는 것이 아닌, 이동을 할지 말지 결정을 해주는 객체지만 랜덤 기반으로 판단으로 결졍할지,
혹은 원하는 순서대로 움직이라고 지시를 내리는 객체가 될수도 있구요.

고민해보시고 테스트 하기 쉬운 구조로 변경해보세요. :)

Copy link
Author

Choose a reason for hiding this comment

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

제가 리팩토링한 부분이 말씀하신것인지가 의문입니다..ㅠㅠ 확인후에 아니라고 생각하시면 말씀해주시면 다시 리팩토링해보도록 하겠습니다.

Comment on lines 28 to 35
public String getCurrentResult() {
StringBuilder currentResult = new StringBuilder();
for (Car car : cars) {
currentResult.append(car.getCurrentPosition());
currentResult.append("\n");
}
return currentResult.toString();
}
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.

위에 피드백을 확인하고 같이 이동하였습니다!

Comment on lines 37 to 38
public List<Car> getCars() {
return cars;
Copy link

Choose a reason for hiding this comment

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

getCars를 써야할 이유가 있을까요?
만약에 써야한다면 Collections.unmodifiableList 등으로 감싸서 돌려주어서, 불변을 보장해주는게 좋을 것 같네요. :)

Copy link
Author

Choose a reason for hiding this comment

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

넵 그생각을 놓쳤네요 ㅎㅎ 감사합니다!

}

public List<Name> getNames() {
return names;
Copy link

Choose a reason for hiding this comment

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

Colelctions.unmodifiableList 참고하세요. :)

Copy link
Author

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 18
for (Car car : cars) {
if (car.isMaxPosition(maxDistanceCar)) {
winners.add(car);
}
Copy link

Choose a reason for hiding this comment

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

stream을 공부해서 사용해보셔도 좋을 것 같네요. :)

Copy link
Author

Choose a reason for hiding this comment

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

stream으로 변경하였습니다!

@ksy90101
Copy link
Author

이번에는 세세한 사항들을 못지킨것 같습니다. 상수처리와 View에 대한 처리에 대해서도 놓친 부분들이 많은 것 같은데, 그런 부분들을 잡아주셔서 감사합니다. 또한 슬랙으로 질문했던 내용들에 대한 답변도 너무 감사합니다. 막혀있던 부분들이 많이 해소된것 같았습니다~
테스트 하기 어려운 부분은 인터페이스로 추상화 이부분에 대해서는 자료를 찾으면서 조금 더 공부해보도록 하겠습니다~ 1차 피드백 고생하셨습니다~

Copy link

@phs1116 phs1116 left a comment

Choose a reason for hiding this comment

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

안녕하세요! 리뷰어 화투입니다.
피드백 반영 잘 해주셨는데 놓치신 듯한 부분,
아쉬운 부분이 조금 있어서 피드백 추가했어요!
참고 부탁드릴게요. :)

}

@Override
public String toString() {
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();
}

// public static void printCurrentResult(String result) {
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.

넵!

import java.util.List;
import java.util.stream.Collectors;

public class Winners {
Copy link

Choose a reason for hiding this comment

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

Winners가 클래스 변수로 자동차 리스트를 관리하고 있네요.
동기화 문제 때문에 변경 가능한 값을 static 변수로 사용되는건 권장되지 않습니다. :)
특히 웹 환경에서는 더더욱 잘 사용되지 않구요.

Winners라는 객체를 인스턴스로 관리해보면 어떨까요?
또한 Winners객체는 Cars에서 생성해도 될 것 같아요.

Copy link
Author

Choose a reason for hiding this comment

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

말씀하신대로 변경하였습니다.


private String name;

public Name(String name) throws IllegalArgumentException {
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 17 to 21
public void moveCars(int randomValue) {
for (Car car : cars) {
car.movePosition(randomValue);
}
}
Copy link

Choose a reason for hiding this comment

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

현재 로직 상 움직일 땐 다같이 움직이는 것 같은데 아닌가요?
요구사항에 맞지 않은 것 같아요. :)
혹시 구현에 어려운 사항 있으시면 DM 주세요!

Copy link
Author

Choose a reason for hiding this comment

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

interface를 해서 구현했는데, 맞는지 모르겠습니다!
제가 너무 안일하게 생각한 것같습니다. 1차 피드백때 말씀해주신 방법대로 한번 코딩해봤습니다!

Copy link
Author

Choose a reason for hiding this comment

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

페어의 피드백을 보고 완전히 터득했습니다! 말씀하신 방법이 맞을꺼같아요!
https://www.slideshare.net/ssuser59a869/ksug-2019?fbclid=IwAR2UcYpT58l7AUEPj8vAXIUpllk4meCTlLk4aGDZJSnaECgMwpRR1sVkYAc
(51페이지부터 참조)

private CarMoveValueGenerator carMoveValueGenerator = () -> (int)(Math.random() * RANDOM_LIMIT_VALUE);

이런식으로 람다를 이용해서 인터페이스에 구현했습니다! 어려웠지만 깨닫고 나니깐 너무 뿌듯하네요! 좋은 패턴 알려주셔서 너무 감사합니다!

Copy link

@phs1116 phs1116 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.stream.Collectors;

public class Cars {
public static List<Car> winners = new ArrayList<>();
Copy link

Choose a reason for hiding this comment

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

public static 으로 가져가면 동기화 문제가 있을 수 있을것 같네요. :)
Cars가 가진 Car가 Cars 인스턴스마다 다를텐데 클래스 변수로 들고 있어야할까요?

또한 public이 아닌 캡슐화를 고민해보시면 좋을 것 같습니다. :0

Copy link
Author

Choose a reason for hiding this comment

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

클래스 변수가 아니라 지역변수로 했는데, 맞는지 잘 모르겠네요! 일주일 동안 고생하셨습니다~ 감사합니다!

@phs1116 phs1116 merged commit 5f754f5 into woowacourse:ksy90101 Feb 18, 2020
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.

3 participants