그동안 수없이 들었던 “UI와 도메인을 분리시켜주세요”라는 피드백.. 분리에 분리를 반복하면서 어느 순간 공통되는 부분들이 보이기 시작했다. 이런 부분들을 모으면 다른 미션에서도 사용할 수 있을 거라는 생각이 들었다.
도메인 의존성 파악하기
MVC 패턴으로 설계된 로또 앱의 구조이다. 여기에서 로또 앱 도메인과 관련된 부분만 형광표시하면 다음과 같다.
Model, Controller, View에 로또 리스트, 로또 구매 등 도메인 관련 변수, 메서드들이 혼재되어 있다. 다르게 말하면 형광 표시되어있지 않은 부분이 도메인과 관계없는 각 모듈의 기본 역할이라고 볼 수 있다. 이러한 공통되는 부분들만 모으고 상속받는다면 도메인에 관련된 역할만 수행하는 자식 클래스들을 구현할 수 있을 것이다.
도메인 계층 분리하기
도메인 관련 변수, 메서드들을 LottoModel
, AppController
, AppView
라는 자식 클래스로 분리시킨 상태이다. 상속으로 인해 레이어가 형성되었다. 공통적으로 수행되는 부분이지만 도메인 의존성이 있는 메서드들은 부모 클래스에 선언하고 자식 클래스에서 오버라이드해 구현하도록 한다.
예) Controller의 이벤트 바인딩
class Controller {
bindEventHandlers() {}
}
class AppController extends Controller {
bindEventHandlers() {
this.view.bindOnClickPaymentSubmit(this.purchase.bind(this))
this.view.bindOnClickNumberToggle()
}
}
추가로 Model의 상태관리에 대한 부분을 구현했다. Model에 state
라는 멤버 변수와 이를 관리하는 메서드들을 정의했다. 예를 들어 초기상태를 지정하는 setInitState()
메서드는 항상 자식 클래스에서 오버라이드하도록 하기 위해 에러를 throw하도록 했다.
class Model {
setInitState() {
throw new Error("override")
}
}
class LottoModel extends Model {
setInitState() {
return {
lottoList: [],
}
}
}
결과
인사이트
언제까지 약속만 할 것인가 by 포코
- 의도만으로 약속하고 의도대로 동작하지 않는 위험한 Core 코드 덩어리들
- 컨벤션으로 커버되는 범위의 위험성을 가지고 있는 위험함
1단계 공통 피드백에서 포코가 스켈레톤 코드로 작성된 메서드들이 자바스크립트인데도 마치 자바의 implements처럼 동작한다는 피드백을 했다. 코드에서 강제되지 않은 부분을 개발자끼리의 약속으로 커버하는 것이 위험하다는 뜻으로 이해했다. 자식클래스에서 구현이 꼭 필요한 메서드들은 오버라이드하지 않으면 에러를 던지도록 하고, 인스턴스 생성 후 Object.seal
한다던지 의도대로 동작하도록 하기 위한 주의가 필요해보인다.
확장성에 대한 대응 by 헤인티
각 컨트롤러가 하나의 view 를 가질거란 보장이 없는데요, 이런 확장성에 대해서는 어떻게 대응하실건지 궁금하네요! 예를 들어 LottoGameController 는 PaymentView, LottoListView, TargetNumbersView 와 같이 세 개의 뷰를 가질 수 있죠!
MVC 패턴에서는 다수의 Model과 View가 존재할 수 있다. 현재는 Controller가 하나의 Model과 View만 가지고 있어 확장성에 대해 고려가 필요하다.
YAGNI(You aren’t gonna need it)
“실제로 필요할 때 무조건 구현하되, 그저 필요할 것이라고 예상할 때에는 절대 구현하지 말라.”
이번 미션에서의 구조화, 영역 분리 목표를 열심히 고민하는 것 좋지만, 문제가 생기지도 않았는데 너무 앞서가진 않았는 지 돌아봅시다.
- 불필요한 폴더 구조
- 불필요한 폴더 깊이
- 불필요한 최적화
- 불필요한 추상화
항상 적정선을 찾는 것이 어렵다!