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

[7차 세미나] 리펙토링 #8

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Tving-Clone/Tving-Clone/Application/AppDIContainer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// AppDIContainer.swift
// Tving-Clone
//
// Created by Seonwoo Kim on 6/7/24.
//

import Foundation

final class AppDIContainer {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

와! 의존성분리를 하시다니 진짜 본격적으로 하셧군요! 역시 빡고수,,


func makeContentSceneDIContainer() -> ContentDIContainer {
let dependencies = ContentDIContainer.Dependencies(contentDataSource: ContentDataSource())
return ContentDIContainer(dependencies: dependencies)
}
}
41 changes: 41 additions & 0 deletions Tving-Clone/Tving-Clone/Application/ContentDIContainer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// DIConteainer.swift
// Tving-Clone
//
// Created by Seonwoo Kim on 6/7/24.
//

import Foundation

final class ContentDIContainer {

struct Dependencies {
let contentDataSource: ContentDataSource
}

private let dependencies: Dependencies

init(dependencies: Dependencies) {
self.dependencies = dependencies
}

func makeContentRepository() -> ContentRepository {
return DefaultContentRepository(contentDataSource: dependencies.contentDataSource)
}

func makeContentUseCase() -> ContentUseCase {
return DefaultContentUseCase(repository: makeContentRepository())
}

func makeMainContentViewModel() -> MainContentViewModel {
return MainContentViewModel(contentUseCase: makeContentUseCase())
}

func makeMainContentViewController() -> MainContentViewController {
return MainContentViewController(viewModel: makeMainContentViewModel())
}

func makeTabBarController() -> TabBarController {
return TabBarController(mainContentViewModel: makeMainContentViewModel())
}
}
15 changes: 9 additions & 6 deletions Tving-Clone/Tving-Clone/Application/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@ import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var window: UIWindow?

let appDIContainer = AppDIContainer()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

의존성 분리 수고하셨습니다!!


func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: windowScene)
let navigationController = UINavigationController(rootViewController: TabBarController())
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
}

let contentSceneDIContainer = appDIContainer.makeContentSceneDIContainer()
let tabBarController = contentSceneDIContainer.makeTabBarController()

window = UIWindow(windowScene: windowScene)
window?.rootViewController = UINavigationController(rootViewController: tabBarController)
window?.makeKeyAndVisible()
}

func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
Expand Down
81 changes: 81 additions & 0 deletions Tving-Clone/Tving-Clone/Data/DataSources/ContentDataSource.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//
// ContentDataSource.swift
// Tving-Clone
//
// Created by Seonwoo Kim on 6/7/24.
//

import Foundation

import Moya

class ContentDataSource {
private var movieProvider = MoyaProvider<MovieTargetType>(plugins: [MoyaLoggingPlugin()])
}

extension ContentDataSource {
func getMovieInfo(completion: @escaping (Result<[Content], Error>) -> Void) {
movieProvider.request(.getMovieData) { result in
switch result {
case .success(let response):
let statusCode = response.statusCode
let data = response.data
do {
let networkResult = try self.judgeStatus(by: statusCode, data, MovieResponseDTO.self).toDomain()
completion(.success(networkResult))
} catch {
completion(.failure(error))
}
case .failure(let error):
completion(.failure(error))
}
}
}

func getDetailInfo(code: String, completion: @escaping (Result<ContentDetail, Error>) -> Void) {
movieProvider.request(.getDetailData(code: code)) { result in
switch result {
case .success(let response):
let statusCode = response.statusCode
let data = response.data
do {
let networkResult = try self.judgeStatus(by: statusCode, data, DetailResponseDTO.self).toDomain()
completion(.success(networkResult))
} catch {
completion(.failure(error))
}
case .failure(let error):
completion(.failure(error))
}
}
}

private func judgeStatus<T: Codable>(by statusCode: Int, _ data: Data, _ object: T.Type) throws -> T {
switch statusCode {
case 200..<205:
return try isValidData(data: data, T.self)
case 400..<500:
throw NetworkError.requestError
case 500:
throw NetworkError.serverError
default:
throw NetworkError.networkFailure
}
}

private func isValidData<T: Codable>(data: Data, _ object: T.Type) throws -> T {
let decoder = JSONDecoder()
guard let decodedData = try? decoder.decode(T.self, from: data) else {
print("⛔️ 디코딩 오류가 발생했습니다 ⛔️")
throw NetworkError.decodingError
}
return decodedData
}
}

