Claude-skill-registry android-conventions

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/android-conventions" ~/.claude/skills/majiayu000-claude-skill-registry-android-conventions && rm -rf "$T"
manifest: skills/data/android-conventions/SKILL.md
source content

Android Coding Conventions

프로젝트 코딩 컨벤션 및 스타일 가이드입니다.

Naming Conventions

Classes and Interfaces

TypePatternExample
UseCase
{Action}{Subject}UseCase
GetLottoResultUseCase
Repository Interface
{Subject}Repository
LottoRepository
Repository Impl
{Subject}RepositoryImpl
LottoRepositoryImpl
ViewModel
{Feature}ViewModel
HomeViewModel
Contract
{Feature}Contract
HomeContract
Screen
{Feature}Screen
HomeScreen
Content
{Feature}Content
HomeContent
DataSource
{Subject}{Type}DataSource
LottoRemoteDataSource
DTO
{Subject}Dto
LottoDto
Entity
{Subject}Entity
LottoEntity

Functions

TypePatternExample
UseCase invoke
operator fun invoke()
suspend operator fun invoke(round: Int)
Event handler
on{Action}
onRefresh()
,
onItemClick()
Private helper
{action}{Subject}
loadData()
,
updateState()
Mapper
to{Target}()
toEntity()
,
toDomain()

Variables

TypePatternExample
StateFlow
_uiState
/
uiState
Private mutable / Public immutable
Channel
_effect
/
effect
Private / Public
Boolean
is{State}
,
has{Thing}
isLoading
,
hasError
CollectionPlural nouns
items
,
results
,
numbers

Modules

feature:{feature-name}    # feature:home, feature:qrscan
core:{core-name}          # core:domain, core:data, core:network

Forbidden Patterns

🚫 절대 사용 금지

PatternReasonAlternative
LiveData
Deprecated pattern
StateFlow
AsyncTask
DeprecatedCoroutines
GlobalScope
Memory leak risk
viewModelScope
runBlocking
(production)
Blocks thread
suspend
+ coroutines
findViewById
Old patternView Binding or Compose
XML layouts (new screens)Migration to ComposeJetpack Compose
Mutable collections (public)Immutability violationImmutable collections

Code Examples

// ❌ Don't
val items = mutableListOf<Item>()  // Public mutable
GlobalScope.launch { ... }
runBlocking { ... }

// ✅ Do
val items: List<Item> get() = _items.toList()  // Immutable copy
viewModelScope.launch { ... }
suspend fun doSomething() { ... }

Preferred Patterns

✅ 권장 패턴

PatternUsage
invoke
operator
UseCase entry point
Result<T>
Error handling
State hoistingCompose state management
Immutable data classDomain models
suspend
functions
One-shot operations
Flow
Data streams
Modifier
first optional
Composable parameters

Code Examples

// ✅ UseCase with invoke
class GetDataUseCase @Inject constructor(...) {
    suspend operator fun invoke(id: String): Result<Data> = ...
}

// ✅ Result type for errors
suspend fun getData(): Result<Data> = runCatching {
    repository.fetchData()
}

// ✅ Immutable data class
data class LottoResult(
    val round: Int,
    val numbers: List<Int>,  // List is immutable interface
    val bonusNumber: Int
)

// ✅ Modifier as first optional parameter
@Composable
fun MyComponent(
    text: String,                    // Required
    modifier: Modifier = Modifier,   // First optional
    enabled: Boolean = true          // Other optionals
)

Architecture Rules

Layer Dependencies

✅ Allowed:
Presentation → Domain
Data → Domain

❌ Forbidden:
Domain → Data
Domain → Presentation
Presentation → Data (direct)

Module Dependencies

✅ Allowed:
feature:* → core:domain
feature:* → core:di
core:data → core:domain
core:data → core:network
core:data → core:database

❌ Forbidden:
core:domain → core:data
core:domain → core:network
feature:home → feature:qrscan (direct)

Code Style

Imports

// ✅ Explicit imports (preferred)
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.MutableStateFlow

// ⚠️ Star imports (avoid when possible)
import kotlinx.coroutines.flow.*

Formatting

// ✅ Parameter on new line when many
fun createViewModel(
    useCase1: UseCase1,
    useCase2: UseCase2,
    repository: Repository
): ViewModel

// ✅ Chain calls vertically
repository.getData()
    .map { it.toDomain() }
    .catch { emit(emptyList()) }
    .collect { ... }

Comments

// ✅ KDoc for public APIs
/**
 * Fetches lotto result for the given round.
 *
 * @param round The round number to fetch
 * @return Result containing LottoResult or error
 */
suspend fun getLottoResult(round: Int): Result<LottoResult>

// ✅ Explain WHY, not WHAT
// Cache for 5 minutes to reduce API calls during rapid navigation
private val cache = CacheBuilder.newBuilder()
    .expireAfterWrite(5, TimeUnit.MINUTES)
    .build()

// ❌ Don't explain obvious code
// Increment counter by 1
counter++

Korean Market Specifics

Localization Formats

TypeFormatExample
Date
YYYY년 MM월 DD일
2024년 01월 15일
Time
오전/오후 HH:MM
오후 08:45
Currency
₩{amount:,}
₩1,000,000,000

Accessibility

  • Korean TTS pronunciation 고려
  • 문장 길이 ≤ 30자 권장
  • 명확한 동작 설명 (
    "로또 결과 새로고침"
    )

File Organization

feature/home/
├── HomeScreen.kt           # Screen composable
├── HomeViewModel.kt        # ViewModel
├── HomeContract.kt         # UiState, Event, Effect
├── navigation/
│   └── HomeNavigation.kt   # Navigation setup
└── components/
    ├── LottoResultCard.kt  # Reusable component
    └── NumberBall.kt       # Reusable component