Kotlin Coding Standards
Conventions for clean, idiomatic, safe Kotlin. Reference when writing or reviewing Kotlin code.
Style & Naming
- Follow the official Kotlin coding conventions.
PascalCasefor types,camelCasefor functions/properties,UPPER_SNAKE_CASEfor compile-time constants.- Prefer descriptive names over comments. Names should make intent obvious.
- Keep functions short and single-purpose. If a function needs a section comment, consider extracting it.
Null Safety
- Embrace non-null types. Avoid
!!— it defeats the purpose of Kotlin's null safety. - Use
?.,?:,let, andrequireNotNull/checkNotNull(with messages) instead of force unwraps. - Model "absence" explicitly with nullable types or sealed results, not sentinel values.
Immutability & Data
- Prefer
valovervar. Prefer immutable collections (List,Map) over mutable ones in public APIs. - Use
data classfor value-holding types; usecopy()for derived state. - Use
sealed class/sealed interfacefor closed type hierarchies (e.g., UI state, results). They makewhenexhaustive and self-documenting. - Use
enum classfor fixed sets of constants (the reference design uses these well:SessionStatus,FlagReason, etc.).
Functions & Expressions
- Favor expression bodies for simple functions:
fun total() = qty * price. - Use default and named arguments instead of overloads.
- Use extension functions to add focused behavior without inheritance — but keep them discoverable.
- Use scope functions (
let,run,apply,also,with) intentionally; don't nest them into unreadable chains.
Error Handling
- Use exceptions for truly exceptional cases; use sealed result types (
Result<T>or a customsealed interface) for expected failure paths (e.g., upload failed, match not found). - Always include a message in
require/check/error. - Never swallow exceptions silently. Log with context (session id, page number) as the reference error-handling design specifies.
Coroutines & Concurrency
- Respect structured concurrency: launch in a defined scope (
viewModelScope,coroutineScope). - Inject dispatchers (don't hardcode
Dispatchers.IO) so code is testable. - Make suspend functions main-safe: a suspend function should be safe to call from the main thread and switch dispatchers internally as needed.
- Use
Flowfor streams; keep operators pure and side-effect-free except in terminal operators.
Money & Numbers
- Use
BigDecimalfor monetary values (the reference design does this for line totals and order totals). Never useFloat/Doublefor money. - Be explicit about rounding mode and scale when comparing computed vs printed totals.
Dependency Injection
- Use Hilt for DI on Android. Constructor-inject dependencies; avoid service locators and global singletons.
- Inject interfaces, not concrete classes, so components are swappable and testable.
Documentation
- Use KDoc for public APIs and non-obvious behavior. Document the "why," not the "what."
- Keep interface contracts (like those in the reference design) documented so JSON/boundary contracts stay clear across languages.