要实现高质量的 Kotlin 全栈开发,最佳实践是将 Compose Multiplatform 的跨平台 UI 能力、Android Clean Architecture 的分层架构与 Ktor 的轻量级 HTTP 服务模式系统性结合。本文将基于 Everything Claude Code 的技能体系,拆解从 UI 状态管理到服务端测试的完整工作流,帮助你在 AI 编程助手的协作下,构建可维护、可测试的现代化应用。

KMP 跨平台与 Ktor 服务端:Compose UI、Clean Architecture 与 HTTP 服务最佳实践

在采用 Kotlin Multiplatform (KMP) 进行全栈开发时,开发者常面临三重挑战:如何编写可复用、可测试的跨平台 UI?如何设计清晰、解耦的业务架构?以及如何搭建健壮、可测的后端服务?孤立地解决这些问题往往导致技术栈割裂,维护成本攀升。借助 Everything Claude Code 提供的 compose-multiplatform-patternsandroid-clean-architecturekotlin-ktor-patterns 三个核心 Skill,你可以在 AI 编程助手的协同下,系统性地落地一套从前端到后端的标准化工程实践。

1. 统一基石:以 Clean Architecture 分层驱动全栈开发

在启动一个全栈 KMP 项目时,首要任务是确立清晰的模块边界与依赖规则。android-clean-architecture Skill 定义了标准的分层结构,这是整个应用的骨架。

标准模块结构示例:

project/
├── shared/        # 多平台共享代码(domain, data)
│   ├── domain/    # UseCase、领域模型、Repository接口 (纯 Kotlin)
│   └── data/      # Repository实现、数据源(本地/网络)
├── composeApp/    # Compose Multiplatform UI 模块 (presentation)
├── server/        # Ktor 服务端应用 (可选独立模块)
└── buildSrc/      # 共享构建逻辑

核心依赖规则:

  • domain 层是纯 Kotlin 模块,不依赖任何框架(包括 Compose、Ktor)。
  • data 层实现 domain 定义的接口,可依赖 Room、SQLDelight 或 Ktor Client。
  • composeApp(presentation)依赖 domain,通过 UseCase 获取数据,绝不直接访问 data
  • server 模块拥有自己的分层(routes, services, repositories),但共享 domain 中的领域模型。

这个结构由 AI 根据 Skill 自动初始化和维护,确保业务逻辑(如 GetItemsUseCase)在前后端可复用,且依赖关系清晰。

2. Compose Multiplatform UI:状态管理、导航与平台适配

composeApp 模块中,compose-multiplatform-patterns Skill 指导 AI 生成可预测、可测试的 UI 代码。

Step 1:采用单一状态对象与 ViewModel AI 会为每个界面生成一个 data class 状态和一个 ViewModel,通过 StateFlow 暴露状态。

// 由 AI 生成于 presentation 层
data class HomeUiState(
    val items: List<ItemUiModel> = emptyList(),
    val isLoading: Boolean = false
)

class HomeViewModel(
    private val getItems: GetItemsUseCase // 来自 domain 层
) : ViewModel() {
    private val _uiState = MutableStateFlow(HomeUiState())
    val uiState: StateFlow<HomeUiState> = _uiState.asStateFlow()

    fun loadItems() {
        viewModelScope.launch {
            _uiState.update { it.copy(isLoading = true) }
            getItems().collect { result ->
                _uiState.update { it.copy(isLoading = false, items = result.map { it.toUiModel() }) }
            }
        }
    }
}

Step 2:在 Composable 中安全收集状态并设计事件处理 使用 collectAsStateWithLifecycle() 确保生命周期安全,并采用 sealed interface 定义事件。

@Composable
fun HomeScreen(viewModel: HomeViewModel = koinViewModel()) {
    val state by viewModel.uiState.collectAsStateWithLifecycle()

    HomeContent(
        state = state,
        onEvent = viewModel::onEvent // onEvent 处理 sealed interface 事件
    )
}

