kotlin
Clean Architecture, project structure, and patterns for pure Kotlin modules.
安装与使用
请根据来源仓库和你的 AI 工具说明安装此技能。先阅读技能文件和依赖要求,再添加到工作流。
查看来源 ↗使用指南技能说明
Kotlin & KMP Architecture Standards
Use this skill for pure Kotlin or Kotlin Multiplatform modules where clean boundaries and testable async code matter.
1. Clean Architecture Rules (Domain Layer)
When writing Kotlin business logic (Core/Domain modules):
-
UseCases (Interactors):
- A UseCase MUST contain only one public function:
fun execute(): Result<T>. - Do NOT use
operator fun invoke. - UseCases MUST always return a Kotlin
Result<T>(success or failure) to explicitly model outcomes. - UseCases can depend on other UseCases or Repositories.
- Any external
HelperorManagerMUST be injected into the UseCase, not the Repository.
- A UseCase MUST contain only one public function:
-
Repositories and DataSources:
-
Repositories return raw data types (e.g.,
User,List<Item>), NOTResult<T>. The UseCase handles error mapping intoResult. - Repositories depend ONLY on DataSources. A Repository MUST NOT depend on another Repository.
- DataSources depend only on external APIs/DBs. A DataSource MUST NOT depend on another DataSource.
- Prefer concrete classes for Repositories unless multi-platform swapping (expect/actual) or strict test mocking requires an
interface.
-
Repositories return raw data types (e.g.,
-
Dependency Graph:
-
UI/Component->UseCase->Repository->DataSource
-
2. Kotlin Language Patterns
-
Coroutines & Flow:
- Prefer
suspendfunctions for one-shot async operations andFlowfor streams of reactive data. -
Dispatcher Injection: NEVER hardcode
Dispatchers.IOorDispatchers.Defaultinside UseCases or Repositories. Pass them via constructor injection so they can be easily replaced withUnconfinedTestDispatcherin unit tests. -
Structured Concurrency: Prefer
coroutineScopeandsupervisorScopeoverGlobalScope. Never launch unmanaged coroutines. -
Context-Preservation (Safe Suspend): A
suspendfunction should be safe to call from any dispatcher (main-safe). If a function performs blocking I/O, it MUST shift its own execution context internally usingwithContext(dispatcher). -
Coroutine Error Handling:
-
Never swallow
CancellationException. If catching a genericExceptioninside a coroutine, explicitly check and rethrowCancellationExceptionto avoid breaking structured concurrency and memory leaks. - Use
CoroutineExceptionHandlerexclusively for uncaught exceptions in root coroutines (launch). Note that it does NOT work forasync(where exceptions are deferred untilawait()).
-
Never swallow
- Prefer
-
Scope Functions: Avoid excessive or nested scope functions (
run,also,apply,let). Only use them when they significantly improve readability. -
Serialization: Prefer
kotlinx.serializationover Jackson/Gson for multiplatform readiness. -
Networking (Ktor): Prefer Ktor Client for HTTP requests in KMP projects. Use
ContentNegotiationwithkotlinx.serializationfor JSON parsing. Define separate request/response DTOs rather than exposing domain models directly to the network layer. -
Error Handling Boundary: Do NOT leak raw Exceptions to the UI. The
Result<T>from a UseCase must be mapped by the ViewModel/Component into a precise, UI-friendly Error State or a One-Time UI Event. - Compiler & API: Use the K2 Compiler defaults. Enable Explicit API mode in core modules (require explicit visibility and return types) to reduce LLM/IDE inferencing errors.
3. Project Structure
- Prefer a Multi-Module Gradle (Kotlin DSL) setup (
build.gradle.kts). - Use Version Catalogs (
gradle/libs.versions.toml) for all dependencies and plugins. - Separate
core(pure Kotlin, no framework dependencies) from framework-specific modules (likeapp,backend,android, etc.).
使用示例
查看来源仓库中的使用示例与配置说明。
查看来源 ↗来源历史
- 收录时间
- 2026-03-11
- 索引更新时间
- 2026-03-11
- Branch
- main
收录与同步日期属于本站记录。源码修改历史请查看来源仓库。
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!