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

[Spring 지하철 노선도 - 3단계] 오찌(오지훈) 미션 제출합니다. #323

Merged
49 commits merged into from
May 16, 2022

Conversation

Ohzzi
Copy link

@Ohzzi Ohzzi commented May 12, 2022

안녕하세요 던! :)

이번에 테코톡이 있어서 테코톡 준비랑 병행하다 보니까 PR도 늦고 코드 퀄리티도 굉장히 떨어지게 되었네요 😢
새로 추가된 로직들을 구현하는 것 부터 굉장히 힘든 3단계였습니다 ㅠㅠ
인수 테스트가 아직 부족해요! PR 요청 기간이 다가와서 우선 기능 구현을 다 하고 PR 드립니다(어쩌다보니 ATDD가 전혀 아니게 되었네요)
부족한 테스트는 리팩토링 하면서 추가해보도록 하겠습니다 :)

그리고 질문이 하나 있습니다!


Q. 서비스에서 어떤 메서드는 DTO를, 어떤 메서드는 도메인을 반환해도 될까요?

편의를 위해 LineService에서 StationSerivce를 단방향으로 참조하게 되어있습니다. 그런데 이 때 StationService의 다른 메서드들은 StationResponse를 반환하는데, LineService에서만 필요한 단건조회 메서드만 Station을 그대로 반환하고 있습니다. 이런 식으로 사용하지 말고 통일적으로 StationResponse를 반환해준 뒤 다시 Station으로 돌려줘야 할까요? 던의 생각은 어떤가요?? :)

Ohzzi added 30 commits May 8, 2022 08:46
Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

안녕하세요 오찌!
3단계 미션 깔끔하게 잘 구현해주셨네요! 👍
테스트도 꼼꼼하게 잘 작성해주셨어요!
코멘트 남겼으니 확인부탁드릴게요~

Comment on lines 58 to 60
if (!stationDao.existsId(id)) {
throw new DataNotFoundException("존재하지 않는 역입니다.");
}
Copy link

Choose a reason for hiding this comment

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

도메인별로 데이터가 존재하지않을때 발생하는 예외를 만들어주는건 어떨까요?
StationNotFoundException 처럼요!
지금은 예외처리가 같기때문에 도메인별로 나누지않아도 되긴하지만, 예외가 발행했을때 어떤 예외가 발생했는지만 보고서도 더 명확하게 예외상황을 파악할 수 있습니다!
메시지로 예외가 발생한 상황을 구분하면 메시지를 잘 남겨야하는 부담도 있을 수 있겠어요.

Copy link
Author

Choose a reason for hiding this comment

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

안그래도 NotFound 쪽만 예외가 뭉뚱그려 만들어져 있어서 분리할까 생각했었는데 분리하는게 좋겠네요!

stationDao.findById(id);
} catch (EmptyResultDataAccessException e) {
throw new EmptyResultDataAccessException("존재하지 않는 역입니다.", 1);
if (!stationDao.existsId(id)) {
Copy link

Choose a reason for hiding this comment

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

boolean을 반환하는 exitst메서드 사용 👍 👍

Comment on lines 46 to 49
public Station findById(Long id) {
validateExist(id);
return stationDao.findById(id);
}
Copy link

Choose a reason for hiding this comment

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

StationService의 다른 메서드들은 컨트롤러에서 호출하고 있기때문에 Response를 반환해주는게 자연스럽고, findById 메서드는 다른 서비스에서 호출하고 있기때문에 Response가 아닌 Station을 그대로 반환해줘도 괜찮아보입니다!
서비스에 메서드의 반환값이 무조건 Response일 필요는 없습니다. 메서드를 호출하는곳에 맞게 사용하면 될 것 같아요

Comment on lines 44 to 48
private Line createLine(LineCreateRequest lineCreateRequest) {
Line line = new Line(lineCreateRequest.getName(), lineCreateRequest.getColor());
validateUnique(line);
return lineDao.save(line);
}
Copy link

Choose a reason for hiding this comment

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

이 메서드에서 단순히 Line객체를 생성하는것 뿐만 아니라 db에 insert까지 하고 있으니 메서드 이름을 create-보다는 save-로 하는건 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

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

항상 메서드 명에 고민이 많았는데 바꿔봐야겠네요! 감사합니다 :)

}
}

@Transactional(readOnly = true)
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 46 to 50
String sql = "SELECT s.id AS id, s.line_id AS line_id, s.distance AS distance, us.id AS us_id,"
+ " us.name AS us_name, ds.id AS ds_id, ds.name AS ds_name FROM SECTION AS s"
+ " INNER JOIN STATION AS us ON s.up_station_id = us.id"
+ " INNER JOIN STATION AS ds ON s.down_station_id = ds.id"
+ " WHERE s.line_id = :line_id";
Copy link

