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

강원대_Android_이아림_1주차과제 #8

Open
wants to merge 33 commits into
base: arieum
Choose a base branch
from

Conversation

arieum
Copy link

@arieum arieum commented Jun 27, 2024

  • UI가 생각보다 고역이었습니다. 리니어레이아웃에서 두 텍스트뷰를 양끝단에 두기위해 space공간을 두는점, softkeyboard가 화면을 가리지 않게 하기 위해 manifest를 수정해야 했던점... 이러한 사소한 부분들이 발목을 많이 잡았습니다
  • 역시나 RecyclerView+Adapter를 구현하는 게 만만치 않았습니다 동시에 Intent도 자칫 잘못하면 갑자기 다른 화면으로 넘어가 난행이었던 것 같습니다
  • 코드 작성하면서 느꼈지만, 내가 클래스명을 지었음에도 계속해서 헷갈렸던것 같습니다. 어떤 클래스가 어떤 기능을 하는지 한눈에 알 수 있는 이름을 짓는다는건 생각보다 연습이 많이 필요한 것 같습니다

arieum and others added 30 commits June 24, 2024 14:35
- Show warning toast msg if name or phone_num is Empty.
- Show success toast msg if both name and phone_num is not Empty.
- Modified AndroidManifest.xml to add 'adnroid:windowSoftInputMode="adjustResize"'.
- Ensured bottom_view remains visible if soft_keyboard is diplayed
- Add edittext_width and edittext_height to dimens.xml
- Add [attr]_hint to strings.xml
- Update EditText layout in activity_main.xml to use resource values for width, height, hint
- MainActivity : Display the list of added contacts
- ViewContact : Show the detailed info of the selected contact
- ResiterContact : Register new contact
- Use a rounded view with black border
- Add Textview to display the first letter of the name in a
  Circular_background
@arieum arieum changed the base branch from main to arieum June 28, 2024 08:35
Comment on lines +28 to +31
lateinit var recyclerView: RecyclerView
lateinit var viewAdapter: PersonAdapter
lateinit var viewManager: RecyclerView.LayoutManager
lateinit var emptyTextview: TextView
Copy link

Choose a reason for hiding this comment

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

image

IDE를 확인해보시면 외부에서 접근하지 않는 변수는 private으로 변경하라는 주의문구가 나올거에요. 개발하시면서 IDE가 하는 주의사항에 유의하셔서 개발하시면 좋을 것 같습니다.
언제 private을 써야 하는지 판단하기 힘드시다면 private을 기본적으로 작성하시고 필요하실때 접근 제한자의 범위를 하나씩 열어보시는게 공부하실 때 도움 되실 겁니다!

startActivity(intent)
}

recyclerView = findViewById<RecyclerView>(R.id.recyclerView).apply {
Copy link

Choose a reason for hiding this comment

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

apply scope function을 의도대로 잘 작성해주셨네요! 👍

lateinit var viewAdapter: PersonAdapter
lateinit var viewManager: RecyclerView.LayoutManager
lateinit var emptyTextview: TextView
var personList: MutableList<Person> = mutableListOf<Person>()
Copy link

Choose a reason for hiding this comment

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

personList의 책임 주체가 어디인지 분명히 하는게 좋을 것 같네요. 이는 멘티분이 생각하시는 대로 일관성있게 작성하시는게 중요합니다.
Android MVC 패턴에서 SSOT (Single Source of Truth)를 챙기기에는 현재 단계에서는 생각할 부분이 많고 모호한 부분이 존재한다고 생각합니다. 현재 작성해주신 코드에서는 SSOT가 MainActivity일 수도 PersonAdapter일 수도 있겠네요. 누가 책임을 가질지는 모호할 수 있지만 중요한 것은 두 객체간의 공유하는 데이터가 있을 때 이를 변경하는 것은 하나의 클래스에서 해야만 한다는 것입니다.
지금 작성해주신바로는 Adapter, Activity 모두 PersonList에 접근해서 데이터를 변경할 수 있네요.
이를 해결하기 위해서 두 가지 방법으로 리팩토링 할 수 있습니다.

  1. MainActivity가 데이터를 관리하게 한다고 한다면 Adapter를 최대한 멍청하게 만드셔야 합니다. 지금과 같은 방식으로 데이터의 변경에 대한 부분을 Adapter를 사용하는 쪽에서 책임을 지는것 입니다. (데이터를 추가하고, 데이터의 변경이 있음을 알리는 등) 이 방법의 경우 장점은 Adapter를 최대한 멍청하게 유지함으로써 다른 View에서도 사용하기 편리할 수 있습니다. 하지만 단점은 데이터 추가 및 변경을 사용하는 쪽에서 하나하나 다 알려줘야 하기 때문에 사용하는 곳(MainActivity 등 View)의 역할이 더더욱 커질 수 있겠네요.

  2. Adapter가 데이터를 관리하는 방식입니다. Adapter가 데이터를 관리해서 MainActivity는 단순히 Adapter에 초기 데이터를 넘겨주고 데이터의 추가 및 수정, 변경 감지에 대한 책임을 Adapter로 미뤄버리는 것입니다. 이 방식의 장점은 MVC 패턴의 가장 큰 단점인 Activity가 너무 많은 역할을 하는 상태(God Object)를 완화시킬 수 있겠네요. 하지만 이 방식도 단점이 존재합니다. 바로 해당 Adapter를 쓰는 View와 강결합된다는 것입니다.

사실 이 문제는 지금 안드로이드를 시작하는 단계에서 생각하기에는 무거운 주제일 수 있습니다. 앞으로 안드로이드를 공부하시다보면 여러가지 아키텍처에 대해서 배우실 겁니다. 현재 단계에서 존재하는 이러한 단점을 인지하고 있으면 추후 다른 아키텍처나 또 다른 Adapter 들을 배우실 때 도움이 되실 거에요. 두 가지 방식 중 한 가지 방식으로 리팩토링을 진행해 보셔도 좋고 힘드시다면 단순히 생각만 해보셔도 좋을 것 같습니다 ~

Comment on lines +42 to +50
val intent = Intent(this, ViewContact::class.java).apply {
putExtra("name", it.name)
putExtra("tel", it.tel)
putExtra("mail", it.mail)
putExtra("sex", it.sex)
putExtra("memo", it.memo)
putExtra("birth", it.birth)
}
startActivity(intent)
Copy link

Choose a reason for hiding this comment

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

이 방식은 Adapter가 가지는 데이터를 신뢰한다는 생각이 깔려있네요. 이런 부분에서 데이터 일관성이 깨질 수 있습니다. 만일 데이터 주체가 MainActivity에 있다면 단편적인 정보(index 등)을 가지고 MainActivity에서 조회하는 방법을 사용할 수 있겠네요.

updateUI()
}

