news 2026/10/9 7:46:05

【ArkUI进阶练中学】第10课:架构设计与工程化最佳实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【ArkUI进阶练中学】第10课:架构设计与工程化最佳实践

本节目标

  • 掌握大型 HarmonyOS 应用的模块拆分策略,理解按业务域、按功能层、按团队边界三种拆分维度的适用场景
  • 掌握依赖治理的核心原则,能够使用 ohpm 的 override、resolve_conflict 和依赖分析工具控制依赖数量与版本一致性
  • 掌握构建优化的关键配置,能够通过增量编译、并行构建、HSP 共享和编译缓存缩短构建时间
  • 掌握团队协作规范,包括代码分层约定、命名规范、提交规范和 Code Review 检查清单
  • 掌握多环境配置管理方案,能够通过 product/flavor 机制管理开发、测试、生产环境的差异化配置
  • 掌握 CI/CD 流水线的搭建方法,能够将编译、测试、性能门禁和签名打包集成到自动化流程
  • 能够为一个中大型应用设计可维护、可扩展、可协作的工程架构

一、模块拆分策略

1.1 按业务域拆分

按业务域拆分是最直观的拆分方式,每个业务域对应一个独立的模块。例如一个电商应用可以拆分为首页模块、商品模块、购物车模块、订单模块、个人中心模块等。每个业务模块内部高内聚,包含该业务域的所有页面、组件、数据模型和业务逻辑。

适用场景:业务边界清晰、团队按业务线划分、需要独立开发和测试的大型应用。

核心原则:模块之间通过明确定义的接口通信,尽量减少直接依赖。业务模块之间不应存在循环依赖,可以通过依赖注入或事件总线解耦。

1.2 按功能层拆分

按功能层拆分是将应用按技术职责分为 UI 层、业务逻辑层、数据访问层和基础设施层。这种拆分方式与架构设计的分层模型一一对应。

适用场景:技术栈统一、需要严格控制分层边界、追求架构一致性的团队。

核心原则:上层依赖下层,下层不感知上层。UI 层只负责展示和交互,业务逻辑层负责规则编排,数据访问层负责持久化与网络,基础设施层提供通用工具和日志。

1.3 按团队边界拆分

按团队边界拆分是康威定律在软件架构中的直接体现——系统架构应与组织结构保持一致。每个团队负责的模块可以独立开发、独立测试、独立发布。

适用场景:多团队协作、需要并行开发、模块间接口稳定的大型项目。

核心原则:模块的所有权明确,接口变更需要经过双方评审。每个模块有独立的负责人和 Code Review 流程。

1.4 三种维度的组合使用

实际项目中,三种拆分维度通常组合使用。推荐的结构是:先按业务域拆分为顶层模块,每个业务域内部再按功能层拆分为子模块,最后根据团队边界确定模块的归属和维护责任。

entry/ # 主入口(HAP) ├── features/ │ ├── home/ # 首页业务域(HAR) │ │ ├── ui/ # UI 层 │ │ ├── viewmodel/ # 业务逻辑层 │ │ └── data/ # 数据访问层 │ ├── product/ # 商品业务域(HAR) │ ├── cart/ # 购物车业务域(HAR) │ └── order/ # 订单业务域(HAR) ├── commons/ │ ├── base/ # 基础工具(HAR) │ ├── network/ # 网络封装(HAR) │ ├── storage/ # 持久化封装(HAR) │ └── ui-components/ # 通用 UI 组件(HAR) └── shared/ └── constants/ # 全局常量(HAR)

二、依赖治理

2.1 依赖数量的控制

依赖数量直接影响构建时间和包体积。每个第三方依赖都会增加编译时间、增大包体积、引入潜在的安全风险。建议遵循以下原则:

优先使用系统能力:HarmonyOS 已经提供了丰富的系统 Kit,如网络、存储、媒体、AI 等,优先使用系统能力而非引入第三方库。

评估依赖的必要性:引入一个依赖前,评估它是否真的必要,是否可以用少量代码自行实现,是否有更轻量的替代方案。

定期清理无用依赖:项目迭代过程中,部分依赖可能已经不再使用。定期使用依赖分析工具扫描未使用的依赖并清理。

2.2 依赖版本的统一

多模块项目中最常见的问题是依赖版本不一致。模块 A 依赖了 lodash 1.0,模块 B 依赖了 lodash 2.0,打包时两个版本都会被包含,导致包体积膨胀和潜在的运行时冲突。

使用 ohpm 的override机制强制统一版本:

// oh-package.json5(工程级) { "overrides": { "lodash": "2.0.0", "axios": "1.6.0" } }

开启resolve_conflict自动解决冲突:

// .ohpmrc { "resolve_conflict": true }

2.3 依赖分析工具

使用ohpm list查看工程的依赖树,识别重复依赖和版本冲突。使用 DevEco Studio 的 Build Analyzer 分析各依赖的体积占比,识别体积大户。

2.4 依赖分层的约束

在大型项目中,需要对依赖关系施加约束,避免模块间随意引用导致的架构腐化。推荐使用以下约束:

业务模块不能反向依赖主入口:features 层的模块不能依赖 entry 模块。

业务模块之间禁止直接依赖:features 层的模块之间如需通信,通过 commons 层的接口或事件总线解耦。

公共模块不能依赖业务模块:commons 层的模块不能依赖 features 层的模块。

三、构建优化

3.1 增量编译与并行构建

HarmonyOS 的模块化编译基于 ES Module 的 Bundleless 编译模式,API 10 及以上版本的 Stage 模型工程默认开启。修改单个模块代码无需整包编译构建,增量编译构建时间极大减少。

hvigor 构建系统默认开启并行构建,可以利用多核 CPU 加速构建。在hvigorfile.ts中可以调整并行度配置。

3.2 编译缓存

DevEco Studio 支持编译缓存,将编译产物缓存到本地,下次构建时复用。缓存生效的前提是源文件未变化。建议在 CI 环境中配置缓存目录,加速重复构建。

3.3 HSP 共享减少重复编译

在多模块项目中,将公共代码和资源抽取为 HSP,消除 HAR 导致的重复拷贝。但需要注意:大量使用 HSP 替代 HAR,会在编译引用这些 HSP 共享包的模块时触发更多的语言编译任务,导致编译耗时和编译内存占用增加。需要综合评估包体积收益和编译时间成本。

3.4 构建配置优化

在build-profile.json5中配置以下选项加速构建:

{ "app": { "products": [ { "name": "default", "signingConfig": "default", "compatibleSdkVersion": "5.0.0(12)", "buildOption": { "strictMode": { "caseSensitiveCheck": true, "useNormalizedOHMUrl": true } } } ] } }

useNormalizedOHMUrl开启后可以优化依赖解析效率。

四、团队协作规范

4.1 代码分层约定

明确各层的职责边界,避免职责混淆:

页面层(pages/views):只负责 UI 展示和用户交互,不包含业务逻辑。通过 ViewModel 获取数据,通过事件回调触发业务操作。

ViewModel 层(viewmodel):负责业务逻辑编排、状态管理、数据转换。不直接操作 UI,不直接访问数据库或网络。

数据层(data):负责持久化和网络请求,提供统一的数据访问接口。不包含业务逻辑。

工具层(utils):提供无状态的通用工具函数,不依赖任何业务模块。

4.2 命名规范

文件命名:页面文件以 Page 结尾(如 HomePage.ets),组件文件以组件名命名(如 TodoItem.ets),工具文件以功能命名(如 DateUtil.ets),模型文件以 Model 结尾(如 TodoModel.ets)。

变量命名:使用小驼峰(如 userName),常量使用全大写下划线分隔(如 MAX_RETRY_COUNT),类名使用大驼峰(如 TodoViewModel)。

接口命名:以 I 开头或使用描述性名称(如 UserInfo、TodoRepository)。

4.3 提交规范

推荐使用 Angular 提交规范,格式为type(scope): subject:

type 类型:feat(新功能)、fix(修复)、docs(文档)、style(格式)、refactor(重构)、perf(性能)、test(测试)、chore(构建/工具)。

scope 范围:模块名,如 home、cart、network。

subject 描述:简洁的描述,使用中文或英文,不超过 50 个字符。

示例:feat(home): 添加待办搜索功能、fix(cart): 修复购物车数量计算错误。

4.4 Code Review 检查清单

每次提交前自查以下项目:

  • 代码是否符合分层约定,是否存在跨层调用
  • 是否有硬编码的字符串、颜色、尺寸
  • 是否处理了异常和边界情况
  • 是否使用了正确的状态管理装饰器
  • 是否有内存泄漏风险(未释放的定时器、未取消的监听)
  • 是否遵循了命名规范
  • 是否有必要的注释和文档

五、多环境配置管理

5.1 环境差异化的需求

一个应用通常需要在开发、测试、生产三个环境中运行,每个环境的 API 地址、日志级别、功能开关都不同。硬编码环境配置会导致每次切换环境都要修改代码,容易出错。

5.2 使用 product 机制

在build-profile.json5中定义多个 product,每个 product 对应一个环境:

{ "app": { "products": [ { "name": "develop", "signingConfig": "default", "compatibleSdkVersion": "5.0.0(12)", "buildOption": { "arkOptions": { "buildProfileFields": { "API_BASE_URL": "https://dev-api.example.com", "LOG_LEVEL": "debug", "ENABLE_MOCK": true } } } }, { "name": "release", "signingConfig": "release", "compatibleSdkVersion": "5.0.0(12)", "buildOption": { "arkOptions": { "buildProfileFields": { "API_BASE_URL": "https://api.example.com", "LOG_LEVEL": "error", "ENABLE_MOCK": false } } } } ] } }

在代码中通过BuildProfile访问:

importBuildProfilefrom'BuildProfile';constAPI_BASE_URL=BuildProfile.API_BASE_URL;constLOG_LEVEL=BuildProfile.LOG_LEVEL;constENABLE_MOCK=BuildProfile.ENABLE_MOCK;

5.3 配置文件的组织

将环境相关的配置集中到一个文件,通过 BuildProfile 注入不同值:

// commons/config/AppConfig.etsexportclassAppConfig{staticreadonlyapiBaseUrl:string=BuildProfile.API_BASE_URL;staticreadonlylogLevel:string=BuildProfile.LOG_LEVEL;staticreadonlyenableMock:boolean=BuildProfile.ENABLE_MOCK;staticisDebug():boolean{returnAppConfig.logLevel==='debug';}}

六、CI/CD 流水线

6.1 流水线的核心环节

一个完整的 HarmonyOS 应用 CI/CD 流水线包含以下环节:

代码检查:运行 Code Linter 静态检测,检查代码规范和潜在问题。

编译构建:执行hvigorw assembleHap构建 HAP 包,开启 Release 模式获取完整优化。

单元测试:运行 Hypium 单元测试,输出测试报告。

UI 测试:在模拟器或真机上运行 UI 自动化测试。

性能门禁:使用 DevEco Testing 运行场景化性能测试,对比性能基线,低于基线则阻断合入。

签名打包:配置发布签名,构建正式 HAP 包。

上传分发:将 HAP 包上传到 AppGallery Connect 或内部测试平台。

6.2 流水线配置示例

以下是一个基于 Jenkins 或 GitLab CI 的流水线配置示例:

stages:-lint-build-test-performance-packagelint:stage:lintscript:-hvigorw codeLinterbuild:stage:buildscript:-hvigorw assembleHap--mode module-p product=defaultunit_test:stage:testscript:-hvigorw test--mode module-p module=entry@defaultperformance:stage:performancescript:-deveco-testing run--task performance--baseline baseline.jsonpackage:stage:packagescript:-hvigorw assembleApp--mode project-p product=releaseartifacts:paths:-build/outputs/default/*.hap

6.3 性能门禁的集成

性能门禁是防止性能退化的关键手段。设定性能基线(如冷启动 ≤3000ms、页面切换 ≤1000ms、帧率 ≥60 帧),每次代码合入前自动运行性能测试,低于基线则阻断合入。

DevEco Testing 的性能基线管理能力可以自动记录内存占用、CPU 负载等关键指标,通过历史数据对比精准定位性能退化问题,在性能退化早期发出预警。

6.4 构建缓存与并行加速

在 CI 环境中配置构建缓存和并行执行,可以显著缩短流水线执行时间:

cache:paths:-.hvigor/cache/-node_modules/-oh_modules/build:stage:buildscript:-hvigorw assembleHap--parallel--daemon

七、多元化习题

习题 1(判断题)

题目:在模块拆分中,业务模块之间可以直接相互依赖,不需要通过公共模块解耦。

答案:错误

解读:业务模块之间禁止直接依赖,如需通信应通过 commons 层的接口或事件总线解耦。直接依赖会导致模块间耦合度过高,一个模块的修改会牵连其他模块,破坏模块的独立性和可维护性。

习题 2(单选题)

题目:以下哪种拆分维度是康威定律在软件架构中的直接体现?

A. 按业务域拆分
B. 按功能层拆分
C. 按团队边界拆分
D. 按技术栈拆分

答案:C

解读:按团队边界拆分是康威定律在软件架构中的直接体现——系统架构应与组织结构保持一致。每个团队负责的模块可以独立开发、独立测试、独立发布。

习题 3(多选题)

题目:关于多环境配置管理,以下说法正确的有(多选):

A. 使用 product 机制定义多个环境,每个 product 对应一套配置
B. 通过 BuildProfile 在代码中访问环境配置
C. 环境配置应硬编码在代码中以便于管理
D. 将环境相关的配置集中到 AppConfig 统一管理

答案:A、B、D

解读:使用 product 机制定义多个环境,每个 product 对应一套配置,选项 A 正确。通过 BuildProfile 在代码中访问环境配置,选项 B 正确。环境配置不应硬编码在代码中,硬编码会导致每次切换环境都要修改代码,容易出错,选项 C 错误。将环境相关的配置集中到 AppConfig 统一管理,选项 D 正确。

习题 4(代码填空题)

题目:请补全以下build-profile.json5配置,使用override机制强制统一 lodash 的版本为 2.0.0。

// oh-package.json5(工程级) { "______________": { "lodash": "2.0.0" } }

答案:overrides

解读:overrides用于强制统一依赖版本。当多个模块依赖同一库的不同版本时,使用overrides指定统一使用的版本号,避免多版本重复打包导致的包体积膨胀和潜在运行时冲突。

习题 5(代码改错题)

题目:以下代码存在架构分层问题,请指出问题并修正。

// features/home/ui/HomePage.etsimport{RdbHelper}from'../../../commons/storage/RdbHelper';@Entry@Componentstruct HomePage{@Statetodos:Todo[]=[];aboutToAppear():void{// 页面层直接访问数据层this.todos=RdbHelper.queryAll();}build(){List(){ForEach(this.todos,(todo:Todo)=>{ListItem(){Text(todo.title)}})}}}

答案:页面层直接访问数据层,违反了分层约定。页面层应通过 ViewModel 获取数据,不直接操作数据库。修正方案:

// features/home/ui/HomePage.etsimport{TodoViewModel}from'../viewmodel/TodoViewModel';@Entry@ComponentV2struct HomePage{@LocalviewModel:TodoViewModel=newTodoViewModel();aboutToAppear():void{this.viewModel.loadTodos();}build(){List(){ForEach(this.viewModel.todos,(todo:Todo)=>{ListItem(){Text(todo.title)}})}}}

解读:分层架构的核心价值在于职责分离。页面层只负责 UI 展示和用户交互,业务逻辑由 ViewModel 层处理,数据访问由数据层处理。页面层直接访问数据层会导致职责混淆,难以维护和测试。

习题 6(简答题)

题目:简述大型 HarmonyOS 应用模块拆分的三种维度,以及各自的适用场景。

答案:三种拆分维度包括:按业务域拆分,每个业务域对应一个独立的模块,适用于业务边界清晰、团队按业务线划分的大型应用。按功能层拆分,将应用按技术职责分为 UI 层、业务逻辑层、数据访问层和基础设施层,适用于技术栈统一、需要严格控制分层边界的团队。按团队边界拆分,是康威定律在软件架构中的直接体现,每个团队负责的模块可以独立开发、独立测试、独立发布,适用于多团队协作、需要并行开发的大型项目。实际项目中三种维度通常组合使用:先按业务域拆分为顶层模块,每个业务域内部再按功能层拆分为子模块,最后根据团队边界确定模块的归属和维护责任。

解读:模块拆分的核心目标是高内聚低耦合。拆分不是越细越好,过度拆分会导致模块数量膨胀、接口复杂度上升、维护成本增加。拆分应基于业务边界、技术边界和团队边界,找到合适的平衡点。

习题 7(简答题)

题目:简述 HarmonyOS 应用 CI/CD 流水线的核心环节,以及性能门禁在其中的作用。

答案:CI/CD 流水线的核心环节包括:代码检查(运行 Code Linter 静态检测)、编译构建(执行 hvigorw assembleHap 构建 HAP 包)、单元测试(运行 Hypium 测试)、UI 测试(在模拟器或真机上运行 UI 自动化测试)、性能门禁(运行场景化性能测试,对比性能基线)、签名打包(配置发布签名构建正式 HAP 包)、上传分发(将 HAP 包上传到 AppGallery Connect 或内部测试平台)。性能门禁的作用是防止性能退化,设定性能基线(如冷启动 ≤3000ms、页面切换 ≤1000ms、帧率 ≥60 帧),每次代码合入前自动运行性能测试,低于基线则阻断合入。DevEco Testing 的性能基线管理能力可以自动记录内存占用、CPU 负载等关键指标,通过历史数据对比精准定位性能退化问题,在性能退化早期发出预警。

解读:性能门禁是 CI/CD 流水线中防止性能退化的关键手段。没有性能门禁,代码合入后性能可能悄悄退化,等到用户反馈时已经影响大量用户。将性能测试自动化、常态化,在性能退化早期就发现并修复问题。

八、本节知识点总结

模块拆分策略
三种拆分维度:按业务域拆分(业务边界清晰)、按功能层拆分(技术栈统一)、按团队边界拆分(多团队协作)。实际项目中三种维度组合使用:先按业务域拆顶层,内部再按功能层拆子模块,最后按团队边界确定归属。

依赖治理
优先使用系统能力,评估依赖必要性,定期清理无用依赖。使用overrides强制统一版本,开启resolve_conflict自动解决冲突。业务模块之间禁止直接依赖,公共模块不能依赖业务模块。

构建优化
模块化编译默认开启增量编译,hvigor 支持并行构建。配置构建缓存和useNormalizedOHMUrl优化构建效率。HSP 共享减少重复编译但需评估编译时间成本。

团队协作规范
代码分层约定明确各层职责,页面层不包含业务逻辑,ViewModel 层不操作 UI,数据层不含业务逻辑。命名规范、提交规范(Angular 格式)、Code Review 检查清单保障代码质量。

多环境配置管理
使用 product 机制定义开发、测试、生产环境,通过 BuildProfile 在代码中访问配置。环境配置集中到 AppConfig 统一管理,避免硬编码。

CI/CD 流水线
核心环节:代码检查、编译构建、单元测试、UI 测试、性能门禁、签名打包、上传分发。性能门禁设定性能基线,低于基线则阻断合入,防止性能退化。配置构建缓存和并行执行加速流水线。

下节预告
第11课将进入 ArkUI 应用的安全与合规进阶的学习,涵盖数据加密与安全存储、网络安全传输、权限最小化、隐私合规检测以及应用加固方案。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 7:44:47

Android开发环境搭建全攻略:JDK/SDK/Gradle配置与实战

1. 开篇:这个系列要做什么,环境为什么值得单独讲一课做啥子嘛,这四个字是四川话里特别日常的一句,意思就是"做什么呢""干嘛呢"。拿它当项目名,是因为这个系列要做的APP本身就是一个帮你解决"…

作者头像 李华
网站建设 2026/10/9 7:43:21

【Jetpack Compose基础语法学与练】第2课 State状态 + 点击交互

前言 上一节课我们完成最简HelloWorld,认识了 Composable 可组合函数、预览注解。 Compose声明式UI的核心:界面跟随状态自动更新。 本课重点学习状态定义、记忆状态、按钮点击事件,打通「状态‑重组‑界面刷新」完整闭环。 前置:完…

作者头像 李华
网站建设 2026/10/9 7:43:00

Maven从下载到配置全流程:环境变量、镜像加速与避坑指南

用过Java的人都绕不开Maven,但能把Maven顺顺利利装到本地的人,我还真没见过几个。多数人卡住的第一个环节就是“下载”,别笑,这个看似简单的步骤里全是坑:官网慢得像蜗牛、下载到一半断掉、好不容易下完了发现跟JDK版本…

作者头像 李华
网站建设 2026/10/9 7:41:22

基于遗传算法与粒子群算法的智能车动态避障路径规划技术深度学习实战python数据分析与可视化

1.2.2 国外研究现状国外对智能车路径规划技术的研究起步较早,早在20世纪80年代就已经开展了相关的研究工作。卡内基梅隆大学、麻省理工学院、斯坦福大学等高校是该领域的先驱,谷歌、特斯拉、通用汽车等公司也投入了大量资源进行相关技术的研发。在传统路…

作者头像 李华