Essential Kotlin Coding Standards for Android: Clean Architecture, MVI & Best Practices
Master Android development with rewritten Kotlin rules emphasizing clean code, SOLID principles, MVI patterns, repository design, and comprehensive testing for robust, scalable apps.
### Context
As a seasoned Kotlin developer specializing in Android, adhere to these guidelines to produce maintainable, efficient code. They promote clean architecture, explicit typing, immutability, and single-responsibility principles, ensuring high-quality apps using ViewBinding, Navigation Component, and Material 3.
### Rules
#### Core Kotlin Principles
- Write all code and comments in English.
- Explicitly specify types for variables, parameters, and return values.
- Steer clear of `Any` type; define custom types instead.
- Eliminate empty lines inside functions.
#### Naming Conventions
- Classes: PascalCase (e.g., UserRepository).
- Variables, methods, functions: camelCase (e.g., fetchUserData).
- Files and directories: snake_case (e.g., user_repository.kt).
- Constants and env vars: UPPERCASE (e.g., MAX_RETRIES).
- No magic numbers; use named constants.
- Functions start with action verbs (e.g., processPayment).
- Booleans: use verbs like isValid, hasData, canSubmit.
- Full words, proper spelling; allow standard acronyms (API, URL) and loop vars (i, j), error shorthand (err), context (ctx), middleware (req, res, next).
#### Function Design
- Keep functions concise (<20 lines), single-purpose.
- Name with verb + descriptor (e.g., validateEmail, saveUserProfile).
- Booleans: isValidEmail, hasNetworkConnection.
- Void functions: executeQuery, updateCache.
- Minimize nesting via early returns, guard clauses, helper functions, or higher-order funcs (map, filter).
- Arrow funcs for tiny logic (<3 lines); named for complex.
- Favor default params over null checks.
- Limit params with data objects (RO-RO pattern); return structured objects.
- Enforce single abstraction level.
#### Data Handling
- Data classes for plain data.
- Wrap primitives in types; avoid raw ints/strings.
- Validate in dedicated classes, not functions.
- Prioritize immutability: use `val` for constants.
#### Class Structure
- Uphold SOLID: single responsibility, open-closed, etc.
- Composition > inheritance.
- Interfaces for contracts.
- Compact classes: <200 lines, ≤10 public methods/properties.
#### Error Management
- Exceptions for unforeseen issues only.
- Catch to resolve known issues or enrich context; else, use global handlers.
#### Testing Practices
- Unit tests: Arrange-Act-Assert; vars like inputData, mockRepo, actualResult, expectedResult.
- Test every public method with mocks (skip cheap third-party).
- Acceptance tests per module: Given-When-Then.
#### Android-Specific Rules
- Clean Architecture: repositories for data, caching strategies.
- State mgmt: MVI in ViewModels; Flows/LiveData for UI updates.
- Auth flow: Splash → Login/Register/Forgot/Verify in dedicated Activity.
- Navigation: Component for screens; MainActivity hosts BottomNavigationView (Home, Profile, Settings, Patients, Appointments).
- Views: ViewBinding, XML/Fragments (no Compose), ConstraintLayout, Material 3.
- Testing: Widget tests, integration for APIs.
### Examples
**Naming & Functions:**
```kotlin
class UserRepository {
fun fetchUserProfile(userId: String): Result<UserProfile> = // ...
fun isUserActive(userId: String): Boolean = // early return if invalid
}
```
**Data Class:**
```kotlin
data class UserProfile(val id: String, val name: String) // immutable
```
**Android ViewModel (MVI):**
```kotlin
class ProfileViewModel(private val repo: UserRepository) : ViewModel() {
private val _uiState = MutableStateFlow(ProfileState())
val uiState: StateFlow<ProfileState> = _uiState.asStateFlow()
fun loadProfile(userId: String) {
viewModelScope.launch {
repo.fetchUserProfile(userId).fold(
onSuccess = { _uiState.update { it.copy(profile = it, isLoading = false) } },
onFailure = { _uiState.update { it.copy(error = it.message, isLoading = false) } }
)
}
}
}
```
**Test Example (AAA):**
```kotlin
@Test
fun `fetchUserProfile returns success`() {
// Arrange
val mockRepo = mock<UserRepository>()
whenever(mockRepo.fetchUserProfile(any())).thenReturn(Result.success(mockUser))
val viewModel = ProfileViewModel(mockRepo)
// Act
viewModel.loadProfile("123")
// Assert
assertEquals(mockUser, viewModel.uiState.value.profile)
}Comments
More Rules
View allGLM-4.7 Optimized Config & System Prompt Designer
Expert system prompt for designing high-performance configurations tailored to GLM-4.7's strengths in coding, reasoning, tool use, and multilingual tasks, backed by benchmarks like SWE-bench and τ²-Bench.
GLM-4.7 Open-Source Coding Expert: Optimized System Prompt
Leverage GLM-4.7's top benchmarks in SWE-bench, LiveCodeBench, and more with this system prompt designed for generating clean, secure, open-source-ready code, stunning UIs, and agentic workflows.
GLM-4.7 Optimized Coding Agent
This system prompt transforms an AI into GLM-4.7, a benchmark-leading coding agent excelling in agentic workflows, tool use, multilingual coding, and complex reasoning with verified best practices for production-ready open-source development.
Agentic Dev Loop: Autonomous Jira-Driven Coding Agent with GitHub CI Self-Healing
Ralph, a persistent autonomous AI agent, implements Jira tickets through an endless loop until 100% test success, with GitHub PRs, Jules AI reviews, and CI self-healing for reliable development workflows.
Türk Hukuku Uzmanı AI Agent: Güvenilir Yasal Danışman System Prompt
Claude'u Türk hukuku alanında dünyanın en önde gelen uzmanı olarak yapılandıran, yapılandırılmış yanıtlar, zorunlu uyarılar ve etik sınırlarla donatılmış profesyonel AI agent promptu.
PostgreSQL Best Practices: Expert Subagent Guide
Expert subagent providing production-ready PostgreSQL guidance on schema design, query optimization, security, performance tuning, and administration with structured, actionable advice and official references.