Choose a reason for hiding this comment

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

join 👍 👍
쿼리를 String으로 표현할때 FROM 앞에서 줄바꿈해주면 가독성이 더 올라갈것 같네요!

Copy link
Author

Choose a reason for hiding this comment

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

가독성을 높여보려고 고민을 되게 많이 했는데, 확실히 접속사 앞에서는 끊어줄 필요가 있겠네요...!

validateExist(id);
Line persistLine = lineDao.findById(id);
Sections sections = new Sections(sectionDao.findAllByLine(persistLine));
Line line = new Line(persistLine.getId(), persistLine.getName(), persistLine.getColor());
Copy link

Choose a reason for hiding this comment

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

새로 Line객체를 만들어서 반환하는 이유를 알 수 있을까요?
persistLine을 그대로 사용해도 될 것 같아요

Copy link
Author

Choose a reason for hiding this comment

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

이 부분은 제가 제정신이 아닌 상태로 코드를 작성했나보네요 ㅋㅋㅋㅋ
persistLine을 그대로 사용해도 되는 코드여서 수정하겠습니다!

@Transactional
public void deleteSection(Long lineId, Long stationId) {
Station station = stationService.findById(stationId);
Line line = lineDao.findById(lineId);
Copy link

Choose a reason for hiding this comment

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

lineId에 해당하는 Line이 없다면 예외가 발생할 것 같아요!

validateContainsTargetStation(station);
List<Station> sortedStations = getSortedStations();
int index = sortedStations.indexOf(station);
if (index == 0 || index == sortedStations.size() - 1) {
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.

체크하는 부분만 메서드로 빼 봐야 겠네요...!

@@ -0,0 +1,9 @@
package wooteco.subway.exception;

public class DuplicateLineException extends DuplicateDataException {
Copy link

Choose a reason for hiding this comment

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

예외를 잘 쪼개셨네요! 👍

Copy link

@ghost ghost 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 +209 to +211
return values.stream()
.noneMatch(section -> section.containStation(target.getUpStation()) && section.containStation(
target.getDownStation()));
Copy link

Choose a reason for hiding this comment

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

Suggested change
return values.stream()
.noneMatch(section -> section.containStation(target.getUpStation()) && section.containStation(
target.getDownStation()));
return values.stream()
.noneMatch(section -> section.containStation(target.getUpStation())
&& section.containStation(target.getDownStation()));

이렇게 변경하는건 어떠신가요? predicate 부분이 조금 더 명확하게 드러나도록 해보았어요.
개인적인 생각이니 오찌가 고민해주세요!ㅎㅎ

Comment on lines +83 to +88
private void validateDuplicate(Section newSection) {
if (values.stream()
.anyMatch(savedSection -> savedSection.hasSameStations(newSection))) {
throw new DuplicateSectionException("이미 존재하는 구간입니다.");
}
}
Copy link

Choose a reason for hiding this comment

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

if문안에 stream전체를 넣으니 살짝 가독성이 떨어지는 느낌이 들어요!
stream 결과를 로컬변수에 저장한뒤에 처리하는건 어떨까요?

Comment on lines +90 to +102
private boolean canBeStartSection(Section newSection) {
return values.stream()
.anyMatch(savedSection -> savedSection.getUpStation().hasSameName(newSection.getDownStation()))
&& values.stream()
.noneMatch(savedSection -> savedSection.getDownStation().hasSameName(newSection.getDownStation()));
}

private boolean canBeEndSection(Section newSection) {
return values.stream()
.anyMatch(savedSection -> savedSection.getDownStation().hasSameName(newSection.getUpStation()))
&& values.stream()
.noneMatch(savedSection -> savedSection.getUpStation().hasSameName(newSection.getUpStation()));
}
Copy link

Choose a reason for hiding this comment

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

여기도 stream 결과를 로컬변수에 저장해서 로직을 한번씩 끊어서 처리해주면 가독성이 더 좋아질 것 같아요!

Comment on lines +109 to +110
.orElseThrow(
() -> new InvalidSectionCreateRequestException("구간 시작 역과 끝 역이 모두 노선에 존재하지 않아 추가할 수 없습니다."));
Copy link

Choose a reason for hiding this comment

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

orElseThrow 부분은 한줄에 이어서 작성해도 될 것 같아요!

@ghost ghost merged commit cdf12ba into woowacourse:ohzzi May 16, 2022
This pull request was closed.
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.

1 participant