Skip to content

πŸ§‘πŸ»β€πŸ’» Conventions

JunHyeong Lee edited this page Jan 3, 2023 · 10 revisions

μ•ˆλ“œλ‘œμ΄λ“œ μ»¨λ²€μ…˜

데이터 바인딩

  • Fragment λ˜λŠ” Activity μ½”λ“œ μ΅œμ†Œν™”λ₯Ό μœ„ν•œ 데이터바인딩 지ν–₯
  • λ¦¬μ‚¬μ΄ν΄λŸ¬ λ·° μ•„μ΄ν…œμ˜ 데이터 ν΄λž˜μŠ€λŠ”Β XxxItem, xml의 바인딩 λ³€μˆ˜λŠ”Β itemΒ μ‚¬μš©
  • xml viewModel 바인딩 λ³€μˆ˜λŠ” viewModel

λ·° ID 넀이밍

  • κΈ°λ³Έ ν˜•μ‹:Β [what]\_[where]\_[des]Β ex) tv_addCalendar_titleHeader
    • μ„Ήμ…˜μ„ ν™•μ‹€ν•˜κ²Œ ꡬ뢄할 수 μžˆλ‹€.
    • μ–Έλ”λ°”λ‘œ κ΅¬λΆ„λ˜μ–΄ μ›ν•˜λŠ” 정보λ₯Ό 골라 읽기 νŽΈν•˜λ‹€.
    • desλ₯Ό 읽을 λ•Œμ—λŠ” κ΅¬λΆ„ν•΄μ„œ 읽을 일이 μ—†λ‹€.
  • 각 μ ˆμ—μ„œ 두 단어 이상이 혼용될 λ•ŒλŠ” camel case둜 μž‘μ„±.
  • 카멜 μΌ€μ΄μŠ€λ‘œ κ΅¬λΆ„λ˜μ§€ μ•ŠλŠ” λ·°(switch, toolbar, ...)λŠ” ν’€ λ„€μž„μ„ μ‚¬μš©.
  • μ ‘λ‘μ‚¬λŠ” simple style(textView -> tv)
Prefix ν’€λ„€μž„
layout LinearLayout, ConstraintLayout,include ...
custom CustomView
tv TextView
btn Button
img ImageView
rv RecyclerView
cb CheckBox
cg CheckGroup
switch Switch
view View
toolbar Toolbar
κ·Έ μ™Έ CamelCase μ•žκΈ€μž λ”°μ„œ 짓기

Drawable

μ°Έκ³ :Β ν—€μ΄λ”œλŸ¬ drawable κ°€μ΄λ“œ

  • <WHAT>(_<WHERE>)_<DESCRIPTION>(_<SIZE>)
  • 이미지가 μ—¬λŸ¬κ΅°λ°μ—μ„œ ν™œμš©λ  경우,Β <WHERE>λŠ” μƒλž΅ κ°€λŠ₯ν•˜λ‹€.
  • μ΄λ―Έμ§€μ˜ 크기가 1κ°œλ°–μ— μ—†λŠ” 경우,Β <SIZE>λŠ” μƒλž΅ κ°€λŠ₯ν•˜λ‹€.

What

Prefix μ„€λͺ…
btn_ λ²„νŠΌμœΌλ‘œ μ“°μ΄λŠ” 이미지
ic_ μ•„μ΄μ½˜, 벑터에 μ‚¬μš©ν•˜λŠ” 이미지
bg_ λ²„νŠΌμ΄ μ•„λ‹Œ 화면에 λ³΄μ—¬μ§€λŠ” 이미지
img_ μ‹€μ œμ‚¬μ§„μ΄κ±°λ‚˜ μ•„μ΄μ½˜ν˜•νƒœκ°€ μ•„λ‹Œ μΌλŸ¬μŠ€νŠΈν˜•νƒœμ˜ 이미지
div_ divider둜 ν™œμš©λ˜λŠ” 이미지
color_ color selector

