Feature/1 my dao - #30
Conversation
wlsh44
left a comment
There was a problem hiding this comment.
Controller를 쓰신 걸 보고 main 에 코드가 몰리지 않게 도와주는 역할로 보였는데, 어떻게 사용하면 좋을까요?
controller는 코드 진행의 흐름을 담당하는 역할이라고 생각하시면 됩니다. 여기서는 view에서 입력을 받은 값을 가지고 로직을 수행하는 객체에 값을 넘겨주고, 그 결과를 받아 출력 view에 넘겨주는 기능이라고 할 수 있습니다!
이 부분에서 매개변수 자리에 들어가는 Query 와 MyDao의 뜻이 궁금합니다..
여기서는 저는 query를 enum의 값에서 볼 수 있는 것처럼 save, find, update, delete를 Query라는 클래스로 묶어주고, 인자로 넘어오는 쿼리의 값과 myDao를 통해서 로직을 수행하도록 했습니다.
여기서 중요한 점은 MyDao를 인터페이스로 넘겨, 해당 메서드는 지금 넘어온 MyDao가 MyListDao인지, MyMapDao인지에 상관 없이 MyDao의 기능만 수행을 한다는 점입니다.
MyDao는 데이터의 접근을 담당하고 CRUD 기능을 하기 때문에 Query에 따라 CRUD의 기능을 하게 됩니다!
처음 하실 때는 다른 사람 코드를 참고하는 것도 도움이 정말 많이 되니까 힘드시면 코드 참고하셔도 좋아요~
| return me; | ||
| } | ||
|
|
||
| public Integer[] StringToInt(String[] array){ |
There was a problem hiding this comment.
해당 메서드는 getAge에서만 사용되는 것 같은데 private로 해주면 좋을 것 같아요!
그리고 메서드는 소문자로 시작해주세요~
There was a problem hiding this comment.
실수로 대문자로 해버렸네요.. private 같은 경우는 외부에서 쓰이지 않는다면 전부 private 으로 이해해도 괜찮을까요?
|
|
||
| public class Person { | ||
| private String name; | ||
| private String birth; |
There was a problem hiding this comment.
생일처럼 날짜를 표현할 때는 자바의 LocalDate라는 기능을 쓰시는 걸 추천드립니다!
There was a problem hiding this comment.
Integer[] Age = stringToInt(birth.split("\\."));
LocalDate localDate = LocalDate.of(Age[0], Age[1], Age[2]);
LocalDate birthData = LocalDate.now().minusYears(localDate.getYear());
이 부분에서 localDate 기능을 사용하긴 했는데, 보여주신 코드에서 어느 점을 고쳐야 할지 모르겠습니다
There was a problem hiding this comment.
제가 말하고 싶었던 부분은 날짜 자체는 String 보다 LocalDate 자료형으로 저장을 하는게 더 좋다는 뜻이었습니다.
그리고 지금 코드에서
LocalDate birthData = LocalDate.now().minusYears(localDate.getYear());이 값은 생일이 아니라 (한국식)나이가 될 것 같네요
| public void outputError(){ | ||
| System.out.println("[ERROR] 해당 이름은 존재하지 않습니다."); | ||
| } | ||
| } |
There was a problem hiding this comment.
view의 분리와 String.format을 이용한 처리 좋네요 👍
There was a problem hiding this comment.
예시 코드 보고 참고한 부분입니다. 확실히 코드가 더 깔끔해졌어요!
| case update: | ||
| case delete: | ||
| } | ||
| } |
There was a problem hiding this comment.
이 부분에서 bhvr에 따라 myDao가 작업을 수행하면 될 것 같다는 생각이 드네요!
| public String getAge(){ | ||
| Integer[] Age = StringToInt(birth.split("\\.")); | ||
| LocalDate localDate = LocalDate.of(Age[0], Age[1], Age[2]); | ||
| LocalDate localDate1 = LocalDate.now().minusYears(localDate.getYear()); |
There was a problem hiding this comment.
단순 localDate, localDate1보다는 좀 더 직관적인 이름을 주는게 좋을 것 같습니다 🙂
|
시험이 이제 막 끝나서 우선 되는 대로 올리겠습니다 추가사항
구현 못한 기능
|
|
입력 예외 지적하신 부분 resolve conversation 잘못눌렀습니다 .. 이 부분에서 제가 if 문으로 예외 처리 했는데 , if 문도 사용자 예외 설정 이라고 볼 수 있나요? 이런 방식으로 예외를 처리하는 게 맞는지도 잘 모르겠네요. |
wlsh44
left a comment
There was a problem hiding this comment.
코드가 점점 좋아지는 것 같네요!
다만 예외 처리를 조금만 더 신경쓰시면 좋을 것 같아요 🙂
Map은 List보다 구현하기 쉬우니까 내일까지 힘내시길 바랍니다!
|
|
||
| public class Person { | ||
| private String name; | ||
| private String birth; |
There was a problem hiding this comment.
제가 말하고 싶었던 부분은 날짜 자체는 String 보다 LocalDate 자료형으로 저장을 하는게 더 좋다는 뜻이었습니다.
그리고 지금 코드에서
LocalDate birthData = LocalDate.now().minusYears(localDate.getYear());이 값은 생일이 아니라 (한국식)나이가 될 것 같네요
| person.setMe(updateDataArray[1]); | ||
| } | ||
| } | ||
| return null; |
There was a problem hiding this comment.
null 반환은 가능하면 하지 않는 것이 좋습니다.
또 해당 메서드는 '유저 데이터 수정'이라는 목적(책임)을 갖고 있기 때문에 해당 목적에 달성을 실패했을 때는 예외가 발생하는게 맞다고 생각이 드네요 🙂
| try { | ||
| updateData = sc.nextLine().split(","); | ||
|
|
||
| } catch (IllegalArgumentException e) { |
There was a problem hiding this comment.
제가 이전 과제 참고 코드에서도 그렇고 이번 코드에서도 그렇고 예외처리 하는 방법을 넣어놨으니 참고해주시면 좋을 것 같아요 ㅎㅎ
| Person save(Person person); | ||
| Person find(String name); | ||
| Person update(String name, String updateName); | ||
| Person update(String updateName, String[] updateData); |
There was a problem hiding this comment.
String[]는 다른 사람이 봤을 때 수정될 내용이 어떤게 들어있는지 파악하기 힘들 것 같아요
| public Person update(String updateName,String[] updateDataArray) { | ||
| for (Person person : peopleList){ | ||
| if (person.getName().equals(updateName)){ | ||
| outputView.outputUpdate(person, updateDataArray[0], updateDataArray[1]); |
There was a problem hiding this comment.
데이터 수정을 하는 메서드에서 출력을 하는 기능이 있다는 것은 두 개 이상의 책임을 가지고 있다는 것을 뜻합니다
https://lktprogrammer.tistory.com/42
이런 글을 참고해보시면 좋을 것 같네요
There was a problem hiding this comment.
하나의 메서드는 하나의 기능을 해야 하는 것을 잊고 있었네요. 처음에는 와닿지 않았는데, 코드를 짜다보니까 메서드들을 연결, 실행해주는 역할의 필요성이 느껴졌습니다 . !
| peopleList.add(person); | ||
| return null; | ||
| outputView.outputSave(person); | ||
| return person; |
| } | ||
| public int inputDecision(){ | ||
| System.out.println("계속하시겠습니까? (CONTINUE: 0, EXIT: 1)"); | ||
| int dc = sc.nextInt(); |
|
시간이 없어서 먼저 올립니다!! 추가사항
구현 못한 기능LIST, MAP의 입력에 따른 LIST, MAP 실행 자바에서 hashMap 이란 걸 처음봐서 찾아보니까 파이썬의 딕셔너리랑 유사한 것 같아서 peopleData 에 put 할 때 key 값을 name으로 했습니다 힘들었던 점으로는 머릿속으로 구성을 짤 때 한 기능을 여러 역할로 분리하고 연결한다는 생각을 하니까 너무 막막하고 손이 굳더라구요. 작은 것부터 완성본을 따라가려다가 너무 멀어서 길이 엇나가고, 다음에 다시 보면 뜯어 고쳐야하는 .. 그런 어려움이 있었습니다. 차차 나아지겠죠? |
wlsh44
left a comment
There was a problem hiding this comment.
그래도 거의 다 구현하신 것 같아요!! 👍👍
이번 과제 하시면서 느낀 점이 좀 있으셨으면 하는 바램이 있네요 ㅎㅎ
힘들었던 점으로는 머릿속으로 구성을 짤 때 한 기능을 여러 역할로 분리하고 연결한다는 생각을 하니까 너무 막막하고 손이 굳더라구요. 작은 것부터 완성본을 따라가려다가 너무 멀어서 길이 엇나가고, 다음에 다시 보면 뜯어 고쳐야하는 .. 그런 어려움이 있었습니다. 차차 나아지겠죠?
코드를 작성하는건 시간이 해결을 해주는 것 같아요! 다만 설계를 하고 역할을 분리하고 이런거는 저도 아직 잘 못합니다 ㅎㅎ 설계를 하는거는 그림으로 구현하는 내용의 맥락을 표현해보는 것도 괜찮은 것 같아요. 그러면 공통된 맥락들이 보이기도 하더라구요.
물론 말씀하신 것처럼 막상 구현을 해보니 생각했던 거랑 너무 달라서 힘든 적도 많았습니다. 그래서 저는 이럴 때는 일단 완성을 하고보는 것 같아요. 완성을 하면 코드에 중복도 보이고 좀 더 코드를 깔끔하게 리팩터링하기 쉬워져요 🙂
아무튼 너무 잘 하고 계셔서 조급하지 않으셔도 될 것 같아요! 고생하셨습니다 😄
| int dataBhvr; | ||
| try { | ||
| dataBhvr = sc.nextInt(); | ||
| if (dataBhvr != 1 && dataBhvr != 2 && dataBhvr != 3 && dataBhvr != 4) { |
There was a problem hiding this comment.
DataBhvr에서 만든 from 메서드를 이용하면 이 부분을 더 깔끔하게 만들 수 있을 것 같아요
| public String inputDataType() { | ||
| System.out.println("접근할 데이터베이스 이름을 입력해주세요. (LIST, MAP)"); | ||
| String dataType = sc.nextLine(); | ||
| if (!dataType.equals("LIST") && !dataType.equals("MAP")) { |
There was a problem hiding this comment.
만약 저장하는 디비 종류가 늘어나면 그때마다 이 부분에서 로직의 변화가 생겨야 하고, 잠재적으로 버그가 될 확률이 높아집니다.
DataBhvr의 from과 같이 처리를 하면 enum에서 몇개가 추가가 되든 삭제가 되든 이 부분은 변화가 생기지 않아도 됩니다.
이런 걸 캡슐화라고 해요 🙂
| public class BhvrController { | ||
| public void bhvrController(DataBhvr bhvr){ | ||
| InputView inputView = new InputView(); | ||
| MyListDao myListDao = new MyListDao(); |
There was a problem hiding this comment.
여기서 타입을 MyListDao로 하기보단, InputView의 inputDataType에 따라 MyListDao 또는 MyMapDao를 리턴하는 메서드나 클래스를 만들고, 반환 타입을 둘의 인터페이스인 MyDao로 하면 BhvrController는 어떤 Dao인지에 상관 없이 crud를 할 수 있게 됩니다.
혹시 이해가 잘 안가신다면 다형성에 대해 공부해보시는걸 추천드려요!
| public interface MyDao { | ||
| Person save(Person person); | ||
| Person find(String name); | ||
| Person update(String updateName, String updateDataBirth, String updateDataMe); |
There was a problem hiding this comment.
각각의 인자를 따로 넘기는 방식도 좋지만, 이렇게 새 변수의 생명주기가 같을 때는 하나의 dto 클래스로 캡슐화를 하는 것도 좋습니다!
클린코드 책을 보면 인자는 가능하면 적을수록 좋다고 나와있어요 🙂
왜인지는 한 번 생각을 해보시면 좋을 것 같아요 ㅎㅎ
| public class MyListDao implements MyDao { | ||
| InputView inputView = new InputView(); | ||
| OutputView outputView = new OutputView(); | ||
| private final List<Person> peopleList; |
There was a problem hiding this comment.
이렇게 하면 MyListDao의 인스턴스가 여러 개가 되면 각각 다른 list를 가지고 있어서 문제가 될 것 같은데 어떻게 해결하면 좋을까요?
| @Override | ||
| public void delete(String name) { | ||
| try{ | ||
| peopleData.remove("name"); |
최대한 혼자 해보려고 했는데 . . .많이 막혀서 코드 조금 참고했습니다 . . .
참고하면서 궁금한 점
2023-spring-study/MyDao/src/main/java/org/example/controller/MyDaoController.java
Line 49 in eadb0c9
이 부분에서 매개변수 자리에 들어가는 Query 와 MyDao의 뜻이 궁금합니다..