chore: core 多模块骨架
This commit is contained in:
22
core/domain/DESIGN_NOTES.md
Normal file
22
core/domain/DESIGN_NOTES.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# DESIGN_NOTES — core:domain
|
||||
|
||||
## 为什么纯 Kotlin
|
||||
|
||||
`core:domain`(以及 `core:model`、`core:common`)用 `mcl.kotlin.library`(`org.jetbrains.kotlin.jvm`),**不依赖 Android**。这样:
|
||||
|
||||
- 业务规则(UseCase)不 import `android.*`,框架解耦,天然可移植。
|
||||
- 单元测试直接跑在 JVM 上(`./gradlew test`),快且稳定,无需 Robolectric/设备。
|
||||
|
||||
## 如何塑造 UseCase / Repository
|
||||
|
||||
- **UseCase**:单一动作的接口,`suspend operator fun invoke(input): Output`(见 `UseCase.kt`)。一个类一个动作,符合单一职责。
|
||||
- **Repository 接口**:定义在 `core:domain`(接口),实现在 `core:data`(`XxxRepositoryImpl`)。调用方只依赖接口,不依赖实现,便于用 fake 替换做测试。
|
||||
|
||||
## 依赖方向
|
||||
|
||||
`core:domain` 只依赖 `core:model` 与 `core:common`(都是纯 Kotlin)。**不要**让 domain 依赖 Android、网络、数据库——那是数据层的职责。
|
||||
|
||||
## 约定
|
||||
|
||||
- 需要协程时用 `kotlinx-coroutines-core`(`Flow` 等);不要在 domain 里用 Android 的 `LiveData`。
|
||||
- 状态/结果优先用 sealed class 表达。
|
||||
9
core/domain/build.gradle.kts
Normal file
9
core/domain/build.gradle.kts
Normal file
@@ -0,0 +1,9 @@
|
||||
plugins {
|
||||
alias(libs.plugins.mcl.kotlin.library)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.kotlinx.coroutines.core)
|
||||
testImplementation(libs.kotlinx.coroutines.test)
|
||||
testImplementation(libs.truth)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.mingyuan.android_client.core.domain
|
||||
|
||||
/**
|
||||
* Base contract for a single-action use case.
|
||||
*
|
||||
* Keeping use cases as plain interfaces with a `suspend operator invoke` keeps domain logic
|
||||
* framework-agnostic and trivially testable on the JVM (see [com.mingyuan.android_client.core.domain.UseCaseTest]).
|
||||
*/
|
||||
interface UseCase<in Input, out Output> {
|
||||
suspend operator fun invoke(input: Input): Output
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.mingyuan.android_client.core.domain
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class UseCaseTest {
|
||||
|
||||
@Test
|
||||
fun `invoke delegates to the implementation`() = runTest {
|
||||
val double = object : UseCase<Int, Int> {
|
||||
override suspend fun invoke(input: Int): Int = input * 2
|
||||
}
|
||||
|
||||
assertThat(double(21)).isEqualTo(42)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user