๐ Code Quality Guide
September 5, 2025 ยท View on GitHub
This document provides comprehensive guidelines for maintaining high code quality in the Thunderbird for Android project. Following these guidelines ensures that the codebase remains:
- Maintainable: Easy to understand, modify, and extend
- Reliable: Functions correctly and consistently
- Efficient: Uses resources effectively
- Secure: Protects user data and privacy
- Testable: Is verified through automated tests
๐ ๏ธ Static Analysis Tools
We use static analysis tools to automatically detect code quality issues and enforce standards.
Android Lint
Android Lint checks for potential bugs, optimization opportunities, and Android-specific issues:
# Run lint checks for all modules
./gradlew lint
# Run lint checks for a specific module
./gradlew :module-name:lint
Common issues detected:
- Unused resources
- Accessibility issues
- Performance optimizations
- Internationalization problems
- Security vulnerabilities
Configuration
The project's lint configuration is in config/lint/lint.xml. You can customize lint rules for specific modules by
adding a lint block to the module's build.gradle.kts file:
android {
lint {
abortOnError = false
warningsAsErrors = false
// Ignore specific issues
disable += listOf("InvalidPackage", "MissingTranslation")
// Enable specific issues
enable += listOf("RtlHardcoded", "RtlCompat", "RtlEnabled")
}
}
Detekt
Detekt analyzes Kotlin code for code smells, complexity issues, and potential bugs:
# Run detekt for all modules
./gradlew detekt
# Run detekt for a specific module
./gradlew :module-name:detekt
Detekt checks for:
- Code complexity (cyclomatic complexity, long methods, etc.)
- Potential bugs (empty blocks, unreachable code, etc.)
- Code style issues (naming conventions, formatting, etc.)
- Performance issues (inefficient collection operations, etc.)
Configuration
The project's Detekt configuration is defined in the config/detekt/detekt.yml file. This file specifies which rules
to apply and their severity levels. The detekt plugin is configured in the
build-plugin/src/main/kotlin/thunderbird.quality.detekt.gradle.kts file.
Spotless
Spotless ensures consistent code formatting across the codebase:
# Check if code formatting meets standards
./gradlew spotlessCheck
# Apply automatic formatting fixes
./gradlew spotlessApply
Spotless enforces:
- Consistent indentation
- Line endings
- Import ordering
- Whitespace usage
Configuration
The project's Spotless plugin is configured in the
build-plugin/src/main/kotlin/thunderbird.quality.spotless.gradle.kts file. We use ktlint for Kotlin formatting.
The rules are defined in the .editorconfig file and as editorconfig overrides in the Spotless configuration.
configure<SpotlessExtension> {
kotlin {
target(
"src/*/java/*.kt",
"src/*/kotlin/*.kt",
"src/*/java/**/*.kt",
"src/*/kotlin/**/*.kt",
)
ktlint(libs.versions.ktlint.get())
.setEditorConfigPath("${project.rootProject.projectDir}/.editorconfig")
.editorConfigOverride(
mapOf(
"ktlint_code_style" to "intellij_idea",
"ktlint_standard_function-signature" to "disabled",
),
)
}
}
For Markdown we use Flexmark and no further configuration is needed.
๐ Code Style Guidelines
Kotlin Style Guide
The project follows the Kotlin style guide with some project-specific adaptations:
- Naming Conventions:
- Use
camelCasefor variables, functions, and methods - Use
PascalCasefor classes, interfaces, enums and type parameters - Use
UPPER_SNAKE_CASEfor constants and enum constants - Prefix interface implementations with
Defaultor a specific name, e.g.: DefaultEmailRepositoryimplementsEmailRepositoryInMemoryCacheimplementsCache
- Use
- Formatting:
- Use 4 spaces for indentation
- Limit line length to 120 characters
- Use
./gradlew spotlessApplyto enforce formatting automatically
- Comments:
- Use KDoc comments for public APIs
- Include a summary, parameter descriptions, and return value description
- Document exceptions that might be thrown
- File Organization:
- One class per file (with exceptions for related small classes)
- Package structure should reflect the module structure
- Imports should be organized alphabetically
Kotlin Best Practices
- Prefer
val(immutable) overvarwhen possible - Use null-safety (
?.,?:,requireNotNull,checkNotNull) - Use extension functions to enhance existing classes
- Leverage Kotlin's functional programming features (
map,filter, etc.) for cleaner code - Use
data classesfor model objects - Implement 'sealed classes' for representing finite sets of options
- Use
coroutinesfor asynchronous operations - Use
flowfor reactive programming
Android Best Practices
- Follow the Android app architecture guidelines
- Use Jetpack libraries when appropriate
- Manage lifecycle properly (
ViewModel,LifecycleOwner) - Handle configuration changes (rotation, locale, dark mode)
- Optimize for different screen sizes and orientations
- Follow Material 3 design guidelines
๐ Security Practices
Security is critical. Always:
- Validate all input
- Avoid logging sensitive data
- Use HTTPS/TLS for all network traffic
- Store secrets securely (e.g., Android Keystore, EncryptedSharedPreferences)
- Apply least privilege to permissions
- Follow Androidโs security best practices
๐งช Testing
Comprehensive testing is a critical aspect of code quality.
Key expectations:
- Write tests for new/changed code
- Use meaningful, deterministic tests
- Follow ArrangeโActโAssert pattern
- Maintain high coverage
๐ See Testing Guide for frameworks, patterns, and CI coverage rules.
๐ Continuous Integration
The project uses GitHub Actions for continuous integration. Each pull request triggers automated checks for:
- Build success
- Test execution
- Lint issues
- Detekt issues
- Spotless formatting
The CI configuration is defined in the .github/workflows directory. The main workflow file is android.yml, which
defines the CI pipeline for Android builds.
๐ See Code Review Guide for PR expectations and etiquette.