Selector

  • λ°°κ²½μ΄λ‚˜ λ²„νŠΌμ—μ„œ View의 μƒνƒœμ— λ”°λΌμ„œ drawable이 λ³€ν•΄μ•Ό ν•˜λŠ” κ²½μš°μ— λŒ€ν•œ 이름은 μ•„λž˜μ™€ κ°™λ‹€.
μƒνƒœ Suffix
Normal _normal
Pressed _pressed
Focused _focused
Disabled _disabled
Selected _selected
Activated _activated

Background

  • 배경색이 pressedμƒνƒœμ— λ”°λΌμ„œ white -> sky_blue둜 λ³€ν•˜λŠ” κ²½μš°λŠ”Β bg_white_to_sky_blue.xml둜 ν•œλ‹€.
  • 배경이 whiteμƒ‰μ˜ 24dp둜 ν…Œλ‘λ¦¬λ₯Ό κ·Έλ¦¬λŠ” κ²½μš°λŠ”Β bg_white_radius_24dp.xml둜 ν•œλ‹€.
  • 배경이 투λͺ…ν•˜λ©° 배경의 μ„ λ§Œμ„ sky_blueμƒ‰μ˜ 8dp둜 ν…Œλ‘λ¦¬λ₯Ό κ·Έλ¦¬λŠ” κ²½μš°λŠ”Β bg_stroke_sky_blue_radius_8dp.xml둜 ν•œλ‹€.
  • μ˜ˆμ‹œ
    • btn_call_normal.png: μ „ν™”κ±ΈκΈ° λ²„νŠΌ 이미지
    • btn_call_pressed.png: μ „ν™”κ±ΈκΈ° λ²„νŠΌ λˆŒλ Έμ„λ•Œμ˜ 이미지
    • btn_call.xml: μ „ν™”κ±ΈκΈ° λ²„νŠΌ μ΄λ―Έμ§€μ˜ selector xml
    • ic_dealer_gift.png: λ”œλŸ¬κ°€ 보내쀀 κΈ°ν”„ν‹°μ½˜μ„ λ³΄μ—¬μ€„λ•Œ ν‘œμ‹œλ˜λŠ” 이미지
    • img_splash_chart.png: μŠ€ν”Œλž˜μ‹œ ν™”λ©΄μ—μ„œ λ³΄μ—¬μ§€λŠ” 차트 이미지

λ ˆμ΄μ•„μ›ƒ prefix

  • item_<what>: λ¦¬μ‚¬μ΄ν΄λŸ¬ λ·° μ•„μ΄ν…œ λ ˆμ΄μ•„μ›ƒμ— μ‚¬μš©
  • view_<what>: μ»€μŠ€ν…€ λ·° λ ˆμ΄μ•„μ›ƒμ— μ‚¬μš©

λ¦¬μ†ŒμŠ€ 넀이밍

Color

<!--color λ¦¬μ†ŒμŠ€ 정리-->
<color name="light_gray">#E4E4E4</color>
<color name="gray">#8D8D8D</color>
<color name="gray_alpha_30">#30000000</color>

<!--색 λ³€μˆ˜ wHeRe_wHAt. μ—¬λŸ¬ κ³³μ—μ„œ μ‚¬μš©λœλ‹€λ©΄ where μƒλž΅ κ°€λŠ₯.-->
<color name="saveSchedule_titleText">@color/light_gray</color>
<color name="yearCalendarView_titleText">@color/gray</color>
<color name="close_background">@color/gray_alpha_30</color>

description은 ν…Œλ§ˆ μ†μ„±μœΌλ‘œ 뢄리

<item name="titleTextColor">@color/yellow_500</item>

λ ˆμ΄μ•„μ›ƒμ—μ„œ μ‚¬μš©μ€ ν…Œλ§ˆ 속성을 μ°Έμ‘°

 style="@style/Theme.titleTextColor"

Dimensions μ»¨λ²€μ…˜

Mnemonic μ‚¬μš©