enum NetworkError: Error {
case requestError
case serverError
case networkFailure
case decodingError
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// DefaultContentRepository.swift
// Tving-Clone
//
// Created by Seonwoo Kim on 6/7/24.
//

import Foundation

import Moya

final class DefaultContentRepository {

private let contentDataSource: ContentDataSource

init(contentDataSource: ContentDataSource) {
self.contentDataSource = contentDataSource
}
}

extension DefaultContentRepository: ContentRepository {
func getMovieInfo(completion: @escaping (Result<[Content], any Error>) -> Void) {
contentDataSource.getMovieInfo(completion: completion)
}

func getDetailInfo(code: String, completion: @escaping (Result<ContentDetail, any Error>) -> Void) {
contentDataSource.getDetailInfo(code: code, completion: completion)
}
}
20 changes: 20 additions & 0 deletions Tving-Clone/Tving-Clone/Domain/Entities/Content.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// Movie.swift
// Tving-Clone
//
// Created by Seonwoo Kim on 6/7/24.
//

import Foundation

struct Content {
let data: [ContentData]
}

struct ContentData {
let image: String
var title: String
var maker: String
var subTitle: String
var ratio: String
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
//
// DetailDataModel.swift
// MovieDetail.swift
// Tving-Clone
//
// Created by Seonwoo Kim on 5/10/24.
// Created by Seonwoo Kim on 6/7/24.
//

import UIKit
import Foundation


struct DetailDataModel {
struct ContentDetail {
var title: String
var openDt: String
var directors: String
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// ContentRepository.swift
// Tving-Clone
//
// Created by Seonwoo Kim on 6/7/24.
//

import Foundation

protocol ContentRepository {
func getMovieInfo(completion: @escaping (Result<[Content], Error>) -> Void)
func getDetailInfo(code: String, completion: @escaping (Result<ContentDetail, Error>) -> Void)
}
Comment on lines +8 to +13

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

프로토콜 선언은 이렇게 하는거군요! 잘 보고 갑니다 :)

32 changes: 32 additions & 0 deletions Tving-Clone/Tving-Clone/Domain/UseCases/ContentUseCase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// FetchContentUseCase.swift
// Tving-Clone
//
// Created by Seonwoo Kim on 6/7/24.
//

import Foundation

protocol ContentUseCase {
func fetchContent(completion: @escaping (Result<[Content], Error>) -> Void)
func fetchContentDetail(code: String, completion: @escaping (Result<ContentDetail, Error>) -> Void)
}

final class DefaultContentUseCase {

private let repository: ContentRepository

init(repository: ContentRepository) {
self.repository = repository
}
}

extension DefaultContentUseCase: ContentUseCase {
func fetchContent(completion: @escaping (Result<[Content], any Error>) -> Void) {
repository.getMovieInfo(completion: completion)
}

func fetchContentDetail(code: String, completion: @escaping (Result<ContentDetail, any Error>) -> Void) {
repository.getDetailInfo(code: code, completion: completion)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ extension LoginViewController {
nickNameViewController.modalPresentationStyle = .formSheet
self.present(nickNameViewController, animated: true)
}

@objc private func textFieldChanged() {
if let idText = loginView.idTextField.text,
let passwordText = loginView.passwordTextField.text {
Expand Down
21 changes: 0 additions & 21 deletions Tving-Clone/Tving-Clone/Models/MainDataModel.swift

This file was deleted.

4 changes: 2 additions & 2 deletions Tving-Clone/Tving-Clone/Network/DTO/DetailResponseDTO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ struct ShowType: Codable {
}

extension DetailResponseDTO {
func toAppData() -> DetailDataModel {
func toDomain() -> ContentDetail {
let movieInfo = self.movieInfoResult.movieInfo

let title = movieInfo.movieNm
Expand All @@ -70,7 +70,7 @@ extension DetailResponseDTO {
let audits = movieInfo.audits.first?.auditNo ?? ""
let companys = movieInfo.companys.first?.companyNm ?? ""

return DetailDataModel(
return ContentDetail(
title: title,
openDt: openDt,
directors: directors,
Expand Down
11 changes: 5 additions & 6 deletions Tving-Clone/Tving-Clone/Network/DTO/MovieResponseDTO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,12 @@ enum RankOldAndNew: String, Codable {
}

extension MovieResponseDTO {
func toAppData() -> [MainDataModel] {
var mainDataModels: [MainDataModel] = []
func toDomain() -> [Content] {
var mainDataModels: [Content] = []

var tempData: [MainData] = []
var tempData: [ContentData] = []
for (index, boxOfficeData) in boxOfficeResult.dailyBoxOfficeList.enumerated() {
let mainData = MainData(
image: .poster4,
let mainData = ContentData(image: "poster4",
title: boxOfficeData.movieNm,
maker: boxOfficeData.movieCd,
subTitle: boxOfficeData.movieCd,
Expand All @@ -52,7 +51,7 @@ extension MovieResponseDTO {
tempData.append(mainData)

if (index + 1) % 8 == 0 || index == boxOfficeResult.dailyBoxOfficeList.count - 1 {
let mainDataModel = MainDataModel(data: tempData)
let mainDataModel = Content(data: tempData)
mainDataModels.append(mainDataModel)
tempData.removeAll()
}
Expand Down
Loading