-
Notifications
You must be signed in to change notification settings - Fork 94
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
2주차 과제제출 #46
2주차 과제제출 #46
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.
반갑습니다. 한 주간 열심히 학습해 봅시다.
app/src/main/java/com/codesoom/assignment/controllers/TasksController.java
Show resolved
Hide resolved
reference: - java.lang.String - https://en.wikipedia.org/wiki/Javadoc
PUT /tasks/{id} PATCH /tasks/{id}
DELETE /tasks/{id}
app/src/main/java/com/codesoom/assignment/controllers/TasksController.java
Outdated
Show resolved
Hide resolved
app/src/main/java/com/codesoom/assignment/errors/TaskIdNotFoundException.java
Outdated
Show resolved
Hide resolved
Co-authored-by: JohnGrib <johngrib.lee@kurlycorp.com>
Co-authored-by: JohnGrib <johngrib.lee@kurlycorp.com>
컨트롤러 이름을 직접 언급하였던 것에서 이것이 어떤 역할을 하는지에 대한 설명으로 교체 Co-authored-by: JohnGrib <johngrib.lee@kurlycorp.com>
08.19
|
private String getPreviousMethodName() { | ||
int PREVIOUS_METHOD_INDEX = 2; | ||
int PREVIOUS_METHOD_INDEX = 3; | ||
return Thread.currentThread().getStackTrace()[PREVIOUS_METHOD_INDEX].getMethodName(); | ||
} |
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.
어디서 ID를 찾을 수 있는지 나타내기 위해 메서드 이름을 가져오게 하였습니다. 그런데 이 부분이 stackTrace에 의존하고 있고, 만약 메서드 위치라도 바뀐다면 이 인덱스를 수정해야 할 것 같습니다. 어떻게 하면 더 좋은 방법을 찾을 수 있을지 궁금합니다.
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.
앗 이거 이렇게까지 할 필요는 없어요. 일단은 에러 메시지가 문제의 원인이 된 "데이터"에 집중하도록 작성해 주세요. 에러 메시지에서 "코드"에 집중하는 것은 훨씬 심각한 경우에 드물게 선택하게 되는 일입니다.
* <p> | ||
* {@link com.codesoom.assignment.controllers.TasksController TasksController}에서 요청을 받고, | ||
* {@link TaskMap TaskMap}에 실제 할 작업을 요청하고 결과를 가져옵니다. | ||
* </p> |
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.
이 주석은 좋지 않아요. TaskManager
는 TasksController
에 의존하고 있지 않습니다. 그런데 이런 주석이 생기면 TaskManager
의 주석이 TasksController
에 의존하게 되어 커플링이 발생합니다.
만약 TasksController
가 TaskManager
를 사용하지 않게 되거나, TaskController
의 이름이 바뀐다고 상상해 봅시다.
그러면 TaskManager
는 코드를 수정하지도 않았고 수정할 일도 없는데 TaskManager
의 주석은 잘못된 정보를 갖고 있게 되겠죠? 즉 TasksController
의 변경이 TaskManager
까지 전파되는 것입니다.
* <p> | |
* {@link com.codesoom.assignment.controllers.TasksController TasksController}에서 요청을 받고, | |
* {@link TaskMap TaskMap}에 실제 할 작업을 요청하고 결과를 가져옵니다. | |
* </p> |
* @author pangnem | ||
* @see com.codesoom.assignment.controllers.TasksController TasksController | ||
* @see TaskMap |
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.
이 세 줄도 불필요합니다.
* @author pangnem | |
* @see com.codesoom.assignment.controllers.TasksController TasksController | |
* @see TaskMap |
@author
는 취향을 타기는 하는데요, 요즘은 git이 있어서 굳이 남기지 않아도 괜찮습니다.@see
에TaskController
가 있는 것은 좋지 않습니다.TaskManager
는 자신을 누가 사용하는지 몰라야 좋습니다.@see
에TaskMap
이 있는 것은 내부 구현 유출입니다. javadoc 주석은 외부에 공개하는 정보라고 생각하고 작성하시는 것이 좋아요. 설령 실제로는 절대로 외부에 공개하지 않는다고 해도요.
public class TaskManager { | ||
|
||
private static final TaskManager uniqueInstance = new TaskManager(); |
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.
static final
로 TaskManager
를 선언해 싱글톤으로 사용하는 것보다 Spring Bean으로 만들어 싱글톤으로 관리하는 것이 좀 더 편리할지도 모릅니다.
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.
Spring Bean에 대해 조사해보고 적용해보겠습니다! :)
public class TaskIdNotFoundException extends RuntimeException { | ||
|
||
public TaskIdNotFoundException(String methodName, Long id) { | ||
super(String.format("%s 메서드에서 id %s 를 찾을 수 없습니다.", methodName, 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.
메소드를 굳이 언급하지 않아도 괜찮아요. 메소드는 지우기도 하고 이름을 바꾸기도 하죠. 문제가 발생한 장소(메소드보다) 문제의 원인에 집중합시다.
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.
id만 메시지에 나오도록 수정하였습니다.
말씀하신대로 문제의 원인을 생각해보면, 단일조회/수정/삭제 요청이든 간에 ID를 찾지 못했다
라는 것이 문제이지 어느 곳에서 발생했는지는 중요하지 않을 것 같네요.
repositories, services
/** | ||
* 할 일 번호 생성을 담당합니다. | ||
*/ | ||
@Service | ||
public class TaskIdGenerator { | ||
|
||
private Long lastId = 0L; | ||
|
||
public Long getLastId() { | ||
increaseLastId(); | ||
return lastId; | ||
} | ||
|
||
private synchronized void increaseLastId() { | ||
lastId++; | ||
} | ||
} |
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.
할일 번호 Id 발급을 해당 클래스가 책임지도록 따로 분리하였습니다.
private final TaskManager taskManager; | ||
|
||
public TasksController(TaskManager taskManager) { | ||
this.taskManager = taskManager; | ||
} |
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.
생성자가 오직 하나만 있고 매개변수로 전달하는 값이 모두 빈으로 등록되어 있다면 생성자에는 @AutoWired
어노테이션을 붙이지 않고 빈으로 꺼내 쓸 수 있습니다.
TaskManager는 @Service
어노테이션으로 빈으로 등록이 되어있기 때문에, TasksController 생성자에서는 @AutoWired
어노테이션을 붙이지 않아도 빈으로 주입이 됩니다.
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.
좋습니다 :-)
app/src/main/java/com/codesoom/assignment/controllers/TasksController.java
Outdated
Show resolved
Hide resolved
app/src/main/java/com/codesoom/assignment/errors/TaskIdNotFoundException.java
Outdated
Show resolved
Hide resolved
app/src/main/java/com/codesoom/assignment/repositories/TaskRepository.java
Outdated
Show resolved
Hide resolved
taskMap.put(id, task); | ||
} | ||
|
||
public Collection<Task> getValues() { |
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.
이렇게 수정하면 어떨까요?
public Collection<Task> getValues() { | |
public Collection<Task> getTasks() { |
또는
public Collection<Task> getValues() { | |
public Collection<Task> getAllTasks() { |
return findWith(id); | ||
} | ||
|
||
public Task update(Long id, String title) { |
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.
이 메소드에 javadoc 주석을 작성해 보세요. 이 메소드는 꼭 작성해야 합니다.
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.
하는김에 TaskRepository 메서드 모두 추가해 보았습니다.
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.
가급적이면 public
메소드에는 모두 작성하는 것이 좋다고 생각해요. private
은 메소드가 한 눈에 이해하기 어려운 경우에만 작성하고요.
Co-authored-by: JohnGrib <johngrib.lee@kurlycorp.com>
- insert() -> save() - getValues() -> getAllTasks()
public boolean isMatchId(long taskId) { | ||
return this.id.equals(taskId); | ||
} |
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.
이 메소드에 대해 javadoc을 작성해 보세요. boolean
메소드는 javadoc을 연습하기에 아주 좋은 대상입니다.
app/src/main/java/com/codesoom/assignment/repositories/TaskRepository.java
Outdated
Show resolved
Hide resolved
|
||
/** | ||
* 번호에 해당하는 할 일을 찾습니다. | ||
* | ||
* @param id 찾을 할 일 번호 | ||
* @return Task | ||
*/ |
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.
번호라는 표현보다 더 추상화된 표현도 생각해 봅시다.
다음과 같은 방법은 어떤가요?
/** | |
* 할 일 번호 생성을 담당합니다. | |
*/ | |
/** | |
* 할 일 식별자의 생성을 담당합니다. | |
*/ |
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.
그렇습니다!
현재 Task 라는 도메인에 getter와 setter가 존재합니다. 객체지향 생활 체조 원칙 중 하나에서는 |
/** | ||
* id가 일치하면 true를 리턴하고, 아닐 경우 false를 리턴합니다. | ||
* @param id 비교 대상 | ||
* @return id가 일치하는 경우 true, 그 외의 경우 false | ||
*/ | ||
public boolean isMatchId(long id) { | ||
return this.id.equals(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.
리뷰해주신대로 javadoc을 추가하였습니다. 다만 isMatchId()
의 경우 현재는 더이상 사용하지 않는데, 이런 경우 제거하는게 좋을까요?
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.
안 쓰는 메소드라면 삭제하는 것이 좋겠죠.
Long lastId = taskIdGenerator.getLastId(); | ||
task.setId(lastId); | ||
Task task = new Task(lastId, source.getTitle()); | ||
|
||
taskRepository.save(lastId, task); |
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.
아이디 발급, 새로운 할 일 생성 등을 현재는 Service에서 하고 있는데, 각 작업들을 Service와 Repository 각각 어디에서 수행하는 게 좋은지 기준이 모호합니다. 예를 들면 taskRepository에서 아이디 발급과 새로운 할 일 생성 등의 작업을 위임할 수도 있을 것 같은데요, 각 레이어마다 어떤 작업까지 하고 넘겨주어야 할지가 궁금해졌습니다.
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.
이렇게 애매할 때가 책임을 고민해볼 때라 할 수 있어요. 그런데 service
라는 이름은 너무 포괄적이고 넓은 의미를 갖고 있지 않나요? 만약 service
라는 단어가 클래스 이름에 금지된다면 우리는 어떤 방법을 생각할 수 있을까요?
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.
앗 제가 TaskManager
를 service
라고 표현했군요. 그렇다면 클래스 이름은 그 이름이 어디까지 책임을 지는가?
라고 생각한다면, 내 영역이 아니라면 위임하고, 내가 일을 그만큼 덜한다면 다른 곳에서 그 일을 가져와서 해도 되지 않을까? 라는 생각이 들었습니다. 예를 들면 새 할일을 만드는 부분을 TaskFactory
등의 새 클래스를 만드는 것입니다.
예전 글이 생각나서 가져왔는데, TaskManager
도 좋은 이름은 아닌 것 같군요 🥲
혹은 controller에서 repository를 바로 호출하는 방식도 있을텐데, 이 글을 통해 좋은 방법인 것 같지는 않다고 판단이 되었습니다.
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.
여기에서 생각해봐야 하는 것은 service
를 여러개로 쪼개서 다양한 이름을 만들어 주는 것이라 할 수 있어요.
한편 만약 여러 개의 클래스에 공통되는 그런데 아이디와 패스워드를 필요로 하는 서비스 클래스가 또 있다고 합시다. 다만 문제는 |
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.
일요일에는 한 주간의 회고를 작성해 슬랙에 공유해주세요. 회고를 확인하면 PR을 머지해드립니다.
/** | ||
* id가 일치하면 true를 리턴하고, 아닐 경우 false를 리턴합니다. | ||
* @param id 비교 대상 | ||
* @return id가 일치하는 경우 true, 그 외의 경우 false | ||
*/ |
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.
거의 완벽한 javadoc을 작성하셨어요. 훌륭합니다.
안녕하세요? 2주차 과제를 제출합니다.
현재는 강의를 수강한 부분까지 완료하였으며 계속 추가할 예정입니다.
기존 1주차에서 사용하였던 코드를 조금 비슷하게 재구성 하였습니다.
리뷰 잘 부탁드립니다 ^~^