-
Notifications
You must be signed in to change notification settings - Fork 148
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
프로젝트 매니저 [STEP 2] Zion, karen #317
base: ic_9_zion94
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enum ListKind: String { | ||
case todo = "TODO" | ||
case doing = "DOING" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ListKind
! 이 이름을 봤을 땐 뷰와 관련이 높은 객체라고만 생각이 들어서,
JobStatus
나 TaskStatus
라는 이름은 어떨까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TaskStatus로 변경했습니다!
let deleteAction = UIContextualAction(style: .destructive, title: "Delete") { [weak self] action, view, handler in | ||
guard let self = self else { return } | ||
|
||
self.didSwipedDeleteTask(deleteTask: self.taskList[indexPath.row]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deleteTask가 중복되어서 wildcard pattern을 이용해도 좋을 것 같네용
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
중복되는 부분은 wildcard Pattern을 사용했습니다!
protocol ListViewControllerDelegate: AnyObject { | ||
func didTappedRightDoneButtonForUpdate(updateTask: Task) | ||
func didSwipedDeleteTask(deleteTask: Task) | ||
func moveCell(moveToListKind: ListKind, task: Task) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from, to 라고 argument label을 이름지어도 좋을 것 같아요 ㅎㅎ
func reloadTaskList(taskList: [Task]) { | ||
setUpDiffableDataSourceSanpShot(taskList: taskList) | ||
headerView?.setUpContents(title: listKind.rawValue, taskCount: "\(taskList.count)") | ||
} | ||
|
||
private func setUpDiffableDataSourceSanpShot(taskList: [Task] = []) { | ||
var snapShot = NSDiffableDataSourceSnapshot<Section, Task>() | ||
|
||
self.taskList = taskList | ||
snapShot.appendSections([.main]) | ||
snapShot.appendItems(taskList) | ||
diffableDataSource?.apply(snapShot) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
현재 구조면 taskList
에 변경이 있을 때마다 NSDiffableDataSourceSnapshot
인스턴스를 생성하게 되네요,
매번 새롭게 생성하는 이유가 있나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MainVC에서처럼 ListVC도 taskList에 프로퍼티 옵저버를 다는 건 어떨까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
apply 함수는 현재의 UI State와 변경될 UI State에서의 차이점을 계산하여 적용되는 것으로 알고 있습니다.
현재의 SnapShot을 불러와서 삽입 및 삭제의 로직을 나누는 것 보다 apply 로직을 하나로 두는 것이 사용하기 쉽고 가독성에도 좋다고 생각했습니다. -
현재 taskList에 대한 write와 관련된 작업은 전부 MainVC에서 발생하고 있습니다!.
따라서 MainVC에서 프로퍼티 옵저버를 다는 것이 한군데서 옵저빙하는 방법이 되기 때문에 좋은 방법이 될 수 있지 않을까 합니다.
extension MainViewController { | ||
private func didTappedRightAddButton() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right~ 라는 단어는 빼도 좋을 것 같아요.
addButton이 꼭 오른쪽에 있으리란 법도 없고, 디자인 상 왼쪽이나 가운데로 수정이 된다면 불필요하게 변수도 같이 수정되어야 하겠어요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right
와 left
가 들어가 있는 부분을 전부 삭제해주었습니다.
extension MainViewController: ListViewControllerDelegate { | ||
func moveCell(moveToListKind: ListKind, task: Task) { | ||
taskList = useCase.convertUpdatedTaskList(taskList: taskList, | ||
updateTask: task, | ||
moveTolistKind: moveToListKind) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 작업만 UseCase에서 하는 이유가 있나요?
카렌과 시온이 생각하는 UseCase란 뭔가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
뷰를 그리는 로직 및 사용자의 이벤트를 처리하는 로직 이외에는 전부 비즈니스 로직이라고 생각하고, UseCase에서는 이러한 비즈니스로직을 담당해야한다고 생각합니다. moveCell 메서드와 같이 단순히 TaskList를 Converting해주는 로직은 UseCase에서 담당해야한다고 생각합니다.
case update | ||
} | ||
|
||
weak var delegate: TaskViewControllerDelegate? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var와 delegate 사이에 띄어쓰기가 두번 된거같아요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수정해 주었습니다.
private let placeHolderLabel: UILabel = { | ||
let label = UILabel() | ||
|
||
label.text = "여기는 할일 내용 입력하는 곳이지롱\n입력 가능한 글자수는 1000자로 제한합니다" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
실제로 1000자로 제한하는 부분은 어디에 있나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저희가 누락한 것 같습니다. 코드 추가하여 적용해주었습니다.
private let dateFormatter: DateFormatter = { | ||
let dateFormatter = DateFormatter() | ||
|
||
dateFormatter.dateFormat = "yyyy. MM. dd." | ||
dateFormatter.locale = Locale.current | ||
dateFormatter.timeZone = TimeZone.current | ||
return dateFormatter | ||
}() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
모든 셀이 꼭 dateFormatter를 가지고 있어야하나요?
여기서는 전달받은 날짜값만 보여줘도 적절할 것 같은데, 어떻게 생각하세요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이부분은 ListViewControllerUseCase를 부여해서 해결했습니다.
이부분에 대해서는 위에 주신 ViewModel의 코멘트와 관련해서 구두로 대화를 나눠보고 싶습니다 델마 따로 DM으로 요청드릴게요!
private func isPassDeadline(deadline: Double) -> Bool { | ||
let currentDateString = dateFormatter.string(from: Date()) | ||
let deadlineDateString = dateFormatter.string(from: Date(timeIntervalSince1970: deadline)) | ||
let currentDate = dateFormatter.date(from: currentDateString) ?? Date() | ||
let deadlineDate = dateFormatter.date(from: deadlineDateString) ?? Date() | ||
|
||
return currentDate.timeIntervalSince1970 > deadlineDate.timeIntervalSince1970 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이것도 모든 셀에서 계산할 일인가 싶긴 하네요!
셀이 계산하지 않고 전달받은 값만 보여주고, 값을 계산하거나 관리하는 건 더 상위의 역할에서 하는 게 어떨까요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이부분 또한 상위 타입에서의 UseCase로 옮겨 해결했습니다!
@delmaSong
안녕하세요. 델마~
Zion
,karen
🦦입니다.최대한 요구사항에 맞추어 작성하기 위해 많이 늦어졌습니다.🥹
Step02 PR
보냅니다.리뷰 잘 부탁드립니다.🙇🏻♀️
🤔 고민한 부분
1️⃣ CollectionView VS TableView
2️⃣ DiffableDataSource Header 갱신
🙇🏻♀️ 조언을 얻고 싶은 부분
1️⃣
Edit
일 경우 표시되는 메뉴버튼edit
을 할 경우에 상단에 위치하는 버튼이 Cancel은 그대로 두고 edit와 done이 변동되어져야하는게 아닌가 싶은데 델마가 보시기에는 어떠신가요?edit
와 done 같은 기능을 하는데 두개가 나란히 같이 있는건 무의미해 보여서요.일단 edit으로 시작하면 어찌되었든 데이터를 전송하게 되는것 같아서 취소를 할 수가 없는 상황인 것 같습니다.2️⃣ MVP, MVVM의 차이
MVC, MVP, MVVM과 같은 아키텍처들의 역할 및 목적에 대해 파악하고 비교하는 것에 가장 많은 시간을 들였습니다. 특히 MVP와 MVVM의 차이점에 대해 이해하고 데이터 바인딩을 할 수 있는 방법에 대해 생각하고 고민해봤습니다.
제가 생각하는 View Model의 가장 큰 특징은 데이터 바인딩입니다. 하지만 데이터 바인딩을 할 수 있는 여러가지 방법들을 생각해본다면 delegate Pattern도 데이터 바인딩을 할 수 있는 하나의 방법이라고 생각합니다. MVP에서는 Presenter가 delegate를 통해 View에 UI를 갱신해야한다는 이벤트를 전달하는 아키텍처로 알고 있습니다. 그랬을 때 MVP와 MVVM의 분명한 차이가 발생하지 않는다고 생각합니다.
MVP와 MVVM을 구분할 수 있는 다른 특징을 알고 싶습니다.