-
Notifications
You must be signed in to change notification settings - Fork 177
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
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.
안녕하세요 오찌!
3단계 미션 깔끔하게 잘 구현해주셨네요! 👍
테스트도 꼼꼼하게 잘 작성해주셨어요!
코멘트 남겼으니 확인부탁드릴게요~
if (!stationDao.existsId(id)) { | ||
throw new DataNotFoundException("존재하지 않는 역입니다."); | ||
} |
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.
도메인별로 데이터가 존재하지않을때 발생하는 예외를 만들어주는건 어떨까요?
StationNotFoundException 처럼요!
지금은 예외처리가 같기때문에 도메인별로 나누지않아도 되긴하지만, 예외가 발행했을때 어떤 예외가 발생했는지만 보고서도 더 명확하게 예외상황을 파악할 수 있습니다!
메시지로 예외가 발생한 상황을 구분하면 메시지를 잘 남겨야하는 부담도 있을 수 있겠어요.
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.
안그래도 NotFound 쪽만 예외가 뭉뚱그려 만들어져 있어서 분리할까 생각했었는데 분리하는게 좋겠네요!
stationDao.findById(id); | ||
} catch (EmptyResultDataAccessException e) { | ||
throw new EmptyResultDataAccessException("존재하지 않는 역입니다.", 1); | ||
if (!stationDao.existsId(id)) { |
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.
boolean을 반환하는 exitst메서드 사용 👍 👍
public Station findById(Long id) { | ||
validateExist(id); | ||
return stationDao.findById(id); | ||
} |
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.
StationService의 다른 메서드들은 컨트롤러에서 호출하고 있기때문에 Response를 반환해주는게 자연스럽고, findById 메서드는 다른 서비스에서 호출하고 있기때문에 Response가 아닌 Station을 그대로 반환해줘도 괜찮아보입니다!
서비스에 메서드의 반환값이 무조건 Response일 필요는 없습니다. 메서드를 호출하는곳에 맞게 사용하면 될 것 같아요
private Line createLine(LineCreateRequest lineCreateRequest) { | ||
Line line = new Line(lineCreateRequest.getName(), lineCreateRequest.getColor()); | ||
validateUnique(line); | ||
return lineDao.save(line); | ||
} |
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.
이 메서드에서 단순히 Line객체를 생성하는것 뿐만 아니라 db에 insert까지 하고 있으니 메서드 이름을 create-보다는 save-로 하는건 어떨까요?
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.
항상 메서드 명에 고민이 많았는데 바꿔봐야겠네요! 감사합니다 :)
} | ||
} | ||
|
||
@Transactional(readOnly = 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.
👍
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"; |
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.
join 👍 👍
쿼리를 String으로 표현할때 FROM 앞에서 줄바꿈해주면 가독성이 더 올라갈것 같네요!
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.
가독성을 높여보려고 고민을 되게 많이 했는데, 확실히 접속사 앞에서는 끊어줄 필요가 있겠네요...!
validateExist(id); | ||
Line persistLine = lineDao.findById(id); | ||
Sections sections = new Sections(sectionDao.findAllByLine(persistLine)); | ||
Line line = new Line(persistLine.getId(), persistLine.getName(), persistLine.getColor()); |
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.
새로 Line객체를 만들어서 반환하는 이유를 알 수 있을까요?
persistLine을 그대로 사용해도 될 것 같아요
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.
이 부분은 제가 제정신이 아닌 상태로 코드를 작성했나보네요 ㅋㅋㅋㅋ
persistLine을 그대로 사용해도 되는 코드여서 수정하겠습니다!
@Transactional | ||
public void deleteSection(Long lineId, Long stationId) { | ||
Station station = stationService.findById(stationId); | ||
Line line = lineDao.findById(lineId); |
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.
lineId에 해당하는 Line이 없다면 예외가 발생할 것 같아요!
validateContainsTargetStation(station); | ||
List<Station> sortedStations = getSortedStations(); | ||
int index = sortedStations.indexOf(station); | ||
if (index == 0 || index == sortedStations.size() - 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.
이 로직을 메서드로 분리해서 의미를 더 드러내볼 수 있을까요?
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.
체크하는 부분만 메서드로 빼 봐야 겠네요...!
@@ -0,0 +1,9 @@ | |||
package wooteco.subway.exception; | |||
|
|||
public class DuplicateLineException extends DuplicateDataException { |
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.
예외를 잘 쪼개셨네요! 👍
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.
안녕하세요 오찌!
구현 잘해주셔서 코멘트 남길 부분이 딱히 없었네요 👍
가독성 관련해서 간단한 코멘트 남겼으니 확인부탁드릴게요!~
이번 미션 구현하시느라 수고많으셨습니다! 다음 미션도 화이팅입니다!
return values.stream() | ||
.noneMatch(section -> section.containStation(target.getUpStation()) && section.containStation( | ||
target.getDownStation())); |
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.
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 부분이 조금 더 명확하게 드러나도록 해보았어요.
개인적인 생각이니 오찌가 고민해주세요!ㅎㅎ
private void validateDuplicate(Section newSection) { | ||
if (values.stream() | ||
.anyMatch(savedSection -> savedSection.hasSameStations(newSection))) { | ||
throw new DuplicateSectionException("이미 존재하는 구간입니다."); | ||
} | ||
} |
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.
if문안에 stream전체를 넣으니 살짝 가독성이 떨어지는 느낌이 들어요!
stream 결과를 로컬변수에 저장한뒤에 처리하는건 어떨까요?
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())); | ||
} |
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.
여기도 stream 결과를 로컬변수에 저장해서 로직을 한번씩 끊어서 처리해주면 가독성이 더 좋아질 것 같아요!
.orElseThrow( | ||
() -> new InvalidSectionCreateRequestException("구간 시작 역과 끝 역이 모두 노선에 존재하지 않아 추가할 수 없습니다.")); |
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.
orElseThrow 부분은 한줄에 이어서 작성해도 될 것 같아요!
안녕하세요 던! :)
이번에 테코톡이 있어서 테코톡 준비랑 병행하다 보니까 PR도 늦고 코드 퀄리티도 굉장히 떨어지게 되었네요 😢
새로 추가된 로직들을 구현하는 것 부터 굉장히 힘든 3단계였습니다 ㅠㅠ
인수 테스트가 아직 부족해요! PR 요청 기간이 다가와서 우선 기능 구현을 다 하고 PR 드립니다(어쩌다보니 ATDD가 전혀 아니게 되었네요)
부족한 테스트는 리팩토링 하면서 추가해보도록 하겠습니다 :)
그리고 질문이 하나 있습니다!
Q. 서비스에서 어떤 메서드는 DTO를, 어떤 메서드는 도메인을 반환해도 될까요?
편의를 위해
LineService
에서StationSerivce
를 단방향으로 참조하게 되어있습니다. 그런데 이 때StationService
의 다른 메서드들은StationResponse
를 반환하는데,LineService
에서만 필요한 단건조회 메서드만Station
을 그대로 반환하고 있습니다. 이런 식으로 사용하지 말고 통일적으로StationResponse
를 반환해준 뒤 다시Station
으로 돌려줘야 할까요? 던의 생각은 어떤가요?? :)