κ°€μž₯ 일반적인 margin/padding 16dp = β€˜μΌλ°˜ 치수 크기의 100% μ‚¬μš©β€™

<dimen name="small_25">2dp</dimen>
<dimen name="small_50">4dp</dimen>
<dimen name="small_100">8dp</dimen>   <!-- 50% of normal = 8dp -->

<dimen name="normal_100">16dp</dimen> <!-- 100% of normal = 16dp --> <dimen name="normal_125">20dp</dimen> <!-- 125% of normal = 16dp + 4dp = 20dp --> <dimen name="normal_150">24dp</dimen> <dimen name="normal_175">28dp</dimen>

<dimen name="large_100">32dp</dimen> <!-- large_100 = 2 x normal_100 --> <dimen name="large_125">40dp</dimen> <dimen name="large_150">48dp</dimen> <dimen name="large_175">56dp</dimen> <dimen name="large_200">64dp</dimen>

일반 μΉ˜μˆ˜μ— λΉ„ν•΄ 훨씬 큰 dimensions의 경우

  • κΈ°λ³Έ ν˜•μ‹ : [what]_[where]_[des]_[size] ex) keyline_all_text
<dimen name="size_selectVideo_player">500dp</dimen>

<WHAT>

Prefix Usage
width width in dp
height height in dp
size if width == height
margin margin in dp
padding padding in dp
elevation elevation in dp
keyline absolute keyline measured from view edge in dp
textsize size of text in sp

Android - Dimensions by Conventions

Style 넀이밍

  • μΉ΄λ©œμΌ€μ΄μŠ€
  • κΈ°λ³Έ ν˜•μ‹:Β [des][View]Β ex) customText
<style name="selectVideoOptionImage" parent="Widget.AppCompat.ImageButton">
    <item name="android:layout_width">@dimen/large_125</item>
    <item name="android:layout_height">@dimen/large_125</item>
    <item name="elevation">@dimen/small_25</item>
    <item name="android:padding">@dimen/small_100</item>
</style>

Style resource | Android Developers

μ½”ν‹€λ¦° μ»¨λ²€μ…˜

클래슀 λͺ…

λ‹¨μ–΄μ˜ 첫 κΈ€μžλ§Œ upper case

class Person
class User

ν”„λ‘œνΌν‹°

1 λŒ€ 1 관계면 viewModel

1λŒ€1 λ‹€ 관계면 ν’€λ„€μž„

val viewModel: AddTaskViewModel by viewModels()
val activityViewModel: MainViewModel by viewModels()
val addTakAdapter = AddTaskAdapter()

ν•¨μˆ˜ λͺ…

μ½”ν‹€λ¦° 곡식 λ©”μ†Œλ“œ 넀이밍

첫 단어λ₯Ό μ œμ™Έν•œ 단어뢀터 λ‹¨μ–΄μ˜ 첫 κΈ€μžλ§Œ upper case

동사 ν˜Ήμ€ 동사ꡬ(λ™μ‚¬λ‘œ μ‹œμž‘)

fun getPersonId() {}
fun getUserId() {}

클래슀 λ‚΄λΆ€ ν•¨μˆ˜ 배치 μˆœμ„œ

  • ν”„λ‘œνΌν‹°
  • μƒμ„±μž
  • init
  • onCreate
  • onCreateView
  • ν•¨μˆ˜
  • onDestroy
  • companion object
interface Example{
    // 띄기
    fun A()
    
    fun B()
    
    fun C()
    // 띄기
}

class D(
    a,
    b,
    c // 140 space λ§žμΆ°μ„œ (Arrange Option λ³€κ²½ν•˜κΈ°)
) : B {
    // 띄기
    private val _binding
    private val binding = get() = _binding
    
    private val viewModel by viewModels{}
    
    private lateinit var
    
    private val a = 3
    
    init {
        
    }
    
    override onCreate()
    
    private fun()
    
    override onDestroy()
    
    inner class C() {
        
    }
    
    companion object {
        
    }
}

ν•¨μˆ˜ νŒŒλΌλ―Έν„°

