-
Notifications
You must be signed in to change notification settings - Fork 48
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
[부나] 1, 2단계 쇼핑 장바구니 제출합니다. #25
Conversation
- Presenter.view.presenter와 같은 접근을 방지하기 위한 목적
안녕하세요 말리빈 😃 리뷰 남겨주신 부분에 대해 제가 잘 이해하지 못한 부분에 대해 코멘트를 남겨놨습니다! |
fun getPartially(size: Int): List<DataRecentProduct> | ||
fun add(product: DataRecentProduct) |
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.
아래 처럼 작성한다면, source는 무엇을 Partially하게 가져온다는 의미일까요?
val source = LocalRecentProductDataSource()
source.getPartially()
add 라는 단어에 대해서도 고민해보세요 :)
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.
getPartially()
, add()
만으로는 무엇을 대상으로 동작하는 함수인지 파악하기 어렵겠군요!
getRecentProductsPartially()
, addRecentProduct()
로 변경하였습니다!
typealias DataPageNumber = PageNumber | ||
|
||
data class PageNumber(val value: Int, val sizePerPage: Int) { |
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.
typealias를 사용한 의도를 잘 모르겠어요.
이렇게 사용했을 때 어떤 이점을 가져올 수 있었나요?
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.
각 레이어별로 model이 존재하는데, IDE 패키지에서 봤을 때 DataXxx, UiXxx, DomainXxx 와 같이 Prefix가 붙어 있는 것이 읽기 힘들다고 느껴졌습니다!
그래서 코딩을 할 때에는 모델의 이름을 그대로 사용하고, 사용할 때에는 typealias의 이름을 사용하도록 하였습니다.
super.onCreate(savedInstanceState) | ||
binding = DataBindingUtil.setContentView(this, R.layout.activity_basket) |
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.
layout Id를 알고 있는 경우에는 type safe을 위해 후자를 택하라
는 이유가 무엇이었을까요?
layout id를 모르는 경우에도 Databinding을 쓸 수 있나보네요.
DataBindingUtil.setContentView가 반환하는 타입은 ActivityBasketBinding 이었나요?
물론 실제 반환하는 인스턴스는 ActivityBasketBinding가 맞겠지요! 메서드에 반환으로 적혀있는 것은 무엇이었나요?
binding.adapter = BasketAdapter(presenter::removeBasketProduct) | ||
} | ||
|
||
override fun updateBasket(products: List<UiProduct>) { | ||
binding.adapter?.submitList(products) | ||
} |
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.
Adapter를 이렇게 활용한 특이한 케이스는 처음 보네요! 😮
|
||
override fun updateNavigatorEnabled(previous: Boolean, next: Boolean) { |
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.
previous, next 변수명은 좀 더 고민해보았으면 좋겠어요.
이전 Boolean 값과 다음 Boolean값으로 이해가 되어서 혼란이 있었어요.
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.
다시 보니 코드를 작성한 본인조차도 헷갈리네요 🤔
조금 더 구체적으로 작성해보겠습니다!
override fun fetchNext() { | ||
currentPage++ | ||
fetchBasket() | ||
} | ||
|
||
override fun fetchPrevious() { | ||
currentPage-- | ||
fetchBasket() | ||
} |
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.
#25 (comment)
동일한 의견이에요.
이후에 특정 페이지를 불러와야 한다면 어떤 변경점이 생겨날까요?
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.
이 코드도 마찬가지군요!
이전, 다음보다는 fetchBasket() 메서드에 page 인자를 전달받는 것이 여러 면에서 사용하기 좋아 보입니다!
이로 인해 위 두 함수는 필요 없어져서 지웠습니다 : )
override fun addBasketProduct() { | ||
thread { |
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.
ANR이 발생하기 이전에 어떤 현상이 생겨날까요?
ANR은 어떨 때에 발생할까요?
스레드 간 이동을 수행하는 것은 Presenter의 일일까요?
이후에는 thread 이동에 대해 어떻게 더 잘 활용할 수 있을 지 고민해보셨으면 좋겠어요 :)
지금은 스레드간 이동을 하는 경우 고려해야할 것들이 매우 많은데요,
그렇기에 해당 문제를 인지하고 따로 공부해보시고, 지금은 MVP 아키텍처와 레벨 1 내용을 안드로이드에 지속적으로 적용해보는 것을 연습해보셨으면 좋겠어요. 😊
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.
1, 2단계 미션 고생 많으셨어요!
다음 미션을 위해 머지할게요.
피드백은 다음 미션에 반영해주세요!
private val shoppingDatabase by lazy { ShoppingDatabase(this) } | ||
override val presenter: Presenter by lazy { createShoppingPresenter(this, shoppingDatabase) } |
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.
#25 (comment)
여전히 View에서 ShoppingDatabase를 알고있네요!
ShoppingDatabase의 생성도 분리된 곳에서 수행해보는 것은 어떨까요?
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.
ShoppingDatabase 생성 또한 별도로 분리하여 주입받도록 변경하였습니다!
class LoadMoreAdapter( | ||
private val onItemClick: () -> Unit, | ||
private val button: MutableList<Any> = mutableListOf(), | ||
) : RecyclerView.Adapter<LoadMoreViewHolder>() { |
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.
이 버튼 친구는 따로 Adapter를 선언하기보다, 다른 Adapter의 ViewType으로 넣어보는 건 어떨까요?
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.
우선 3, 4단계를 진행하고 시간이 되면 리팩토링을 진행해보겠습니다!
감사합니다 : )
verify(exactly = 1) { basketRepository.remove(any()) } | ||
verify(exactly = 1) { basketRepository.getPartially(any()) } | ||
verify(exactly = 1) { view.updateBasket(any()) } | ||
verify(exactly = 1) { view.updateNavigatorEnabled(any(), any()) } |
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.
모든 값을 any()로 검증하기 보다 의도된 특정 값이 들어왔는 지 검증해보는 건 어떨까요?
* feat: 기초 세팅 * docs(README): 기능목록 작성 * feat: 추가 기초세팅 * feat(Price): 상품 가격 검증 로직 작성 * feat(Product): 상품 클래스 구현 * feat(Basket): 장바구니에 상품을 담는 기능 구현 * feat(Basket): 장바구니 삭제 기능 구현 * feat(BasketRepository): 장바구니 레퍼지토리 인터페이스 추가 * feat(ProductRepository): 상품 레퍼지토리 인터페이스 추가 * feat(RecentProductRepository): 최근 상품 레퍼지토리 인터페이스 추가 * feat(themes): 액션바 제거 * feat(ShoppingActivity): Toolbar 제작 * feat(item_shopping): 제품화면 리사이클러뷰 아이템 생성 * feat(ShoppingActivity): 제품 목록을 보여주는 기능 구현 * feat(ShoppingActivity): 제품 상세 화면 구현 * feat(ShoppingActivity): 인텐트 팩토리함수 작성 * feat(BasketActivity): 장바구니 화면 구현 * feat(ShoppingActivity): 리사이클러뷰 첫번쨰 아이템 뷰작업 * feat(ShoppingActivity): 멀티뷰 아이템 어댑터 생성 * feat(ShoppingActivity): 리사이클러뷰 멀티뷰 수용하도록 로직 작성 * feat(ProductDataBase): product 저장 및 불러오기 로직 작성 * gitignore 설정 * feat(RecentProductDataBase): 최근 목록 관련 DB로직 작성 * feat(RecentProductRepository): 최근 본 상품 저장 로직 작성 * feat(RecentProduct): 최근 본 상품 어댑터 최신화 로직 * feat(ShoppingActivity): 상품목록 불러오는 기능 구현 * feat(ProductDetailActivity): 화면간 이동로직 작성 * feat(BasketRepository): 장바구니 테이블 구현 * feat(BasketActivity): 장바구니 목록 불러오는 기능구현 * feat(ProductDetailActivity): 화면간 이동로직 작성 * feat(Basket): 장바구니 데이터 삭제로직 작성 * feat(diffutil): areItemsTheSame 함수 수정(리사이클러뷰 아이템 blink issue) 방어적 복사와 해시코드와 ===을 생각해보시오 * feat(ShoppingActivity): 장바구니 버튼 클릭리스너 작성 * feat(BasketActivity): 툴바 백버튼 설정 * feat(ProductDetail): 툴바 백버튼 설정 * feat(ShoppingActivity):페이징시 다음 아이템 존재하는지 판단로직 작성 * feat(ShoppingActivity): Pagination 구현 * feat(BasketActivity): 장바구니 페이징 UI 네비게이터 생성 * feat(BasketActivity): 장바구니 페이지네이션 구현 * refactor(ShoppingActivity): 리사이클러뷰 어댑터를 ConcatAdapter로 변경 * refactor(ProductDetailActivity): Toolbar에 menu를 사용하도록 변경 * refactor(uimodel): 패키지 이동 * feat(RecyclerViewBindingAdapter): setHasFixedSize를 Databinding으로 구현 * refactor: ShoppingGridLayoutManager 클래스로 분리 * refactor(ShoppingActivity): RecyclerView 관련 로직을 메서드로 분리 * refactor(ShoppingActivity): RecyclerView에 필요한 객체 초기화 로직을 BindingAdapter로 분리 * refactor: 코드 포맷팅 * feat(ShoppingActivity): 아이템을 클릭하면 최근 본 상품 리스트에 보여주는 기능 구현 * feat(RecentProducts): 최근 본 상품 도메인 클래스 구현 * fix(ShoppingActivity): 더 보기 버튼 안 보이는 버그 수정 * fix(ShoppingActivity): 처음 최근 본 목록에 아이템 추가시 업데이트 안 되는 버그 수정 * refactor(BasketActivity): RecyclerView adapter listener를 데이터 바인딩으로 분리 * fix(RecentProductWrapperAdapter): 최근 본 목록이 여러개 보이는 버그 수정 * refactor(ToolbarBindingAdapter): NavigationIconClickListener 데이터 바인딩 구현 * feat(BasketActivity): 장바구니 페이지네이션 구현 * refactor(Database): Database close()를 Activity에서 하도록 변경 * fix(BasketActivity): 페이지네이션 비정상적으로 동작하는 버그 수정 * refactor(ShoppingActivity): fetchAll() 메서드 구현 * refactor(Presenter): 모든 Presenter 팩토리 함수 구현 * refactor(Presenter): Thread를 사용하지 않도록 변경 * refactor(ShoppingActivity): 불필요한 함수 제거 * refactor(Presenter): 추상 클래스로 변경 - Presenter.view.presenter와 같은 접근을 방지하기 위한 목적 * refactor(BasketPresenter): 페이지와 제품 목록을 생성자로 이동 * test(BasketPresenterTest): 프레젠터 테스트 코드 작성 * test(ShoppingPresenterTest): 테스트 코드 작성 * test(ProductDetailPresenterTest): 테스트 코드 작성 * feat(PageNumber): 페이지 번호 검증 기능 구현 * feat(PageNumberTest): 페이지 번호 도메인 테스트 코드 작성 * test(BasketProductTest): 장바구니 도메인 모델 테스트 코드 작성 * fix(Products): 불러오기 단위가 1일 때, 항상 더 불러올 수 없는 상태인 버그 수정 * test(ProductsTest): 제품 목록 도메인 모델 테스트 코드 작성 * test(RecentProductsTest): 최근 조회 목록 도메인 모델 테스트 코드 작성 * refactor: View 네이밍 축약어를 사용하지 않도록 변경 * refactor: 코드 포맷팅 --------- Co-authored-by: changhwan <[email protected]>
* feat: 기초 세팅 * docs(README): 기능목록 작성 * feat: 추가 기초세팅 * feat(Price): 상품 가격 검증 로직 작성 * feat(Product): 상품 클래스 구현 * feat(Basket): 장바구니에 상품을 담는 기능 구현 * feat(Basket): 장바구니 삭제 기능 구현 * feat(BasketRepository): 장바구니 레퍼지토리 인터페이스 추가 * feat(ProductRepository): 상품 레퍼지토리 인터페이스 추가 * feat(RecentProductRepository): 최근 상품 레퍼지토리 인터페이스 추가 * feat(themes): 액션바 제거 * feat(ShoppingActivity): Toolbar 제작 * feat(item_shopping): 제품화면 리사이클러뷰 아이템 생성 * feat(ShoppingActivity): 제품 목록을 보여주는 기능 구현 * feat(ShoppingActivity): 제품 상세 화면 구현 * feat(ShoppingActivity): 인텐트 팩토리함수 작성 * feat(BasketActivity): 장바구니 화면 구현 * feat(ShoppingActivity): 리사이클러뷰 첫번쨰 아이템 뷰작업 * feat(ShoppingActivity): 멀티뷰 아이템 어댑터 생성 * feat(ShoppingActivity): 리사이클러뷰 멀티뷰 수용하도록 로직 작성 * feat(ProductDataBase): product 저장 및 불러오기 로직 작성 * gitignore 설정 * feat(RecentProductDataBase): 최근 목록 관련 DB로직 작성 * feat(RecentProductRepository): 최근 본 상품 저장 로직 작성 * feat(RecentProduct): 최근 본 상품 어댑터 최신화 로직 * feat(ShoppingActivity): 상품목록 불러오는 기능 구현 * feat(ProductDetailActivity): 화면간 이동로직 작성 * feat(BasketRepository): 장바구니 테이블 구현 * feat(BasketActivity): 장바구니 목록 불러오는 기능구현 * feat(ProductDetailActivity): 화면간 이동로직 작성 * feat(Basket): 장바구니 데이터 삭제로직 작성 * feat(diffutil): areItemsTheSame 함수 수정(리사이클러뷰 아이템 blink issue) 방어적 복사와 해시코드와 ===을 생각해보시오 * feat(ShoppingActivity): 장바구니 버튼 클릭리스너 작성 * feat(BasketActivity): 툴바 백버튼 설정 * feat(ProductDetail): 툴바 백버튼 설정 * feat(ShoppingActivity):페이징시 다음 아이템 존재하는지 판단로직 작성 * feat(ShoppingActivity): Pagination 구현 * feat(BasketActivity): 장바구니 페이징 UI 네비게이터 생성 * feat(BasketActivity): 장바구니 페이지네이션 구현 * refactor(ShoppingActivity): 리사이클러뷰 어댑터를 ConcatAdapter로 변경 * refactor(ProductDetailActivity): Toolbar에 menu를 사용하도록 변경 * refactor(uimodel): 패키지 이동 * feat(RecyclerViewBindingAdapter): setHasFixedSize를 Databinding으로 구현 * refactor: ShoppingGridLayoutManager 클래스로 분리 * refactor(ShoppingActivity): RecyclerView 관련 로직을 메서드로 분리 * refactor(ShoppingActivity): RecyclerView에 필요한 객체 초기화 로직을 BindingAdapter로 분리 * refactor: 코드 포맷팅 * feat(ShoppingActivity): 아이템을 클릭하면 최근 본 상품 리스트에 보여주는 기능 구현 * feat(RecentProducts): 최근 본 상품 도메인 클래스 구현 * fix(ShoppingActivity): 더 보기 버튼 안 보이는 버그 수정 * fix(ShoppingActivity): 처음 최근 본 목록에 아이템 추가시 업데이트 안 되는 버그 수정 * refactor(BasketActivity): RecyclerView adapter listener를 데이터 바인딩으로 분리 * fix(RecentProductWrapperAdapter): 최근 본 목록이 여러개 보이는 버그 수정 * refactor(ToolbarBindingAdapter): NavigationIconClickListener 데이터 바인딩 구현 * feat(BasketActivity): 장바구니 페이지네이션 구현 * refactor(Database): Database close()를 Activity에서 하도록 변경 * fix(BasketActivity): 페이지네이션 비정상적으로 동작하는 버그 수정 * refactor(ShoppingActivity): fetchAll() 메서드 구현 * refactor(Presenter): 모든 Presenter 팩토리 함수 구현 * refactor(Presenter): Thread를 사용하지 않도록 변경 * refactor(ShoppingActivity): 불필요한 함수 제거 * refactor(Presenter): 추상 클래스로 변경 - Presenter.view.presenter와 같은 접근을 방지하기 위한 목적 * refactor(BasketPresenter): 페이지와 제품 목록을 생성자로 이동 * test(BasketPresenterTest): 프레젠터 테스트 코드 작성 * test(ShoppingPresenterTest): 테스트 코드 작성 * test(ProductDetailPresenterTest): 테스트 코드 작성 * feat(PageNumber): 페이지 번호 검증 기능 구현 * feat(PageNumberTest): 페이지 번호 도메인 테스트 코드 작성 * test(BasketProductTest): 장바구니 도메인 모델 테스트 코드 작성 * fix(Products): 불러오기 단위가 1일 때, 항상 더 불러올 수 없는 상태인 버그 수정 * test(ProductsTest): 제품 목록 도메인 모델 테스트 코드 작성 * test(RecentProductsTest): 최근 조회 목록 도메인 모델 테스트 코드 작성 * refactor: View 네이밍 축약어를 사용하지 않도록 변경 * refactor: 코드 포맷팅 --------- Co-authored-by: changhwan <[email protected]>
안녕하세요 말리빈!
이번 미션.. 구현하지 못한 부분과 더티 코드가 많습니다.
리뷰 요청 드리기가 부끄러울 정도네요.. 🥲
잘 부탁드립니다!