서버를 기다리며, 서버 없이 개발하기 - Domain 설계 #101
shippingpark
started this conversation in
Idea
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
서론
안녕하세요! 3기 보노 입니다.
저희 팀은 총 일곱 번 기획을 엎는 결단을 거쳐 쇼케이스를 약 2주 앞두고
전쟁을 치르듯 기획, 디자인, 개발을 병행 중 입니다.
돌이켜 보니 급한 일정에 러너분들과 개발 이야기를 많이 나누지 못한 것 같아 아쉬움이 남습니다
그러니 페어 프로그래밍을 하듯
외부 데이터 없이도 도메인을 작성하고, 화면 작업을 수행하기 위해 하루동안 고민한 내용을 공유하고자 합니다.
#95 에 작성하였던 [구체적이지 않은 요구사항으로 개발하기- 확장성을 고려한 모델 설계]에 이어지는 글 입니다.
본문에 코드 분류, 계층 분류를 상징하는 단어가 자주 언급되지만 글이 너무 길어질 것 같아 자세히 설명하지 못했습니다.
저희 팀만의 해석이 담긴 단어들도 있어 가볍게 보시길 권장 드리고 싶습니다.
더불어 조언이 있다면 언제든 부탁드립니다!
+) 서비스를 잘 모르는 채 설명을 따라가기는 어려운 것 같습니다.
아래에 본문을 간단히 요약해 둡니다!
요약
모델 설계 이후 남은 도메인 설계(UseCase)를 진행
protocol로
UseCase
가 1)필요로 하는 정보(Repository)와 2)제공해야 할 정보의 형태(UseCase)를 정의아직 서버가 없어 작성할 수 있는 명세가 없음, 테스트 편의 확보를 위해
Repository
인터페이스를 채택한 구현체MockRepository
를 만들어 서버 개발 진도에 발이 묶이지 않도록 처리핵심 기능이 되는
JudgmentUseCase
(protocol)를 채택한JudgmentUseCaseMock
구현체를 만들어Presentaion
계층이Domain
의 구현체를 모르도록 완전히 분리추후
Presentaion
계층을도메인
으로부터 Target 형태로 분리할 때 편의를 얻고자 목표+) 물리적 분리를 염두하는 이유는 UnitTest와 UITest 에서 빌드 시간 단축
감사합니다.
많은 조언 부탁드립니다.
좋은 하루 되세요!
모델 수정 진행
Bird
는 '해외여행 시 지출 판단을 도와주는 기준'을 가진 서로 다른 모델을 의미합니다.지난 글에서는 앱의 핵심 모델인
Bird
를 설계하는 과정을 설명했습니다.그렇게 작업을 진행하던 중 기획을 다듬고 있는
팀원
의 질문을 받았습니다그럼요! 라고 대답했지만 뭔가 찜찜해서 코드를 다시 보았습니다
여러 생각이 떠올랐습니다. 생각나는 대로 정리해 보겠습니다
생각이 복잡해져서
Bird
가 어떤 책임을 지고 있는지 천천히 다시 생각해 보았습니다Bird
는 고유한 지출 판단 기준을 가지고 있으며 특정 방식으로 행동하도록 기대 받습니다.Bird
는 구매 여부를 판단한 후 그 이유를 설명하는 역할 입니다이를 다시 정의하고 보니 기존의 작성한
Bird
를지출판단
책임 객체라 느낀 것과 달리지출 판단
에 대한 결과를 상세 풀이하는 책임을 가졌음을 알게 되었습니다.화면에서 드러나는 지출판단은 'O' 뿐입니다.
그 외의 모든 것은 O, X가 결정된 이후 보다 자세하게 결정된 기능입니다.
따라서
지출판단
은Bird
이전에 존재해야 한다고 느끼고지출판단
책임을 수행할 모델을 작성하였습니다.지출판단
책임을 가진 Judgment 모델지출판단
기준이 여러 개이기 때문에 그 자격을Judgment
를 정의하고 이를 채택한 구현체를 생성하였습니다.예를 들어, 선택된 국가와 한국 내 평균을 기준으로 판단하는
좌측, 중간 새는
CountryAverageJudgment
를 토대로 판정된 값에 살을 붙이는 친구일 것 입니다.우측 새는 기준 값으로 직전 소비를 평가하는 기준으로 생성된
PreviousJudgment
에 살을 붙이는 친구로 보입니다.아직 정해지지 않은 기획단의 요구는 비워 두었습니다.
이제
Bird
를 만들 차례입니다.Bird는 판단 결과에 근거를 추가하여 정보를 노출하는 역할로 보이기에,
어떤 정보가 보여져야 할 지를 고려하여 아래와 같이 작성하였습니다.
CountryAverageJudgment
기준을 바탕으로 Bird의 행동을 구체화한ForignBird
를 구현하였습니다이제 Bird 모델이
Judgment
와 분리되며 각각의 역할이 명확해졌습니다또 지난 코드와 눈에 띄게 달라진 점은
명칭
이기도 합니다.Judgment
라는 앞선 모델의 역할과 책임을 분리하기 위해서Bird
가 보여주는 다양한 정보나 행동�을BirdReaction
, 즉Reaction
이라 명명하였습니다.+)
BirdModel
을 설명하니 뭔가 Model이라기 보다는ViewModel
처럼 느껴 지기도 하는 것 같습니다.챗지피티에게 ViewModel의 정의를 물으니 더욱 비슷해 보입니다.
고민 끝에 폴더 분류를 아래와 같이 정리하였습니다.
(이를 지켜보던 팀원이 진짜
View-Model
이네, 라는 말을 했습니다)도메인 설계 과정
저희 팀의 도메인은 UseCase, ViewModel(New!), Entity로 구성되었습니다.
UseCase
는Presentation
계층과Data
계층의 중간에서 비즈니스 로직을 수행합니다.예를 들면,
화면
의 요청을 토대로 (화면에 의한 UseCase 메서드 실행)데이터 계층
에게 요청하여 필요한 정보를 받고 (Repository 메서드 실행 후 반환 값 획득)합니다.
1의 작업을 명시하기 위해 아래와 같이
JudgmentUseCase
를 정의하였습니다.해당 인터페이스는 Presentaion 계층에서 필요로 하는
UseCase
의 역할이 됩니다. (호출자가 Presentaion/View)위의 메서드는 사용자에 의해 발생되는 이벤트를 알고 있는(
Presentaion
)의 필요에 의해 실행될 것 입니다.이제
UseCase
는 위의 몇몇 메서드 정의 시적절한 return 값을 만들기 위해서 데이터 계층을 필요로 하게 될 것 입니다.
UseCase
가 필요로하는 정보를 관리할 객체의 책임을 아래와 같이 두 개로 분류하였습니다.이제 간 계층 간의 전환이 어떤 식으로 이루어질 지 대략적인 감을 잡게 되었습니다 !
계층 간의 소통 방식이 정해졌으니 이제 위의 메서드를 정의할 구현체가 필요합니다.
데이터 전달 구현체 없이 개발하기
서버 개발이 완료되지 않았으므로 Mock 데이터를 사용해 개발을 진행하였습니다.
아래 코드처럼 원하는 값의 형태를 조작하여
RepositoryMock
구현체를 작성하였습니다�
Presentaion
계층, 즉View
가 사용할UseCase
또한 Mock으로 작성합니다.아주 엄밀히 고려하며 진행하지 않았기 때문에 느낌만 확인하시면 좋을 것 같습니다!
여담
저는 본래 이전 프로젝트에서 Domain -> Data (고->저)가 아닌
Presentaion -> Domain 구간(저->고)에는 인터페이스를 두지 않는 편이었습니다.
하지만 해당 프로젝트는 UnitTest와 UITest를 진행하고 있고 빠른 빌드를 위해
추후 View와 Domain 코드를 물리적으로 분리할 목적으로 UseCase를 추상화하였습니다.
당장은 ViewController에서 Preview를 사용할 때 실제 구현체를 사용하지 않기 위함 입니다.
Mock 끼리는 의존성을 분리할 필요를 느끼기 어려워
UseCaseMock 내부에서 RepositoryMock 값을 직접 생성되도록 작성하였습니다.
결론
이렇게
UseCase
설계를 마무리 지었습니다.내일은 UnitTest를 거쳐 코드를 다듬고 데이터를 기다리며 화면 작업을 할 예정입니다.
어쩌다 밤을 새버려서 글이 두서가 없습니다 ㅜㅜ 이상하게 서술된 점이 있다면 댓글을 부탁 드립니다.
또 두서 없이 써 내린 글이지만 많은 조언 부탁드립니다!
감사합니다.
Beta Was this translation helpful? Give feedback.
All reactions