[2단계 - 행운의 로또 미션] 준찌(장준혁) 미션 제출합니다#121
Conversation
src/js/views/LottoContainerView.js
Outdated
| this.#onSubmitCharge = (e) => emitListener(EVENT.SUBMIT_CHARGE, e); | ||
| this.#onChangeAlignState = (e) => emitListener(EVENT.CHANGE_ALIGN_STATE, e); | ||
| this.#onInputOverMaxLength = (e) => emitListener(EVENT.INPUT_OVER_MAX_LENGTH, e); | ||
|
|
||
| this.#chargeForm.addEventListener('submit', this.#onSubmitCharge); | ||
| this.#alignConverter.addEventListener('change', this.#onChangeAlignState); | ||
| this.#chargeForm.addEventListener('input', this.#onInputOverMaxLength); |
There was a problem hiding this comment.
| this.#onSubmitCharge = (e) => emitListener(EVENT.SUBMIT_CHARGE, e); | |
| this.#onChangeAlignState = (e) => emitListener(EVENT.CHANGE_ALIGN_STATE, e); | |
| this.#onInputOverMaxLength = (e) => emitListener(EVENT.INPUT_OVER_MAX_LENGTH, e); | |
| this.#chargeForm.addEventListener('submit', this.#onSubmitCharge); | |
| this.#alignConverter.addEventListener('change', this.#onChangeAlignState); | |
| this.#chargeForm.addEventListener('input', this.#onInputOverMaxLength); | |
| this.#chargeForm.addEventListener('submit', (e) => emitListener(EVENT.SUBMIT_CHARGE, e)); | |
| this.#alignConverter.addEventListener('change', (e) => emitListener(EVENT.CHANGE_ALIGN_STATE, e)); | |
| this.#chargeForm.addEventListener('input', (e) => emitListener(EVENT.INPUT_OVER_MAX_LENGTH, e)); |
#bindEventHandler안에서 이벤트 핸들러로만 쓰인다면 따로 클래스 필드로 선언하지 않아도 될 것 같네요.
There was a problem hiding this comment.
질문이 있는데 율리의 코드에서 removeEventListener는 어떻게 할 수 있나요??
사실 당장 필요한 것이 아니라 고려하지 않았어야하는 생각도 있습니다. 하지만 클래스 필드로 선언한데에는 참조값을 알고 있어야 삭제할 수 있으니까 라는 이유가 있었습니다.
율리가 짜주신 방식이 기존의 코드이고, 삭제 기능을 위해 클래스 필드를 사용한 것이 리팩토링 과정에서 추가된 부분인데, 어떻게 생각하시나요?
There was a problem hiding this comment.
아- removeEventListener를 고려한거다. 그럼 이해됩니다~ 그럼 removeEventListener를 바인딩하는 코드도 있는게 좋겠죠? 지금 당장 필요하지 않는다면 필요한 시점에 리팩토링하는건 어떨 까요?
There was a problem hiding this comment.
맞는 것 같아요 !!! 필요할 때 작성한다 라는 사실을 지향하며 코드를 수정해보겠습니다.
커스텀 이벤트와 어느 포인트에서 어떻게 비교해야 될 지 잘 모르겠네요. 비교대상인지 잘 모르겠어요. 커스텀 이벤트와 굳이 비교를 한다면 말씀하신것 처럼 커스텀 이벤트를 만드는데의 수고로움이 있으나 커스텀 이벤트명으로 이벤트 발생을 개발자가 의도한 시점에서 자유롭게 이벤트를 일으킬 수 있다. 정도 있겠네요.
이런 시도 자체는 좋은 것 같아요. 그러나 일부는 말씀하신것 처럼 좀 복잡해진 경향이 있기도 하고요. 일부 코드 중 단순한 뷰 변경 플로우는 action과 리듀서를 거쳐야 하는 과정이 필요한가? 그리고 현재 모든 이벤트 핸들러를 모아서 관리해야 할까? 몇가지 의구심이 들었습니다. 🙂 |
| const expectedRank = '1등'; | ||
| const rank = lotto.computeWinResult([...lotto.getLottoNumbers()], 7); | ||
|
|
||
| expect(expectedRank === rank).toBe(true); |
There was a problem hiding this comment.
당첨된 등수와 개수에 따라 예상하는 수익률과 일치하는지 알 수 있는 테스트도 있으면 좋겠네요! 😀
There was a problem hiding this comment.
추가하다가 문득... 율리가 말한 테스트를 구현하기 위해 LottoList의 private method 를 public으로 변경해야겠다고 생각이 들었는데,
이런 경우 public으로 메소드를 풀어야 하나요 ? 아니면 다른 방식이 또 있을까요 ? ㅠㅠ
There was a problem hiding this comment.
도메인 폴더의 LottoList 클래스의 퍼블릭 메소드 createLottoList, getLottoList, computeStatisticsAndProfitRatio 와 constants를 이용해보면 어떨까요? 저도 이걸 코드로만 보고 이야기 드리는거라 ㅎ 잘 될지 모르겠으나 방법은 있을 것 같네요. 🙂 너무 구현이 복잡해진다면 LottoList에서 정말 이게 private으로 필요한가... 생각해보는 기회가 될 수도 있겠네요. ㅎㅎ
There was a problem hiding this comment.
좋은 것 같습니다. 현재 private으로 은닉화 해야하는 메소드, 멤버가 무엇일지 감이 안와서 내부에서만 사용된다면 private 으로 정의해두었거든요.. 테스트를 추가하면서 이를 좀 더 고민해보겠습니다.
객체의 상태를 변경시키지 않는 메소드 ( 객체의 상태를 기반으로 값을 계산하는 )을 public으로 변경해보았습니다.
객체의 상태를 변경시키지 않는다가 private을 제거하는 이유가 될 수 있나요?
There was a problem hiding this comment.
개인적으로는 public과 private 메소드의 차이는 외부에서 접근해도 되는 메소드 이냐 아니냐의 기준인데요. 그 접근 가능 여부가 준찌가 말한 외부에서 접근했을 때 객체의 상태를 직접적으로 변경 시키는가?도 포함되는 것 같네요! 😀 또는 외부에서 써도 안전한 메소드인가? 라는 기준도 될 수 있겠네요.
src/js/domains/LottoList.js
Outdated
| } | ||
|
|
||
| createLottoList(chargeInput) { | ||
| if (this.#lottoList && !confirm('구매하신 로또는 사라집니다. 그래도 구매하시겠습니까?')) { |
There was a problem hiding this comment.
조건식이 이해하기 불편하지는 않으셨나요???? 함수로 분리해서 더 명시적인 의미를 줄까 싶은데 어떻게 생각하시나요 ?
There was a problem hiding this comment.
아- 네 듣고 보니 함수로 분리하는게 좋겠네요. 덤으로 저 컨펌 메세지도 constants로 분리하고요~ 👍
| @@ -0,0 +1,19 @@ | |||
| /** 비즈니스 로직을 담은 클래스가 여러 개여도 모든 핸들러는 이 객체로 들어오게됩니다. */ | |||
| /** 여러 화면에서 사용되는 핸들러가 있다면 하나의 객체에 담아두고 필요할 때 쓰도록 하였습니다. */ | |||
There was a problem hiding this comment.
여러 화면에서 사용되는 핸들러만 들어가는게 아니고 모든 핸들러를 담아두는 것 같네요. 🙂
glassyi
left a comment
There was a problem hiding this comment.
준찌 🙂 많이 기다렸을 텐데 자잘하게 수정 요청할 내용이 별로 없네요.
번호보기에 미리보기 기능 추가한 부분은 생각지도 못했던 아이디어라
웃으면서 화면 확인했습니다~ ㅎ 고정된 이미지긴 하지만 아이디어는 좋았습니다! 👍
여쭤보신 질문에 대한 답변과 몇가지 코멘트 추가 했으니 확인 부탁드려요~!
1번째 질문에 대한 답변을 또 답변!!우선 제가 어떤 부분을 비교해보고 싶었는지 명확하게 포인트를 집지 않아 죄송합니다 ㅠㅠ 제가 이렇게 도전한 이유는 다음과 같은 사항이 궁금해서 였습니다.
굳이 비교 대상이 아니라는 부분을 제 시각에선 이해할 수 없었습니다 ㅠㅠ 충분히 다른 방식으로 근데 2번째 질문에 대한 답변을 또 답변!!아 이부분도 제 생각을 자세히 적지 않아 율리에게 죄송하네요 ㅠㅠ 막상 설계할 때는 몰랐는데, 막상 짜고 나니 이 과정(뷰 변경 플로우를 action - reducer를 거쳐야 하는 과정)이 꼭 필요한지 저 또한 의구심이 들었습니다. 막상 기존의 설계에서 나아가 얻고 싶었던 장점도 크게 없는 것 같구요. 다른 이야기 : 이벤트 핸들러를 현재라면 모아서 관리할 필요가 없지만, 이벤트 핸들러(비즈니스 로직이 담긴)을 여러 개의 분산된 모듈에서 가지고 있다면, 객체에 담아두는 방식으로 한 곳에 모아두고 많은 화면에서 이를 사용할 수 있게 할 수 있을 것 같았습니다. ( 율리가 설명한 커스텀 이벤트의 이점을 보니 생각이 달라지긴 했습니다) |
|
율리~~~ 율리가 말한 부분을 수정했습니다..!!! 근데 궁금한게 하나 생겨서 질문 하나 더 올립니다.... 피로하실지라도 ㅠㅠ 읽어봐주시면 감사할것같습니다. 최근 1~2 주 정도 그래서 다른 방식으로 구현할 수 있어도 도전의 의미를 담아 클로저 패턴 혹은 커링 함수는 언제 활용될 수 있을까요???실무에서의 이야기어도 좋고, 율리님의 개인 경험이어도 좋습니다. 다른 사람의 의견이 조금 궁금해져서 질문남깁니다..! (개인적으로는 네트워크 요청 데이터를 캐싱해야된다면 사용을 고려할 수 있지 않을까 싶습니다. 조금 더 다양한 아이디어로 |
준찌가 사용에 대한 의견을 말했다시피 자유변수의 참조값을 캐싱하고자 할 때 많이 쓰고, 실무에서는 스크롤이벤트에 디바운스를 걸 때 클로저를 활용해서 작업해 보기도 했네요. 제 설명보다 재남님.. ㅎㅎ 의 코어 자바스크립트 책에 굉장히 설명이 잘 되어 있어서 추천드릴게요. |


데모 페이지 입니다. UX를 조금 개선해보았습니다!!
리뷰어님이 추가했으면 하는 기능이 있을까요?
설계
기존의 설계에서 더 나아간 이유
도메인과 뷰를 사용하는 입장에서 (LottoGameManager) 좀 더 선언적으로 도메인과 뷰를 동작하게 하고싶습니다. (지금 처럼 모든 일을 하나하나 찝어주며 시키는게 아니라, 어떤 일을 하세요! 라고 요청하면 그들이 알아서 일을 하도록)
1.Domain과 UI가 좀 더 능동적으로 동작했으면
2.Game Manager에서 선언적인 코드 작성이 가능해졌으면
새로운 모델링 - 변경된 Entity들의 역할
Managers
매니저들은 업무를 지시하거나, 수행하는 역할을 합니다.
LottoGameManager : DomainManager - ViewManager 에게 새로운 데이터로 할 일을 전달합니다. 기존의 기능 (DOM select, Domain, View가 할일을 모두 수행시키는 기능은 하지않습니다)
DomainManager : Lotto Game에서 요구되는 도메인을 관리합니다. LottoGameManager 로 부터 할일과 데이터(사용자가 입력하는)를 전달받으면, 그에 맞게 도메인 데이터를 변형하는 업무를 수행합니다.
ViewManager : Lotto Game의 모든 뷰들을 관리합니다. 마찬가지로 LottoGameManager 로 부터 할일과 데이터를 전달받으면 그에 맞게 화면에 그리는 업무를 세부 뷰들에게 지시합니다.
Domains
도메인 데이터를 가지고 있으며, 독립적으로 변형할 수 있는 능력을 갖추었습니다.
Views
LottoViewManager가 뷰들의 메소드들을 다루며, 화면을 변경합니다.질문
1. View에서 이벤트를 바인딩하고자,
closure패턴을 활용하였습니다.custom event로 핸들링 하는 방식은 사용하지 않았는데 둘을 비교하면 어떤 차이가 있을까요?view에서 이벤트를 바인딩 하는 이유는LottoGameManager가view가 관리하는DOM에 직접 관여하는 것이 좋지 않다고 판단하였습니다.뷰 객체가 만들어질때, 자체적으로 이벤트를 바인딩 해준다면 좋겠다고 판단하여 이러한 구조를 택하였습니다.
closure패턴을 활용하여 짠 이유는props drilling)2. 새로운 설계를 보시고 든 생각은 어떠하신가요?
제가 생각하기엔 뭔가 LottoGameManager에서 할일을 LottoDomainManager, LottoViewManager 들에게 위임시켰다? 정도로 보입니다. 막상 개발을 해놓고 보니, 이게 그냥 할 일을 수행할 클래스를 만들어 , Task를 전달하는 레이어만 깊어진게 아닌가 하는 생각이 드네요.