//single Event
class Adapter(val onClick : (String) -> Unit)

//Multiple Event
class Adapter(val onClick : MinSeokOnClickListener)

fun interface MinSeokOnCLickListener {
    
    fun onClick(str : String)
    
    fun onLongClick(str : String)
    
}

val onclickListener = object: MinSeokOnCLickListener {
    fun onClick(str : String) {
    
    }
    
    fun onLongClick(str : String) {
    
    }
}

Adapter(onclickListener)

Adapter(::onClick) // 3쀄 이상 뢄리
Adapter {
    Log.d("asd", it)
} // 2쀄 이내 μ‚¬μš©

Enum

[What]Type

Sealed

NetworkState(= retrofit Result) MultipleViewType

scope ν•¨μˆ˜

apply, also, with, let, run

  • Scope 쀑첩 지양(μ΅œλŒ€ 2쀑첩)
  • it 지양 (λ‹€λ₯Έ μ΄λ¦„μœΌλ‘œ μ„ μ–Έν•΄μ„œ μ“°κΈ°)

ν•¨μˆ˜λͺ… prefix

비동기 ν•¨μˆ˜

  • fetch: Read
  • post : Write view(viewModel.fetchData) -> viewModel(repo.fetchData) -> repo(source.fetchData)

μΆ”κ°€

  • add: list μ•ˆμ— 넣을 λ•Œ
  • create: μƒˆλ‘œ 생성

쑰회

  • get: any
  • find: nullable any
  • is, has: boolean

ν™”λ©΄μ „ν™˜

  • show[Dialog]
  • start[Activity]
  • navigate[Fragment]

ν™”λ©΄ κ°±μ‹ 

  • show
  • invalidate

if문

else if μ‚¬μš© κΈˆμ§€ -> when으둜 λ³€ν™˜ else도 지양 κ³ λ € μ€‘κ΄„ν˜Έ 무쑰건 μ“°κΈ°

// μ€‘κ΄„ν˜Έ ν™•μ‹€νžˆ μ‚¬μš©ν•˜κΈ°
if (true) {
    foo()
} else {
    bar()
}

// else 지양 
⬇️
bar()
if (true) {
    foo()
}

when문

// μžλ™ μ •λ ¬ μ‚¬μš©ν•˜κΈ°
when {
    aaa -> {
        
    }
    
    bbb -> {
        
    }
}

// 2쀄 이상은 μ€‘κ΄„ν˜Έ λ‚΄μ—μ„œ, 1쀄은 μ€‘κ΄„ν˜Έ x
when {
    aaa -> foo()
    bbb -> bar()
}

// early return
// else 문을 미리 when μœ„μ— λΉΌμ„œ return μ‹œν‚€κΈ° (else blockμ—μ„œ μ²˜λ¦¬ν•  것이 없을 λ•Œ)
val xxx = ... ?: return
when(target) {
		aaa -> {}
		bbb -> {}
}

navigate

ShoppingFragment -> ShoppingDetailFragment 
// 1. ShoppingFragment with Safe Args
override fun navigateToShoppingDetail(shoppingItemInfo: ShoppingItemInfo) {
        val navAction = ShoppingFragmentDirections.actionShoppingFragmentToDetailFragment(shoppingItemInfo)
        findNavController().navigate(navAction)
    }

// 2 ShoppingDetailFragment 
class ShoppingDetailFragment : Fragment(), ShoppingItemOnClickListener {
    private val args: ShoppingDetailFragmentArgs by navArgs()
    private val shoppingItemInfo : ShoppingItemInfo by lazy { args.shoppingItemInfo }

override fun onCreateView(...){...}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
     super.onViewCreated(view, savedInstanceState)
	   Log.d("shoppingItemInfo",shoppingItemInfo.toString()) // μ‚¬μš©
    }

μƒμˆ˜

