Skip to content
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

오른쪽 스와이프 시 음악을 플레이리스트에 저장한다. #39

Open
Park-kxng opened this issue Nov 13, 2024 · 10 comments
Open
Assignees

Comments

@Park-kxng
Copy link
Collaborator

No description provided.

@Park-kxng Park-kxng self-assigned this Nov 13, 2024
@windowcow
Copy link
Collaborator

플레이리스트에 저장하는건 덱에서 하면 어떨까요??
image

이런 느낌으로 덱이 현재 재생 중인 노래 카드의 원본을 들고 있습니다.
view model은 source of truth인 random music card deck 에게 시키는 식으로 하면 어떨까요??

@Park-kxng
Copy link
Collaborator Author

코드 리뷰 중 말씀해주신 부분을 본 기억이 납니다.
TO DO로 남겨주신 부분에 추가하자는 말씀이신거죠??

   func likeCurrentMusic() {
        removeCurrentMusic()
        // TODO: 현재 노래에 대한 좋아요 로직
    }

    func dislikeCurrentMusic() {
        removeCurrentMusic()
        // TODO: 현재 노래에 대한 싫어요 로직

@windowcow
Copy link
Collaborator

windowcow commented Nov 13, 2024

맞습니다.
RandomMusicCardDeck에서 UserPlaylistRepository프로토콜의 구현체를 의존성 주입 받아서 가지고 있다가 좋아요한 로직을 실행합니다.

좋아요 로직의 경우에는 현재 플레이리스트에 RandomMusic 추가하기가 되겠죠??

RandomMusicCardDeck에서는 상세 내용을 구현을 안하고 userPlaylistRepository.likeCurrentMusic(isrc: String)로 시킵니다.

여기서 가장 중요한 부분은 우리는 프로토콜로 정의된 UserPlaylistRepository의 구현은 모르지만 인터페이스는 예상할 수 있다는 점 같습니다.
userPlaylistRepository.likeCurrentMusic(isrc: String)라는 메서드 시그니처만으로 RandomMusicCardDeck에서 호출합니다.
이렇게 하면 뒷부분 구현(UserPlaylistRepository)이 되어있지 않아도, MockUserPlaylistRepository로 인터페이스만 구현한 이후 테스트할 수 있습니다.

UserPlaylistRepository를 구현하는 쪽에서는 DefaultUserPlaylistRepository를 동시에 개발하고 테스트해서 이후에 Mock을 대체하는 진행 방법을 생각했습니다.

@windowcow
Copy link
Collaborator

windowcow commented Nov 13, 2024

창우가 MusicListView를 개발해야한다.
그런데 MusicListRepository가 아직 없다?

  1. 모두에게 MusicListRepository 필요하거나 구현 중이냐고 물어보기
  2. 만약 그렇다면 Protocol을 제공하거나 제공받기
  3. 그거에 맞추서 창우는 MockMusicListRepository로 MusicListView 구현체를 구현한다
  4. DefaultMusicListRepository를 구현하는 사람은 아까 의논한 프로토콜에 맞춰서 구현한다
  5. 각자 테스트하고 Mock -> Default로 갈아끼고 테스트 한번 더 한 후에 머지하기

저도 사실 이런 내용은 잘 몰라서 의논하고 싶어서 적어봤습니다 ㅎㅎ

@windowcow
Copy link
Collaborator

마침 제가 PlaylistPlaylistRepository도 정의해야할 것 같은데 프로토콜을 의논해서 정해두고 나중에 끼워맞춰지는지 연습해봐도 좋을 것 같아요! 저는 사용자의 플레이리스트들을 리스트에 보여주는 UI를 그려야합니다.

struct PlaylistListView: some View {
    var playlistManager: any PlaylistRepository

}

protocol PlaylistRepository {
    func fetchPlaylist() async
    func deletePlaylist(playlistID: String)() async
}

이런식으로 PlaylistManager의 인터페이스만 의논해서 정해두고
저는 그거에 맞춰서 PlaylistListView를 구현하고
근영님은 DefaultPlaylistRepository를 구현하신 후에 합치면 어떨까요??

좋은 기술적 도전이라고 생각합니다!

@Park-kxng
Copy link
Collaborator Author

저번에 뷰랑 뷰 모델 따로 작업할 때 프로토콜 만들어서 작업하자라고 말씀하셨던 것 같은데 그와 비슷한 맥락으로 이해했습니다.
노래를 조회, 저장, 삭제를 구현하는 PlaylistRepository에 대한 프로토콜을 먼저 정의하고 시작하자는 말씀이신 건가요?

@Park-kxng
Copy link
Collaborator Author

지금 CoreData 공부하며 Entity 정의 중이어서, 다 정의한 후에 매개변수나 리턴 값이 확정된 후 프로토콜 이야기해보면 어떨까요?

@windowcow
Copy link
Collaborator

저번에 뷰랑 뷰 모델 따로 작업할 때 프로토콜 만들어서 작업하자라고 말씀하셨던 것 같은데 그와 비슷한 맥락으로 이해했습니다. 노래를 조회, 저장, 삭제를 구현하는 PlaylistRepository에 대한 프로토콜을 먼저 정의하고 시작하자는 말씀이신 건가요?

맞습니다. PlaylistListViewDefaultPlaylistRepository 모두 PlaylistRepository에 의존하도록 하는겁니다!
원래는 PlaylistListView -> DefaultPlaylistRepository였지만
PlaylistListView -> PlaylistRepository <- DefaultPlaylistRepository로 두고
PlaylistRepository를 고려해서 두 구현체를 정의하는 겁니다!

DIP 그 자체인거죠 🙀🙀

대신 PlaylistRepository는 최대한 안 바뀌도록 적어도 프로토콜을 정의할 때에는 많이 의논해야 할 것 같네요

@windowcow
Copy link
Collaborator

지금 CoreData 공부하며 Entity 정의 중이어서, 다 정의한 후에 매개변수나 리턴 값이 확정된 후 프로토콜 이야기해보면 어떨까요?

좋습니다!! CoreData를 PlaylistRepository 때문에 하시는 거라면 일단은 그것 조차도 Mock으로 두는 방법이 있을 것 같습니다.

struct DefaultPlaylistRepository: PlaylistRepository {
    private var playlistDatabaseService: any PlaylistDataBaseService
    private var playlistNetworkService: any PlaylistNetworkService

    func fetchPlaylist() async -> [Playlist] {
        if isLoggedIn {
            return await playlistDatabaseService.fetch()
        } 

        return await playlistNetworkService.fetch()
   }
}

이렇게 두고

struct MockDatabaseService: PlaylistDataBaseService {
    private var playlistDatabaseService: any PlaylistDataBaseService
    private var playlistNetworkService: PlaylistNetworkService
    private var storage: [Playlist]

    func fetch() async -> [Playlist] {
        return // 가짜데이터
   }
    
    func save(playlist: Playlist) async {
        storage.append(playlist)
    }
}

이미 이렇게 하셨을 수도 있으시겠지만 이렇게 둔 다음에
MockDatabaseService 나중에 구현하고 나중에 갈아끼워도 될 것 같습니다
혹시 코어데이터를 지금 하기 싫으시다면 말입니다 ㅎㅎ

@windowcow
Copy link
Collaborator

예전에 마스터님께서 최대한 하위 모듈에 시켜라!라고 한게 이제 뭔가 와닿는 것 같습니다

Park-kxng added a commit to Park-kxng/iOS06-molio that referenced this issue Nov 14, 2024
Park-kxng added a commit to Park-kxng/iOS06-molio that referenced this issue Nov 14, 2024
- Data 계층에 CoreData의 DataModel이 추가 되면서, Model이라는 폴더가 생성되었다.
- DTO 폴더만 존재하였으나, Model이라는 폴더가 생기며 Model 폴더 안에 DTO, DataModel을 정리할 수 있다.
Park-kxng added a commit to Park-kxng/iOS06-molio that referenced this issue Nov 14, 2024
- MusicKit에 Playlist라는 클래스가 이미 존재하여 MolioPlaylist로 이름을 설정했다.
Park-kxng added a commit to Park-kxng/iOS06-molio that referenced this issue Nov 14, 2024
Park-kxng added a commit to Park-kxng/iOS06-molio that referenced this issue Nov 14, 2024
Park-kxng added a commit to Park-kxng/iOS06-molio that referenced this issue Nov 14, 2024
Park-kxng added a commit to Park-kxng/iOS06-molio that referenced this issue Nov 14, 2024
@Park-kxng Park-kxng changed the title 오른쪽 스와이프 시 일정 위치 이상 넘어가고 touchUp시 플레이리스트에 저장한다. 오른쪽 스와이프 시 음악을 플레이리스트에 저장한다. Nov 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants