本文译自「You Can’t Hide Secrets in Your Android App. Here’s What to Do Instead.」,原文链接https://proandroiddev.com/you-cant-hide-secrets-in-your-android-app-here-s-what-to-do-instead-cce380fc1f82,由Anang Suwasto发布于2026年8月25日。
从零开始的架构测试套件
本文译自「Kotlin Architecture Tests with Konture: A Practical Guide - Part 3/3」,原文链接Kotlin Architecture Tests with Konture: A Practical Guide - Part 3/3,由Bao Le发布于2026年7月17日。
搭建一个专门的架构测试模块,添加 Konture,并构建一套小型结构规则,以保护 Kotlin 项目实际依赖的边界。
最好的首次架构测试通常并不巧妙。
这是团队一直以来都奉行的规则:
1 2 | |
这条规则很具体,也很容易解释,但一旦违反就会付出代价。它还能培养正确的习惯:将真实的架构决策编码到代码中,而不是理想化的示意图。
本指南使用 Gradle Kotlin DSL 和 JUnit 5。Konture 本身与测试运行器无关,因此相同的规则可以从 JUnit、Kotest、TestBalloon 或其他 Kotlin/JVM 运行器运行。
目标设置
使用专用的架构测试模块。
架构测试为何需要双视图
本文译自「Kotlin Architecture Tests: Why Konture Exists」,原文链接Kotlin Architecture Tests: Why Konture Exists,由Bao Le发布于2026年7月16日。
Kotlin 架构对同一架构有两种不同的理解:Gradle 图决定了哪些组件可以链接,而 Kotlin 源代码模型决定了代码的实际内容。Konture 的存在就是为了测试这两种理解。
考虑以下来自 Android 项目的规则:
展示代码不得在屏幕状态或面向 UI 的 API 中暴露传输 DTO。
这条规则在两个不同的地方都可能失效。
当表示模块直接连接到传输模块时,构建图可能会失败:
1 2 3 4 | |
它在源端也可能失败:
1 2 3 4 5 | |
这些故障彼此关联,但并不完全相同。第一种是 Gradle 模块的物理依赖问题,第二种是源代码级别的导入问题。一款优秀的 Kotlin 架构测试工具必须能够识别这两种故障,因为多平台系统同时受这两种因素的影响。
这就是 Konture 存在的理由。
不完整的观点
现有工具很有用。Konture 的目的并非取代编译器、代码检查器、测试运行器或所有架构测试库。问题在于,Kotlin 项目的每种视图都会有所遗漏。
| 视图 | 优势 | 不足 |
|---|---|---|
| JVM 字节码 | 已编译类及其依赖关系 | Kotlin 源代码意图、源代码集、Gradle 项目边界、部分编译器插件的影响 |
| Kotlin 源代码扫描 | 包、导入、声明、修饰符、注解 | 真实的 Gradle 模块图和项目依赖策略 |
| Gradle 图检查 | 模块、源代码集、已声明的项目依赖关系 | 源代码级导入、公共签名、可见性和类型泄漏 |
| 代码检查工具 | 局部风格和单文件质量 | 整体项目结构和架构所有权 |
Kotlin架构贯穿于这些观点之中。
你可以在已提交的示例中看到这一点。“Now in Android”示例包含 36 个 Gradle 项目(位于 settings.gradle.kts 文件中),其中包括 API/实现功能拆分和一个专门的 :konture-test 项目。KotlinConf KMP 示例 包含 9 个 Gradle 项目,涵盖共享核心、后端、Android、桌面、Web、管理和架构测试。单视图工具在这些项目中仍然有用,但它无法自然地看到项目使用的所有边界。
工具对比
实际问题不是“哪个工具最好?”,而是“哪个工具遵循哪种规则?”
| 工具选项 | 优势 | 劣势 | 适用场景 | 与 Konture 结合使用 |
|---|---|---|---|---|
| ArchUnit | 成熟的 JVM 字节码规则和类依赖性检查 | Gradle 项目图、KMP 源集、源代码级 Kotlin 意图 | 系统主要基于 JVM,规则在已编译类中可见 | 你还需要模块依赖策略、Kotlin 可见性或 KMP/平台边界 |
| detekt 自定义规则 | Kotlin PSI、样式、命名、本地声明规则 | Gradle 模块图和跨模块依赖策略 | 该规则类似于 lint:命名、注解、本地源代码约定 | lint 发现的问题需要与模块所有权或公共 API 边界一致 |
| Gradle Doctor 或模块图插件 | 构建健康状况、项目图可见性、依赖性报告 | 源导入、签名、类可见性、API 泄漏 | 你需要图洞察、构建性能报告或依赖性卫生 | 图边缘只是故事的一半,源代码级别的泄漏也至关重要 |
| 自定义 PSI 工具 | 高度特定的 Kotlin 源代码规则 | 维护成本、构建集成、图感知 | 你拥有一个针对特定组织的规则,团队可以拥有该工具 | 自定义规则应与构建图契约并行运行 |
| 运行时或 UI 测试工具,例如 Kakao | 用户流程和 Android UI 行为 | 静态架构 | 你正在验证行为、页面和交互流程 | 结构边界应在成为运行时行为缺陷之前失效 |
| 简单的审查清单 | 判断、细微差别、例外情况 | 在时间压力下的一致性 | 规则仍在不断演变或取决于人为设计的权衡 | 清单项变得足够稳定,可以在 CI 中执行 |
Konture 的赌注很窄:Kotlin 架构需要一个单一的测试表面,能够同时讨论 Gradle 模块和 Kotlin 源代码声明。
促使它发生的失败模式
最昂贵的架构故障很少始于“糟糕的架构”,它们往往始于合理的局部修复:
- 一个功能实现导入了另一个功能实现,因为 API 模块尚未公开某个缺失的契约。
- 一个共享的 KMP 模块在截止日期前接受了一个 Android 导入,之后发现桌面或 iOS 无法再干净地重用该代码。
- 一个公共存储库接口返回一个数据库实体,因为该实体已经包含所需的字段。
- 后端路由直接调用存储库,因为服务层对于一个端点来说过于繁琐。
每一次失败都会产生利息债务。下一次重构必须先偿还隐藏的耦合,才能实现预期的变更。下一个平台目标必须分离原本应该可移植的 API。下一个代码审查员必须从分散的导入和构建文件中重构架构决策。
Konture 的设计初衷就是为了解决这类问题:它既不是纯粹的源代码级规则,也不是纯粹的构建级规则,而是架构级规则,因为它介于两者之间。
字节码固然重要,但它并非 Kotlin 程序的全部。
ArchUnit 已成熟并被证明适用于 JVM 系统。如果你的架构规则可以从编译后的类中得到解答,那么字节码分析通常是一个不错的选择。
现代 Kotlin 项目通常需要比这更多的上下文信息。
Kotlin 源代码结构并非总能与团队想要维护的源代码级设计完美契合。顶层函数和扩展函数会被编译成生成的持有者类。内联函数会将函数体移至调用点。object、委托属性和编译器插件可能会引入一些对运行时很重要但对源代码级设计规则而言却显得冗余的生成结构。
但这并不意味着字节码分析是错误的。而是说,对于诸如以下规则而言,字节码并非最佳的主要分析视角:
:feature:checkout:impl是否依赖于同级实现模块?commonMain是否导入了 Android API?- 公共领域签名是否暴露了持久化类型?
impl包在源代码中是否保持内部状态?
这些是 Kotlin 和 Gradle 架构方面的问题,而不仅仅是 JVM 类方面的问题。
源代码扫描很有用,但文件夹并非构建方式
Kotlin优先的源代码扫描器擅长处理声明、导入、命名、注解和可见性。它们可以表达许多字节码工具难以处理的规则。
但源代码目录并非 Gradle 项目。包名并非模块依赖项。名为 api 的文件夹与通过 api 或 implementation 依赖的其他项目所依赖的模块并不相同。
这种区别在 Android 和 Kotlin 多平台项目中至关重要:
1 2 3 4 5 6 7 8 9 10 | |
构建过程已经知道哪些模块存在、哪些源集是生产源集,以及声明了哪些项目依赖项。架构测试应该使用这些信息,而不是仅仅依靠命名约定来重建架构。
代码检查器不是架构测试器
detekt 和 ktlint 非常擅长局部检查。它们并非设计用于回答系统整体问题:
- 此模块是否依赖于被禁止的同级模块?
- 某个功能实现是否对其他实现可见?
- 项目图是否存在循环?
- 公共 API 是否暴露了其他层拥有的类型?
这些不是格式问题,而是所有权和依赖关系问题。
Konture的双视图模型
Konture 将构建视图和源代码视图结合在一起。
构建视图包括:
- Gradle 模块。
- 源代码集。
- 生产环境 Kotlin 源代码目录。
- 已声明的项目依赖项。
- 已应用的插件上下文。
源视图包括:
- 文件、包和导入。
- 类、接口、函数和属性。
- 可见性和注解。
- 项目类之间的引用。
让架构边界变成可执行的测试
本文译自「Kotlin Architecture Tests: What They Are and Why They Matter - Part 1/3」,原文链接https://medium.com/proandroiddev/kotlin-architecture-tests-what-they-are-and-why-they-matter-389ce9a1204c,由Bao Le发布于2026年7月16日。
一个 Kotlin 项目可以编译通过,通过单元测试,满足代码检查工具的要求,但其结构仍然可能变得难以修改。架构测试正是为了弥补这一缺陷而存在的。
规范驱动开发:让AI生成符合预期的KMP代码
本文译自「Design a screen, get a Clean Architecture feature — Spec-Driven Development that keeps AI-generated KMP code from drifting」,原文链接https://proandroiddev.com/design-a-screen-get-a-clean-architecture-feature-and-keep-ai-generated-kmp-code-from-drifting-c134ffc9bfc2,由Ali Sadeghi发布于2026年7月23日。
千万别误用Android Skills
本文译自「Android Skills — What Google Just Released and Why Most Developers Are Already Using It Wrong」,原文链接https://medium.com/proandroiddev/android-skills-what-google-just-released-and-why-most-developers-are-already-using-it-wrong-43f71f61069b,由Dilipchandar发布于2026年8月8日。
Android XR 开发入门完全指南
本文译自「The Complete Guide to Getting Started with Android XR Development」,原文链接https://medium.com/proandroiddev/the-complete-guide-to-getting-started-with-android-xr-development-65bb057ec1b1,由Akshay Nandwana发布于2026年7月21日。
探究Android Views、Flutter和Compose如何渲染你的UI
本文译自「One Tap, Three Machines: How Android Views, Flutter, and Compose Actually Render Your UI」,原文链接https://medium.com/proandroiddev/one-tap-three-machines-how-android-views-flutter-and-compose-actually-render-your-ui-ad31c30ec279,由Angelina Andronova发布于2026年7月16日。
响应式的Android身份验证架构
本文译自「An Android auth architecture with encrypted tokens, auto-refresh, and reactive navigation」,原文链接https://proandroiddev.com/an-android-auth-architecture-with-encrypted-tokens-auto-refresh-and-reactive-navigation-b5dcb7704f83,由Shivam Agrawal发布于2026年6月27日。
简介
MVI模式的完整历史、误解和现代Android范式
本文译自「Yes, That’s MVI: The Pattern’s Full History, Misconceptions, and Modern Android Form」,原文链接https://proandroiddev.com/yes-that-is-mvi-674f810ca4fe,由Eury Pérez Beltré发布于2025年5月29日。
每项传统背后都有其原因——而原因背后,又蕴藏着一个故事。 – 佚名