resource -> 화면에 λ³΄μ΄λŠ”κ°€λ₯Ό κΈ°μ€€μœΌλ‘œ string.xml에 뢄리 κ²°μ •

  • ex: EXTRA_TITLE_ID = "title_id" μƒμˆ˜ 넀이밍은 upper snake case

의미 μžˆλŠ” 숫자, λ¬Έμžμ—΄μ€ companion에 const val μ„ μ–Έ

  • ex: LOOP_COUNT = 10

λ„€νŠΈμ›Œν¬ response 객체 Entity 맀핑 방식

  • from ⭐

ν…ŒμŠ€νŠΈ ν•¨μˆ˜ 넀이밍

  • ν•œκ΅­μ–΄, snake case
instrument ok
fun `일정을_잘λͺ»_κ°€μ Έμ˜¬_λ•Œ`()

Git μ»¨λ²€μ…˜

Feature 브랜치 넀이밍

Issue #<number> type: subject

body(option)

footer(option)

Type

  • feat:Β μƒˆλ‘œμš΄ κΈ°λŠ₯
  • fix: 버그 μˆ˜μ •
  • docs:Β README, gitignore 주석 μˆ˜μ •
  • refactor:Β μ½”λ“œ λ¦¬νŒ©ν„°λ§
  • test:Β ν…ŒμŠ€νŠΈ μ½”λ“œκ°€ μΆ”κ°€λ˜κ±°λ‚˜ λ¦¬νŒ©ν„°λ§ μ‹œ μ‚¬μš©ν•˜λ©° ν”„λ‘œλ•μ…˜ μ½”λ“œλŠ” λ³€κ²½λ˜μ§€ μ•ŠλŠ”λ‹€.
  • chore:Β ν”„λ‘œμ νŠΈ ν™˜κ²½μ„€μ • λ³€κ²½, λΉŒλ“œ ꡬ성 λ³€κ²½ 등에 μ‚¬μš©λ˜λ©° ν”„λ‘œλ•μ…˜ μ½”λ“œλŠ” λ³€κ²½λ˜μ§€ μ•ŠλŠ”λ‹€.
  • res

β†’ μ†Œλ¬Έμž:

Subject

  • 50자 이내
  • ꡬ어체/λ¬Έμž₯ν˜• X, λͺ…λ Ήν˜•μœΌλ‘œ μž‘μ„±
  • λ§ˆμΉ¨ν‘œ μ‚¬μš© λΆˆκ°€

Body(Option)

  • μƒλž΅ κ°€λŠ₯
  • 72자 이내
  • μ–΄λ–€(What) μž‘μ—…μΈμ§€, μž‘μ—…μ˜ λͺ©μ (Why)에 λŒ€ν•΄ μž‘μ„±. μž‘μ—…μ„ ν•΄κ²°ν•œ 방식(How)은 μž‘μ„± X

Footer(Option)

Push/PR Issue μ—°κ²°

  • Issue Tracker ID ν‘œμ‹œ
  • Issue Tracker 유
    • Fixes: 이슈 μˆ˜μ •μ€‘ (아직 ν•΄κ²°λ˜μ§€ μ•Šμ€ 경우)
    • Resolves: 이슈λ₯Ό ν•΄κ²°ν–ˆμ„ λ•Œ μ‚¬μš©
    • Ref: μ°Έκ³ ν•  μ΄μŠˆκ°€ μžˆμ„ λ•Œ μ‚¬μš©
    • Related to: ν•΄λ‹Ή 컀밋에 κ΄€λ ¨λœ 이슈번호 (아직 ν•΄κ²°λ˜μ§€ μ•Šμ€ 경우)

Issue & PR 곡톡 사항

라벨 달기(chore, bug, fix, feature, docs, help wanted, wrong, question)
- project달기
- Milestone 달기
- asignees 지정

PR ν…œν”Œλ¦Ώ

# PR λ‚΄μš©

...μž‘μ—… λ‚΄μš©...

Issue ν…œν”Œλ¦Ώ

# 진행 상황

...체크포인트...

μ°Έκ³  url
Clone this wiki locally