Appearance
10_Engineering/04 - 模块化架构
1. 为什么需要模块化
HarmonyOS 大型应用(如金融、电商、社交类应用)往往包含数十个功能模块。没有模块化的代码库会导致:
- 编译时间过长(全量编译 vs 增量编译)
- 代码耦合严重,修改一处影响多处
- 团队协作困难,合并冲突频繁
- 无法独立测试和部署子功能
- 不同团队重复造轮子
2. 模块化策略
2.1 分层架构
┌─────────────────────────────────────────┐
│ Entry (应用层 / UI层) │
│ Index.ets | LoginPage.ets | Home.ets │
├─────────────────────────────────────────┤
│ Feature (业务逻辑层 / Feature模块) │
│ network/ │ pay/ │ search/ │ cart/ │
├─────────────────────────────────────────┤
│ Common (公共层 / 共享库) │
│ common/ │ ui-kit/ │ logger/ │
├─────────────────────────────────────────┤
│ Kernel (内核层 / 基础库) │
│ crypto/ │ cache/ │ config/ │
└─────────────────────────────────────────┘2.2 模块化原则
| 原则 | 说明 |
|---|---|
| 单一职责 | 每个模块只负责一个业务域 |
| 高内聚低耦合 | 模块内部紧密,模块之间松散 |
| 依赖方向 | 上层依赖下层,不允许反向依赖 |
| 独立编译 | 每个模块可独立编译、独立测试 |
| 接口隔离 | 通过 ArkTS 接口(interface)暴露能力 |
3. 组件化架构
3.1 组件化 vs 模块化
| 维度 | 模块化(Module) | 组件化(Component) |
|---|---|---|
| 粒度 | 模块级(HAR/HSP) | 组件级(独立可复用单元) |
| 编译 | Hvigor 多模块 | 可独立 App 或库 |
| 耦合 | 通过依赖引用 | 通过接口/路由 |
| 测试 | 模块内测试 | 组件可独立测试 |
| 复用 | 编译时复用 | 运行时复用 + 编译时复用 |
| 适用规模 | 中小项目 | 大型项目、多产品线 |
3.2 组件架构示例
MyApp/
├── entry/ # Entry HAP - 主应用壳
├── feature-home/ # HAR - 首页模块
│ ├── src/main/ets/
│ │ ├── HomePage.ets
│ │ ├── HomeViewModel.ets
│ │ └── HomeRouter.ets # 模块路由
├── feature-search/ # HAR - 搜索模块
├── feature-cart/ # HAR - 购物车模块
├── feature-pay/ # HSP - 支付模块(需动态加载)
├── common-core/ # HAR - 核心公共库
├── common-ui/ # HSP - UI 组件库
├── network/ # HAR - 网络层
└── crypto/ # HAR - 加密模块3.3 模块间通信
方式一:接口依赖(推荐)
typescript
// common-ui/src/main/ets/interfaces/IButton.ets
export interface IButton {
onClick(): void;
setText(text: string): void;
}
// feature-home/src/main/ets/HomePage.ets
import { IButton } from '@ohos/common-ui';
@Component
struct HomePage {
@State message: string = '';
build() {
Column() {
MyButton({
onClick: () => { this.message = 'Hello'; },
text: 'Click Me'
})
}
}
}方式二:路由分发(组件解耦)
typescript
// common-core/src/main/ets/router/RouteManager.ets
import { router } from '@kit.ArkUI';
export class RouteManager {
static navigate(page: string, params?: object): void {
switch (page) {
case 'search':
router.pushUrl({ url: 'feature-search:SearchPage', params });
break;
case 'cart':
router.pushUrl({ url: 'feature-cart:CartPage', params });
break;
case 'pay':
router.pushUrl({ url: 'feature-pay:PayPage', params });
break;
}
}
}
// feature-home 中调用
RouteManager.navigate('search', { keyword: '手机' });方式三:事件总线(跨模块通信)
typescript
// common-core/src/main/ets/event/EventBus.ets
export class EventBus {
private static instance: EventBus | null = null;
private listeners: Map<string, Function[]> = new Map();
static getInstance(): EventBus {
if (!this.instance) {
this.instance = new EventBus();
}
return this.instance;
}
on(event: string, callback: Function): void {
if (!this.listeners.has(event)) {
this.listeners.set(event, []);
}
this.listeners.get(event)!.push(callback);
}
emit(event: string, data?: any): void {
const cbs = this.listeners.get(event) || [];
cbs.forEach(cb => cb(data));
}
}
// 模块 A 监听
EventBus.getInstance().on('orderPlaced', (order: Order) => {
console.info('收到订单通知:', order.id);
});
// 模块 B 发送
EventBus.getInstance().emit('orderPlaced', order);4. 多模块管理
4.1 依赖管理
json5
// oh-package.json5
{
"dependencies": {
"feature-home": { "path": "./feature-home" },
"feature-search": { "path": "./feature-search" },
"feature-pay": { "path": "./feature-pay" },
"common-core": { "path": "./common-core" },
"common-ui": { "path": "./common-ui" },
"network": { "path": "./network" }
}
}4.2 构建配置
json5
// build-profile.json5
{
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [{ "name": "default", "applyToProducts": ["default"] }]
},
{
"name": "feature-home",
"srcPath": "./feature-home",
"targets": [{ "name": "default", "applyToProducts": ["default"] }]
},
{
"name": "feature-search",
"srcPath": "./feature-search",
"targets": [{ "name": "default", "applyToProducts": ["default"] }]
},
{
"name": "common-core",
"srcPath": "./common-core",
"targets": [{ "name": "default", "applyToProducts": ["default"] }]
},
{
"name": "common-ui",
"srcPath": "./common-ui",
"type": "shared",
"targets": [{ "name": "default", "applyToProducts": ["default"] }]
}
]
}4.3 模块职责分离表
| 模块 | 类型 | 职责 | 对外接口 |
|---|---|---|---|
feature-home | HAR | 首页业务逻辑 | HomePage, HomeViewModel |
feature-search | HAR | 搜索业务逻辑 | SearchPage, SearchViewModel |
feature-pay | HSP (dynamicLoad) | 支付业务逻辑 | PayPage, PayService |
common-core | HAR | 路由、事件、常量 | RouteManager, EventBus, Constants |
common-ui | HSP (dynamicShare) | UI 组件库 | IButton, Input, Card 等 |
network | HAR | HTTP 请求封装 | HttpClient, ApiResponse |
crypto | HAR | 加密、签名 | CryptoUtils, Encryptor |
5. 模块化最佳实践
5.1 目录规范
feature-home/
├── src/main/
│ ├── ets/
│ │ ├── HomePage.ets
│ │ ├── HomeViewModel.ets
│ │ ├── model/
│ │ │ └── BannerItem.ets
│ │ └── api/
│ │ └── HomeApi.ets
│ ├── resources/
│ └── module.json5
├── hvigorfile.ts
├── build-profile.json5
└── README.md # 模块使用说明5.2 接口定义规范
typescript
// feature-home/src/main/ets/api/IHomeApi.ets
/** 首页数据接口 */
export interface IHomeApi {
/** 获取首页数据 */
getHomeData(): Promise<HomeData>;
/** 获取推荐列表 */
getRecommendList(page: number): Promise<RecommendItem[]>;
/** 下拉刷新 */
refresh(): Promise<void>;
}
// 实现
export class HomeApiImpl implements IHomeApi {
async getHomeData(): Promise<HomeData> {
const response = await Network.get('/api/home');
return response.data as HomeData;
}
async getRecommendList(page: number): Promise<RecommendItem[]> {
const response = await Network.get('/api/recommend', { page });
return response.data as RecommendItem[];
}
async refresh(): Promise<void> {
// refresh logic
}
}6. 面试高频考点
Q1: 模块化和组件化有什么区别?
回答要点:
- 模块化是编译时概念(HAR/HSP 模块)
- 组件化是架构设计概念,模块是组件化的实现手段
- 组件化更强调独立、可替换、可复用
- 组件通过接口/路由解耦,模块通过依赖管理
Q2: 多模块间如何通信?
回答要点:
- 接口依赖:通过 ArkTS interface 定义,编译期类型检查
- 路由分发:通过 RouteManager 统一路由,降低耦合
- 事件总线:跨模块发布/订阅模式
- 推荐优先使用接口依赖,其次路由,最后事件总线
Q3: 如何防止模块间循环依赖?
回答要点:
- Hvigor 在编译期会检测循环依赖并报错
- 使用接口隔离:A 依赖 B 的 interface,B 不依赖 A
- 将共享接口提取到独立的 core 模块
- 代码审查 + 静态检查工具
7. Android 对比
| 概念 | Android | HarmonyOS |
|---|---|---|
| 模块化 | Gradle 多 module | Hvigor 多 module |
| 静态库 | .aar | HAR |
| 动态库 | N/A(通过 Dynamic Feature) | HSP |
| 组件通信 | Interface / EventBus / Room | Interface / EventBus / 路由 |
| 依赖管理 | Gradle / Maven / JitPack | oh-package.json5 / ArkPackage |