private fun updateUI() {
Copy link

Choose a reason for hiding this comment

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

updateUI는 데이터가 변경이 될 때마다 이뤄져야 하는 것으로 보입니다. Observable 패턴을 쓰지 않고는 이러한 변경을 감지하는게 힘들 수 있겠네요. 이를 위해 adapter에서 데이터 감지를 포착해주는 콜백 메서드가 있습니다. 이를 활용해보세요.

Comment on lines +73 to +74
personList.add(Person(name, tel, mail, sex, memo, birth))
viewAdapter.notifyDataSetChanged()
Copy link

Choose a reason for hiding this comment

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

MainActivity에서 데이터를 관리한 다면 이 두 메서드는 묶어서 하나의 메서드로 작성할 수 있겠네요.

Comment on lines +73 to +74
personList.add(Person(name, tel, mail, sex, memo, birth))
viewAdapter.notifyDataSetChanged()
Copy link

Choose a reason for hiding this comment

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

notifyDataSetChanged()를 사용하시면 IDE에서 주의사항을 알려줄 텐데 이 메서드는 효율적인 방법이 아닙니다. 한 번 찾아보시겠어요?

android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
Copy link

Choose a reason for hiding this comment

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

end 및 bottom 쪽으로만 margin이 필요한데 전체 margin을 주신 이유가 있을까요?

}

recyclerView = findViewById<RecyclerView>(R.id.recyclerView).apply {
setHasFixedSize(true)
Copy link

Choose a reason for hiding this comment

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

성능을 위한 코드를 잘 작성해 주셨네요.
혹시 이 함수가 어떤 역할을 하는지 알고 계신가요?

Comment on lines +66 to +71
val name = data?.getStringExtra("name") ?: ""
val tel = data?.getStringExtra("tel") ?: ""
val mail = data?.getStringExtra("mail") ?: ""
val sex = data?.getStringExtra("sex") ?: ""
val memo = data?.getStringExtra("memo") ?: ""
val birth = data?.getStringExtra("birth") ?: ""
Copy link

Choose a reason for hiding this comment

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

이 정보들이 null일 때 꼭 빈 String을 가져야 하나요? 그냥 null을 쓰면 안될까요?

@mkSpace
Copy link

mkSpace commented Jun 30, 2024

안녕하세요 앞으로 6주간 코드 리뷰를 도와드리게 된 제리 멘토라고 합니다.
전반적으로 구현 사항을 잘 구현해주셨네요!
제가 남겨드린 리뷰 살펴보시고 이해가 힘드신 부분은 추가 의견 남겨주시면 바로 답변 남겨드리겠습니다.
의견을 작성하기 힘든 부분들은 추후 멘토링 시간을 이용해서 자세히 알려드릴 수 있으면 좋겠습니다.
감사합니다 ~

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

Successfully merging this pull request may close these issues.

2 participants