Harness Engineering:AI辅助Android开发的质量保障与工程实践

发布时间:2026/8/14 19:12:54
Harness Engineering:AI辅助Android开发的质量保障与工程实践 1. 项目概述从 Harness Engineering 到 AI 驱动的 Android 开发最近在和一些资深架构师交流时频繁听到一个词Harness Engineering。这个词乍一听有点陌生但拆解其内核你会发现它直指现代软件工程尤其是我们这些在移动端、AI 领域摸爬滚打的开发者每天都在面对的核心痛点——如何系统化地“驾驭”复杂性确保项目不“翻车”。Harness意为“驾驭”、“控制”在工程语境下它强调的是一套完整的、可重复的、自动化的工具链和流程用以管理和控制从代码提交到最终交付的每一个环节确保质量、效率和可预测性。这让我立刻联想到了当前最火热也最让人又爱又恨的组合用 AI 辅助 Android 应用开发。我们正处在一个奇妙的拐点。一方面AI 代码助手如 GitHub Copilot、Cursor、以及各种大模型驱动的 IDE 插件已经能显著提升编码效率从生成样板代码、补全函数到解释复杂逻辑无所不能。另一方面Android 开发本身的复杂性并未减少甚至因为多设备、多形态手机、折叠屏、车载、电视而加剧。当我们将这两者结合梦想着“AI 帮我写 App”时一个巨大的问号随之而来效率提升的背后质量如何保障项目会不会在看似智能的辅助下悄无声息地滑向混乱、不可维护甚至崩溃的深渊这正是 Harness Engineering 理念给我的核心启发。它告诉我们不能只盯着 AI 生成的单行代码是否“正确”而必须构建一个系统性的“驾驭”框架。这个框架要能容纳 AI 的创造力同时用工程化的缰绳约束其可能带来的不确定性。本文将结合我过去在多个中大型 Android 项目中的实战经验深入探讨如何将 Harness Engineering 的原则落地构建一套让“AI Android”开发既高效又稳健的最佳实践。无论你是独立开发者还是团队的技术负责人这些思路都能帮助你避免常见的陷阱真正让 AI 成为你可靠的副驾而非导致项目偏离航向的“幽灵司机”。2. 核心理念拆解什么是“驾驭工程学”在深入技术细节之前我们必须先统一思想。Harness Engineering 不是一个具体的工具而是一种方法论和思维模式。它的核心目标是通过自动化、标准化和持续反馈来“驾驭”软件开发过程中的各种变数和风险。对于“AI Android”这个场景我们可以将其分解为三个需要被“驾驭”的核心维度2.1 驾驭“不确定性”AI 生成代码的固有风险AI 模型是基于概率的它生成的代码在语法上可能完美但在逻辑、架构、性能甚至安全性上存在隐蔽缺陷。这种不确定性是固有的无法完全消除但可以被管理和控制。逻辑正确性风险AI 可能生成一段能编译运行的代码但其业务逻辑与你的需求存在微妙偏差。例如你让它“实现一个 RecyclerView 的适配器并支持点击事件”它可能生成了代码但却把点击监听器错误地绑定在了onCreateViewHolder而不是onBindViewHolder中或者在多选场景下状态管理混乱。架构一致性风险一个健康的 Android 项目有其约定的架构模式如 MVVM、MVI、包结构、命名规范。AI 在缺乏完整上下文时生成的代码可能破坏这种一致性。比如它可能把网络请求逻辑直接写在Activity里而不是按照项目规范放在Repository层。性能与资源风险AI 可能写出低效的代码。例如在RecyclerView适配器中频繁创建对象、在主线程进行耗时操作、或生成存在内存泄漏风险的代码如未正确解注册监听器。安全与合规风险这是最危险的一点。AI 可能引入不安全的 API 使用如硬编码密钥、或者使用了已被废弃且有安全漏洞的库版本。Harness Engineering 的应对策略是“假设生成物不可信必须验证”。我们需要建立强大的自动化验证屏障让每一行 AI 参与生成的代码都必须通过和人工编写代码同等甚至更严格的检验。2.2 驾驭“复杂性”Android 生态与 AI 工具的整合Android 开发本身就是一个复杂的生态系统Gradle 构建系统、Kotlin/Java 语言特性、Jetpack 组件、第三方 SDK、厂商适配……引入 AI 工具后复杂性是指数级增加的。你需要管理 AI 工具的配置、上下文提示Prompt的优化、不同模型本地 vs. 云端的切换等。Harness Engineering 的应对策略是“标准化与抽象”。我们需要为 AI 的使用制定团队规范创建可复用的、高质量的上下文模板比如针对“生成一个使用 Room 的 DAO”、“生成一个 ViewModel 单元测试”的专用 Prompt并将 AI 工具链无缝集成到现有的开发工作流如 Git、CI/CD中减少开发者的认知负担和操作成本。2.3 驾驭“演进性”AI 与项目的共同成长项目和 AI 模型都在不断演进。Android 框架会更新项目的业务逻辑会变化AI 模型的能力也在迭代。如何确保今天用 AI 生成的代码在三个月后依然可维护、可理解并且能与新引入的 AI 能力协同工作Harness Engineering 的应对策略是“持续反馈与知识沉淀”。这不仅仅是收集数据更是要建立一个闭环将 AI 生成代码在实际项目中暴露出的问题通过 Code Review、测试失败、生产故障反馈回来用于优化我们的使用规范、验证规则和 Prompt 策略。同时将成功的 AI 应用模式沉淀为团队的知识库或内部工具。理解了这三个需要驾驭的维度我们就可以开始构建具体的防御体系了。接下来的内容将围绕一个核心闭环展开如何为“AI Android”开发打造一个从代码生成、到验证、再到集成的“安全驾驶系统”。3. 构建防御体系AI 辅助开发的四大核心实践空谈理念不如实战。下面我将结合具体场景分享四个关键的工程实践它们共同构成了驾驭 AI 风险的防御体系。3.1 实践一制定精准的 AI 交互契约Prompt Engineering as Code把向 AI 提问Prompt看作是与一个能力超强但经验不足的实习生沟通。模糊的指令必然得到模糊甚至错误的结果。我们需要将 Prompt 工程化、代码化。1. 创建上下文丰富的“角色卡片”不要每次从头开始描述。为你的 AI 助手定义一个明确的“角色”和“上下文”。例如创建一个名为android_senior_dev.prompt的模板文件保存在项目根目录或团队知识库中你是一位经验丰富的 Android 高级开发工程师精通 Kotlin、Jetpack Compose、MVVM 架构和 Clean Architecture。你熟悉最新的 Android 开发最佳实践注重代码性能、可读性和可测试性。 **当前项目上下文** - 项目名称MyProductApp - 主要架构MVVM Repository 模式 - 网络层Retrofit Kotlin Coroutines - 本地数据库Room - 依赖注入Hilt - 代码规范遵循 Kotlin 官方编码约定使用 ktlint 进行格式化。 - 关键包结构 com.myproduct.data // 数据层Repository, DataSource com.myproduct.domain // 领域层UseCase, Model com.myproduct.presentation // 表现层ViewModel, UI **你的任务准则** 1. 生成的代码必须符合上述架构将代码放在正确的包层级中。 2. 优先使用 Kotlin 协程处理异步避免回调地狱。 3. 所有公开的 ViewModel 状态必须使用 StateFlow 或 SharedFlow 暴露。 4. 为所有非 trivial 的公共函数编写 KDoc 注释。 5. 避免使用已弃用Deprecated的 API。 6. 考虑内存泄漏确保在生命周期结束时清理资源。 现在请根据以下具体任务生成代码当需要 AI 协助时先加载这个基础上下文再附加具体任务描述。这能极大提高生成代码的准确性和一致性。2. 任务描述结构化、场景化坏例子“写一个登录功能。” 好例子“在com.myproduct.presentation.auth包下创建一个名为LoginViewModel的类。它需要依赖一个AuthRepository通过 Hilt 注入。功能要求1. 包含两个StateFlow分别表示用户名和密码的输入状态String类型。2. 包含一个login方法该方法会调用AuthRepository.login这是一个 suspend 函数返回ResultAuthToken。3. 在登录过程中需要一个_isLoading的MutableStateFlow来驱动 UI 显示加载状态。4. 登录成功或失败后需要用SharedFlow发射相应的事件LoginSuccess或LoginError供 UI 层消费。请生成该 ViewModel 的完整 Kotlin 代码。”实操心得我发现将 Prompt 保存在项目下的.prompt/目录中并纳入版本控制是非常有效的做法。团队新成员可以快速了解如何与 AI 协作保证了协作的一致性。3.2 实践二建立自动化的代码质量关卡生成代码只是第一步立即投入使用的风险极高。必须设立多道自动化检查关卡这是 Harness Engineering 的精髓。1. 静态代码分析SAST强化在 CI/CD 流水线中在 AI 生成代码合并前必须运行比平时更严格的静态检查。基础工具ktlint或detekt确保代码风格统一。将规则配置得严格一些例如强制要求显式返回类型、禁止使用!!非空断言。架构守护使用ArchUnit编写架构规则测试。这是对抗 AI 破坏架构一致性的利器。例如你可以写一个测试“ViewModel类不能直接依赖android.*包下的类如Context”或者“data层包下的类不能被presentation层直接导入”。当 AI 生成了不符合架构的代码时这些测试会在合并前失败。安全扫描集成工具如MobSF(Mobile Security Framework) 或DependencyCheck对引入的依赖和代码模式进行安全扫描防止 AI 引入已知的安全漏洞代码模式。2. 针对性单元测试生成与验证让 AI 生成代码的同时也让它为这段代码生成单元测试。然后必须运行这些测试。Prompt示例“为我刚才生成的LoginViewModel编写相应的单元测试。使用kotlinx-coroutines-test进行协程测试使用MockK或Mockito进行依赖模拟。请覆盖以下场景1. 初始状态验证。2. 输入用户名密码后状态更新。3. 登录成功用例。4. 登录失败用例。5. 加载状态切换。”关键动作生成测试后立即在 CI 中运行它们。如果测试失败首先检查是测试用例写得不对还是生成的业务代码本身有逻辑缺陷。这个过程能发现大量隐蔽的边界条件错误。3. 依赖与许可证审查AI 可能会在代码中建议引入新的第三方库。必须有一个自动化流程来审查这些依赖。版本冲突检查Gradle 的dependencyUpdates插件可以帮助检查是否有新版本但更重要的是检查 AI 建议的依赖版本是否与项目现有依赖冲突。许可证合规性扫描使用如FOSSA、Black Duck等工具自动扫描新引入依赖的许可证如 GPL、AGPL 等确保符合公司合规要求。AI 可不会替你考虑法律风险。注意千万不要因为代码是 AI 生成的就绕过或简化 Code Review 环节。相反应该进行更聚焦的 Review。Reviewer 的重点应从“语法细节”转向“架构符合度”、“业务逻辑正确性”和“AI 引入的特定风险点”。3.3 实践三AI 集成开发环境IDE的标准化配置开发者的主要战场是 IDE。混乱的 AI 工具配置会导致效率低下和结果不一致。1. 统一团队 AI 助手插件团队应约定使用同一款或同一类 AI 代码助手插件如 GitHub Copilot、Amazon CodeWhisperer、或基于特定大模型定制的 IDE 插件。并共享配置模板。上下文配置在插件设置中明确哪些文件应该被纳入上下文如build.gradle.kts,项目架构说明.md哪些不应该如*.log, 大型二进制文件。快捷键统一定义团队内接受建议、触发生成的统一快捷键减少操作摩擦。2. 创建项目级的“智能上下文”文件在项目根目录创建.cursor/rules或.copilot/instructions.md文件取决于你的工具。这些文件会被 AI 插件自动读取作为项目级的固定上下文。内容可以包括 * 项目技术栈摘要。 * 重要的架构决策记录ADR。 * 团队约定的代码风格如“我们使用sealed class而不是枚举来处理状态”。 * 常见任务的代码片段示例。3. 本地模型与云端模型的策略对于涉及敏感代码或网络不便的场景可以考虑配置本地运行的大模型如通过ollama运行 CodeLlama 等。在 IDE 中配置备用模型源并制定清晰的使用策略普通代码补全用云端模型以保证速度和质量涉及核心业务逻辑或敏感信息时切换到本地模型进行辅助。实操心得我们团队曾因为未统一配置导致有的成员用 Copilot 生成了 Java 代码而项目主体是 Kotlin造成了不必要的格式转换成本。一个简单的、版本化管理的 IDE 配置文件如.vscode/settings.json或.idea/codeStyles/能避免很多此类问题。3.4 实践四度量、反馈与持续改进闭环没有度量就无法改进。我们需要数据来回答AI 到底帮了我们多少又带来了多少麻烦1. 定义关键度量指标AI 代码采纳率在 Code Review 中标记出由 AI 生成的代码块。统计最终被合并的代码中AI 生成代码的行数占比。这能衡量 AI 的实际贡献度。AI 引入缺陷率在测试阶段单元测试、集成测试和线上故障中追踪那些根本原因可追溯到 AI 生成代码的缺陷数量。与总缺陷数对比评估其风险。任务完成时间抽样记录特定类型开发任务如“创建一个新的带列表的页面”在使用 AI 辅助前后的平均耗时。开发者满意度定期进行匿名调研了解开发者对 AI 工具在准确性、流畅度、对工作流干扰度等方面的感受。2. 建立反馈收集机制在 Code Review 中嵌入反馈在 Review AI 生成代码时除了评论代码本身可以增加标签如#ai-logic-error,#ai-arch-issue便于后续分类分析。创建“AI 模式库”建立一个内部 Wiki 或共享文档记录两种内容成功模式记录那些高质量的、可复用的 Prompt 和生成的优秀代码案例。例如“如何用 Prompt 生成一个完美的 Paging 3 DataSource”。失败模式与修复方案记录常见的 AI 生成错误及其人工修正方法。例如“AI 生成的 RoomQuery方法漏掉了suspend关键字需手动添加”。3. 定期复盘与策略调优每季度或每两个迭代团队应进行一次复盘。基于收集的度量数据和反馈讨论并调整我们的 Prompt 模板需要更新吗静态分析规则是否需要针对新的 AI 错误模式进行加强是否需要调整 AI 工具的使用场景例如规定业务核心逻辑模块暂时禁用全自动生成只使用补全通过这个“实践-度量-反馈-优化”的闭环你就能像驾驭一辆高性能赛车一样驾驭 AI 的开发潜力让它始终在安全的赛道上为你加速。4. 典型场景实战一个需求从 Prompt 到 Merge 的全流程让我们通过一个虚构但非常典型的 Android 需求将上述所有实践串联起来看一个完整的、“不翻车”的工作流是怎样的。需求描述在“我的”页面新增一个“消息中心”入口点击后进入一个列表页展示用户的消息包括系统通知和私信支持下拉刷新和上拉加载更多。4.1 第一步需求分析与 Prompt 准备开发者或产品经理首先需要将模糊的需求转化为精确的技术任务描述。这本身就是一个重要的分解过程。任务拆解A. 在“我的”页面 (ProfileFragment) 的 UI 上添加一个入口项。B. 创建新的消息列表页 (MessageListFragment或Activity)。C. 实现对应的MessageListViewModel。D. 实现数据层MessageRepository,MessageRemoteDataSource,MessageLocalDataSource(如果需要缓存)。E. 定义数据模型Message。F. 实现分页逻辑使用 Paging 3。编写结构化 Prompt 打开之前定义的android_senior_dev.prompt基础模板在后面附加具体的任务描述。我们以创建MessageListViewModel和 Paging 相关逻辑为例“具体任务实现消息列表的 ViewModel 和分页逻辑。请创建MessageListViewModel。使用 Paging 3 库进行分页。定义一个MessagePagingSource它需要依赖一个MessageRepository来获取数据。假设MessageRepository有一个suspend fun getMessages(page: Int, pageSize: Int): ListMessage方法。MessageListViewModel需要暴露一个FlowPagingDataMessage给 UI 层。同时ViewModel 需要处理下拉刷新和重试逻辑。请提供刷新和重试的方法。考虑到消息可能有已读/未读状态ViewModel 还应提供一个markAsRead(messageId: String)的方法。请为以上所有内容生成完整的 Kotlin 代码并包含必要的导入语句。”4.2 第二步在受控环境中生成与初步审查生成代码在 IDE 中将上述 Prompt 提交给 AI 助手。本地运行静态检查生成代码后不要立即复制粘贴。先在 IDE 或本地命令行运行./gradlew ktlintCheck detekt检查生成代码的风格和基础问题。运行架构单元测试运行项目中已有的 ArchUnit 测试确保新生成的ViewModel没有破坏架构约束比如错误地引入了 Android 依赖。人工逻辑初审开发者快速浏览生成的代码重点关注分页逻辑是否正确PagingSource的load方法实现。状态管理是否合理刷新状态是否用MutableStateFlow管理。协程作用域 (viewModelScope) 的使用是否正确。生成的markAsRead方法是否合理是否调用了 Repository 的相应方法。4.3 第三步生成并运行配套单元测试针对生成的MessageListViewModel和MessagePagingSource再让 AI 生成单元测试。Prompt“请为上面生成的MessageListViewModel和MessagePagingSource编写单元测试。使用MockK模拟MessageRepository。测试用例需覆盖1.PagingSource的load方法在成功、失败、无更多数据时的行为。2.ViewModel刷新操作是否能触发新的PagingData。3.markAsRead方法是否能正确调用 Repository。”生成测试后立即在本地运行./gradlew test --tests *MessageList*。如果测试失败分析原因是测试写得不对还是 ViewModel 逻辑有问题这个过程能发现大量边界情况 Bug。4.4 第四步集成与提交前检查将生成的代码和测试放入项目正确位置。运行完整的本地构建./gradlew clean build。确保编译通过所有现有测试包括刚生成的都通过。提交代码提交时在 Commit Message 中明确标记[AI-Assisted]并简要说明 AI 协助的部分如“MessageListViewModel及分页逻辑由 AI 生成已通过单元测试”。触发 CI/CD 流水线流水线应自动执行更全面的静态代码分析。所有单元测试和集成测试。依赖安全扫描。如果有 UI 测试也应运行。4.5 第五步聚焦的 Code ReviewReviewer 收到 Pull Request 后其审查重点非常明确架构符合度代码是否放对了包依赖方向是否正确业务逻辑正确性分页、刷新、标记已读的逻辑是否符合产品需求有无遗漏或过度设计AI 特定风险点生成的代码中是否有“幻觉”引入的不存在的 API 或方法错误处理是否完备网络错误、空状态性能是否有隐患如内存泄漏、主线程操作测试充分性AI 生成的测试是否覆盖了核心场景是否需要补充只有通过所有这些关卡代码才能被合并。至此一段由 AI 深度参与的功能代码才算是被“驾驭”着安全落地。5. 常见“翻车”点与避坑指南在实际操作中即使遵循了上述流程依然会遇到一些典型问题。下面是我和团队在实践中总结出的“翻车”重灾区及应对策略。问题现象根本原因避坑策略与解决方案生成的代码编译通过但运行时崩溃或逻辑错误AI 基于过时或错误的上下文生成或对 Android 生命周期理解有偏差。1. 强化上下文在 Prompt 中明确指定使用的库版本和最小 SDK 版本。2. 即时验证生成后立即写一个最简单的集成测试或运行到模拟器上验证核心流程。3. 代码审查聚焦逻辑Review 时让作者口头复述一遍关键算法或数据流常能发现理解偏差。AI 破坏了项目的统一架构风格Prompt 中架构描述不够具体或 AI 未充分理解项目现有代码。1. 架构守护测试如前所述用 ArchUnit 编写硬性规则CI 失败则无法合并。2. 提供“参考样本”在 Prompt 中链接或粘贴一段项目中公认的、符合架构的典型代码如一个现有的ViewModel让 AI “依葫芦画瓢”。3. 创建项目脚手架工具对于常见页面如列表页、详情页开发内部代码生成模板或脚本比依赖 AI 更可靠。AI 引入了有安全漏洞的依赖或代码模式AI 的训练数据中包含大量旧代码或存在漏洞的示例。1. 依赖白名单/黑名单在项目build.gradle或 CI 脚本中配置规则禁止引入特定已知不安全的库。2. 自动化安全扫描将DependencyCheck等工具集成到 CI任何引入新依赖或版本变更的 PR 都必须通过扫描。3. 代码模式审查清单在 Review 清单中加入安全项如“检查是否有硬编码密钥”、“检查网络请求是否使用 HTTPS”等。过度依赖 AI导致开发者自身能力退化或代码“黑盒化”开发者将 AI 当作“黑箱”代码生成器不思考其输出。1. 设立“无 AI 区”规定核心业务模块、算法模块必须由人工主导编写AI 仅作辅助。2. 强制注释与解释要求对 AI 生成的关键代码段开发者必须添加注释说明其工作原理和设计考量。3. 定期代码重构安排专门时间对早期 AI 生成的大量代码进行重构和梳理确保团队对其有集体所有权和深刻理解。Prompt 效果不稳定时好时坏Prompt 描述模糊或 AI 模型本身存在波动。1. 沉淀 Prompt 模板库将针对不同任务CRUD 操作、网络层、UI 组件验证有效的 Prompt 保存下来形成团队资产。2. 迭代优化 Prompt将生成效果不佳的案例记录下来分析是描述不清、缺少上下文还是任务本身过于复杂然后针对性优化 Prompt。3. 结合使用多种模型对于关键任务可以尝试用不同的 AI 模型如 Claude、GPT生成对比结果取最优或综合。我个人最深刻的一个教训是曾经让 AI 生成一个复杂的图像处理管道它生成了一段大量使用GlobalScope.launch的代码。在简单测试中运行良好但上线后不久就收到了关于内存泄漏和 ANR 的崩溃报告。根本原因是 AI 对 Android 生命周期和结构化并发的理解是割裂的。自那以后我们在所有涉及协程的 Prompt 开头都加上了铁律“严禁使用GlobalScope所有协程必须基于viewModelScope或lifecycleScope启动并确保在生命周期结束时取消。” 这个具体的、强制的约束彻底解决了这一类问题。6. 工具链推荐与配置片段工欲善其事必先利其器。一套好的工具链配置是实践 Harness Engineering 的基础。以下是一些经过验证的推荐和配置示例。1. 静态分析与架构守护配置 (build.gradle.kts模块)// 在模块级的 build.gradle.kts 中 plugins { id(org.jlleitschuh.gradle.ktlint) version 11.6.1 id(io.gitlab.arturbosch.detekt) version 1.23.5 } ktlint { // 启用实验性规则更严格 enableExperimentalRules.set(true) // 输出彩色报告 coloredOutput.set(true) // 自定义规则例如禁用 !! 操作符 disabledRules.set(setOf(no-unused-imports)) // 示例可根据需要调整 } detekt { config files($projectDir/config/detekt/detekt.yml) buildUponDefaultConfig true } dependencies { // ArchUnit for Android 测试 testImplementation(com.tngtech.archunit:archunit-junit5:1.2.1) }2. ArchUnit 测试示例 (src/test/kotlin/arch/ArchitectureTest.kt)import com.tngtech.archunit.core.importer.ImportOption import com.tngtech.archunit.junit.AnalyzeClasses import com.tngtech.archunit.junit.ArchTest import com.tngtech.archunit.lang.ArchRule import com.tngtech.archunit.lang.syntax.ArchRuleDefinition.* AnalyzeClasses( packages [com.yourcompany.yourapp], importOptions [ImportOption.DoNotIncludeTests::class] ) class ArchitectureTest { ArchTest val viewModelsShouldResideInPresentationPackage: ArchRule classes().that().haveSimpleNameEndingWith(ViewModel) .should().resideInAPackage(..presentation..) .as(ViewModels 应放在 presentation 包下) ArchTest val repositoriesShouldOnlyBeAccessedByUseCasesOrViewModels: ArchRule noClasses().that().resideInAPackage(..data..) .should().beAccessedByClassesThat().resideInAPackage(..ui..) // UI层如Fragment不应直接访问Repository .as(Data层如Repository不应被UI层直接访问) ArchTest val useCasesShouldNotDependOnAndroidFramework: ArchRule noClasses().that().resideInAPackage(..domain..) .should().dependOnClassesThat().resideInAPackage(android..) .as(Domain层UseCase不应依赖Android框架) }3. CI/CD 流水线关键步骤示例 (GitHub Actions.github/workflows/ci.yml)name: Android CI on: [push, pull_request] jobs: build-and-test: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - name: Set up JDK uses: actions/setup-javav4 with: { distribution: temurin, java-version: 17 } - name: Cache Gradle uses: actions/cachev4 with: { path: ~/.gradle/caches, key: gradle-${{ runner.os }}-${{ hashFiles(**/*.gradle*, **/gradle-wrapper.properties) }} } - name: Run ktlint run: ./gradlew ktlintCheck - name: Run detekt run: ./gradlew detekt - name: Run ArchUnit Tests run: ./gradlew testDebugUnitTest --tests *ArchitectureTest* - name: Run All Unit Tests run: ./gradlew testDebugUnitTest - name: Dependency Security Check run: ./gradlew dependencyCheckAnalyze # 需要配置 org.owasp.dependencycheck 插件 - name: Build APK run: ./gradlew assembleDebug4. 项目级 AI 上下文文件示例 (.cursor/rules.mdc)# 项目MyProductApp - Android 开发规范 ## 技术栈 - 语言Kotlin - 最小 SDKAPI 24 - 架构MVVM Clean Architecture (Data, Domain, Presentation) - 异步Kotlin Coroutines Flow - 依赖注入Hilt - 网络Retrofit Moshi - 本地数据库Room - 分页Paging 3 ## 代码风格 - 使用 StateFlow/SharedFlow 暴露 UI 状态和事件。 - ViewModel 中使用 viewModelScope 启动协程。 - Repository 返回 ResultT 密封类包装成功/失败。 - UI 层使用 Jetpack Compose如项目使用或 ViewBinding如使用 XML。 - 禁止使用 !! 非空断言优先使用空安全调用或 Elvis 操作符。 - 所有 Activity/Fragment 的导航使用 Navigation Component。 ## 生成要求 - 生成的代码必须包含合适的 KDoc 注释。 - 优先使用不可变数据val, data class。 - 对于可能为空的集合返回空集合而非 null。配置好这些工具和规范就如同为你的项目安装了“自动驾驶”的基础传感器和交通规则让 AI 这辆快车能在既定的轨道上安全驰骋。7. 总结从“试用”到“驾驭”的心态转变回顾整个过程从 Harness Engineering 中汲取的最大智慧是完成了一次关键的心态转变从把 AI 当作一个偶尔“试用”的新奇玩具转变为将其视为一个需要被系统化“驾驭”的核心生产力组件。这意味着我们不再纠结于“AI 能不能写出这段代码”而是专注于“我们如何建立一套流程确保 AI 写出的任何代码都能符合我们的质量标准”。前者关注单点能力后者关注系统工程。前者可能导致惊喜与惊吓并存后者则追求稳定的、可预期的产出提升。这套方法的最终目标不是取代开发者而是增强开发者。它将开发者从重复性、模式化的编码劳动中解放出来让我们能更专注于架构设计、复杂问题拆解、核心算法实现和创造性的产品思考。同时它通过自动化的质量关卡将我们从低级的 Bug 排查中拯救出来提升了整个团队的交付信心和代码健康度。开始行动吧。不妨从为一个现有项目配置一套严格的ktlint和detekt规则开始然后尝试为一个简单的功能编写一个详细的 Prompt并运行生成的代码通过你新设立的 CI 关卡。你会立刻感受到那种代码既快速产出又稳稳落地的可控感正是高效、稳健的现代 Android 开发应有的样子。