Step 3:实现类型安全导航 AI 会使用 @Serializable 注解的路由对象,取代容易出错的字符串路由。

@Serializable data object HomeRoute
@Serializable data class DetailRoute(val itemId: String)

// 在 NavHost 中
composable<HomeRoute> { /* ... */ }
composable<DetailRoute> { backStackEntry ->
    val route = backStackEntry.toRoute<DetailRoute>()
    // 安全地获取 itemId
}

3. Ktor 服务端:模块化路由、依赖注入与测试

对于后端服务,kotlin-ktor-patterns Skill 确保 Ktor 应用模块化且易于测试。

Step 1:将路由与插件配置拆分为独立函数 AI 会生成清晰的项目结构,配置代码不杂糅在入口。

// 由 AI 生成于 server 模块
fun Application.module() {
    configureSerialization() // 配置 kotlinx.serialization
    configureDI()            // 配置 Koin
    configureRouting()       // 配置路由
}

fun Application.configureRouting() {
    routing {
        route("/api") {
            itemRoutes() // 来自另一个文件的路由扩展函数
            healthRoutes()
        }
    }
}

Step 2:使用 Koin 进行依赖注入 无论是 UI 层的 ViewModel 还是服务端的 Service,Koin 都能提供统一的 DI 体验。

// 共享的 Koin 模块(可在 common 中定义,各端加载)
val sharedModule = module {
    factory { GetItemsUseCase(get()) }
    single<ItemRepository> { ItemRepositoryImpl(get()) }
}

// Ktor 服务端额外模块
val serverModule = module {
    single { ItemService(get()) } // 依赖 domain 层的 Repository
}

Step 3:编写基于 testApplication 的集成测试 这是保障服务端质量的关键。Skill 会引导 AI 生成使用 testApplication 的端到端测试。

// 由 AI 生成于 server/src/test
class ItemRoutesTest : FunSpec({
    test("GET /api/items should return items list") {
        testApplication {
            application {
                // 配置测试用的 DI 和插件
                configureSerialization()
                install(Koin) { modules(testModule) } // testModule 提供 Mock 实现
                configureRouting()
            }
            val response = client.get("/api/items")
            response.status shouldBe HttpStatusCode.OK
            val items = response.body<List<Item>>()
            items.shouldNotBeEmpty()
        }
    }
})

4. 端到端验证与常见协作模式

将三部分技能结合,可以实现从 UI 到数据库的完整验证循环:

  1. 编写 UI 测试:利用 Compose Test 规则验证屏幕状态和用户交互。
  2. 编写 UseCase 测试:纯 JVM 测试,验证业务逻辑。
  3. 编写 Ktor 集成测试:验证 API 端点、认证和序列化。
  4. AI 代码审查:触发 Kotlin Reviewer Agent,它会依据这三个 Skill 的规则,检查分层违规、非最佳实践的 Compose 代码或不安全的 Ktor 配置。

FAQ

Q: 这套实践适合纯 Android 项目吗? A: 适合。虽然面向 KMP,但 Clean Architecture 分层、Compose 状态管理和 Ktor 服务端模式均是 Android 开发的最佳实践,可直接应用。

Q: 如何让 AI 在生成代码时自动遵循这些模式? A: 在你的 AI 编程助手(如 Claude Code)中,确保已正确安装和激活 Everything Claude Code 的相关 Skill。在提问时明确提及“使用 Clean Architecture 分层”、“按照 Compose Multiplatform 模式”或“用 Ktor 标准结构”,AI 将自动套用对应模式。

Q: domain 层的模型如何在 Ktor 服务端和 Compose UI 中同时使用? A: 这正是 Clean Architecture 的优势。将领域模型(如 Item)定义在共享的 domain 模块中,前后端都依赖此模块。UI 层可转换为 ItemUiModel,服务端可直接使用或映射为数据库 Entity,实现了核心业务规则的最大化复用。