在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

掌握 HAR/HSP 模块化体系、建立接口契约与依赖倒置规范、落地路由解耦与 DI 注入、让多团队协作的大型工程可持续演进


一、前置思考:模块化是"大型工程的生存方式"

1.1 单模块巨兽的困境

问题 表现
编译慢 改一行全量编译(第 38 篇联动)
冲突多 多人改同一文件频繁冲突
测试难 无法独立验证模块
复用差 代码无法跨业务复用
失控 依赖纠缠成"意大利面条"

核心认知:工程规模到一定程度,模块化不是选择,是生存方式

1.2 模块化的收益

维度 单模块 模块化
编译 全量 32 分钟 增量 40 秒
协作 全队抢同一文件 模块自治
测试 全量回归 模块独立测试
复用 复制粘贴 HAR 共享
交付 整体发布 HSP 按需

1.3 模块化的原则

高内聚: 一个模块只做一件事, 内部紧密
低耦合: 模块间只通过接口通信, 不互相依赖实现
依赖倒置: 上层依赖抽象(接口), 不依赖具体实现

二、核心原理:HAR / HSP / HAP

2.1 三类模块

类型 全称 特点 用途
HAP Harmony Ability Package 可独立运行 应用入口/页面
HAR Harmony Archive 静态库, 编译时打包 代码/资源共享
HSP Harmony Shared Package 动态库, 运行时加载 动态交付/共享

2.2 模块依赖关系

HAP (entry) ──► HAR (common/ui)  ──► 编译期合并
HAP (entry) ──► HSP (feature_x)  ──► 运行期按需加载
HAR ──► HAR (可嵌套, 注意循环)
HSP ──► HAR (共享包可依赖静态库)

关键约束

  • HAR 之间禁止循环依赖;
  • HSP 不依赖 HAP(反向依赖会破坏动态性);
  • 依赖方向单向:上层 → 下层。

2.3 高内聚低耦合的设计

                     ┌────────────┐
                     │  entry HAP  │  (编排层: 只做组装)
                     └─────┬──────┘
         ┌─────────────────┼─────────────────┐
         ▼                 ▼                 ▼
   ┌──────────┐      ┌──────────┐      ┌──────────┐
   │ feature_1 │      │ feature_2 │      │ feature_3 │  (业务模块: 各自内聚)
   └─────┬────┘      └─────┬────┘      └─────┬────┘
         └──────────┐      │      ┌──────────┘
                    ▼      ▼      ▼
              ┌─────────────────────┐
              │  core 基础层         │  (common/network/data/ui)
              │  (稳定, 少变更)       │
              └─────────────────────┘

三、源码/API 深度解析:落地四大规范

3.1 接口契约设计

原则:模块间只通过显式接口通信,不直接访问对方内部。

// 契约模块 (contract): 定义模块对外接口
// module: feature_shop/contract
export interface ShopService {
  getProducts(category: string): Promise<Product[]>;
  getProductDetail(id: string): Promise<ProductDetail>;
}

// 实现模块 (impl): 实现契约
// module: feature_shop/impl
export class ShopServiceImpl implements ShopService {
  getProducts(category: string): Promise<Product[]> {
    return network.fetch('/shop/products?cat=' + category);
  }
  getProductDetail(id: string): Promise<ProductDetail> {
    return network.fetch('/shop/detail/' + id);
  }
}

契约规范

  1. 契约接口放独立模块(contract 包),实现与使用方都依赖契约;
  2. 接口方法必须有完整类型定义(禁止 any);
  3. 接口变更 = 契约变更 = 需要评审;
  4. 版本管理:契约升级向后兼容。

3.2 依赖倒置(DIP)

// ❌ 上层直接依赖具体实现 (耦合)
import { UserApiImpl } from '../../feature_user/impl/UserApiImpl';
class OrderPage {
  private api = new UserApiImpl();   // 直接 new 实现
}

// ✅ 依赖倒置: 上层依赖抽象接口
import { UserApi } from '../../feature_user/contract/UserApi';
class OrderPage {
  private api: UserApi;
  constructor(api: UserApi) {
    this.api = api;   // 由外部注入(DI)
  }
}

依赖倒置的收益

  • 替换实现零改动(mock/新实现);
  • 测试可注入假实现;
  • 依赖方向清晰可控。

3.3 路由解耦

原则:模块间跳转通过路由表,不直接 import 对方页面。

// 路由注册 (各模块注册自己的页面)
// module: feature_shop
routerMap.register('shop/home', () => {
  return 'pages/ShopHome';   // 页面路径(可配合动态import)
});
routerMap.register('shop/detail', () => {
  return 'pages/ShopDetail';
});

// 路由跳转 (任意模块, 只依赖路由表)
// module: entry
import { router } from '@kit.ArkUI';

function goShop(): void {
  const url = routerMap.resolve('shop/home');
  router.pushUrl({ url: url, params: { from: 'entry' } });
}

路由解耦的收益

  • 模块间零直接依赖;
  • 新增/替换页面不改调用方;
  • 可统一做登录拦截/埋点/降级。

3.4 DI 注入(轻量实现)

// 轻量 DI 容器
export class ServiceLocator {
  private static services: Map<string, Object> = new Map();

  static register<T>(key: string, impl: T): void {
    this.services.set(key, impl as Object);
  }

  static get<T>(key: string): T {
    return this.services.get(key) as T;
  }
}

// 启动时注册实现
ServiceLocator.register<ShopService>('ShopService', new ShopServiceImpl());

// 任意模块获取(只依赖接口类型)
const shopService = ServiceLocator.get<ShopService>('ShopService');
shopService.getProducts('phone');

DI 纪律

  • 容器只存接口 → 实现映射;
  • 注册集中在 App 启动期(组合根);
  • 避免过度注入(对象越多,启动越慢)。

3.5 模块通信

场景 手段 说明
同进程模块间 接口直调 通过契约接口
页面跳转 路由表 解耦
跨模块事件 事件总线 解耦广播
跨进程/设备 分布式总线 第 27 篇联动
数据共享 公共数据层 单一数据源

四、企业级实战:多团队协作架构

4.1 模块划分方法论

步骤 动作
① 业务域分析 按业务域划分(电商: 商品/订单/支付/用户)
② 通用层下沉 公共能力下沉 core(网络/数据/UI/工具)
③ 依赖梳理 明确模块依赖 DAG, 消除循环
④ 契约先行 先定接口契约再并行开发
⑤ 交付模式 核心 HAR 静态, 低频业务 HSP 动态

4.2 团队与模块映射

团队A ──► feature_shop (商品/购物车)
团队B ──► feature_order (订单/售后)
团队C ──► feature_user (用户/会员)
团队D ──► core 基础层 (公共能力, 变更评审制)

协作规则

  • 各团队只改自己模块;
  • core 变更需全局评审(影响所有人);
  • 契约变更需双方团队确认;
  • 每周模块依赖健康度巡检。

4.3 拆分收益评估

指标 拆分前 拆分后
增量编译 32 分钟 40 秒
模块独立测试 不支持 支持
代码冲突 高频 低频
复用 复制粘贴 HAR 共享
交付 整体发布 HSP 按需

4.4 架构治理

治理项 手段
依赖环检测 CI 自动检测循环依赖
模块边界检查 禁止跨模块 import 实现
契约变更评审 契约变更走评审
模块健康度 依赖数/变更频率监控
架构守护 架构测试(ArchUnit 风格)

五、排查与优化:架构问题定位

5.1 架构腐化信号

信号 危害 对策
循环依赖 构建警告/死锁 拆出公共依赖
上帝模块 单模块过大 拆分
跨层访问 业务直连数据库 分层约束
重复代码 多份实现 下沉 core
依赖扩散 改一处动全身 契约收敛

5.2 高频坑点速查

  • 模块间是否只通过接口通信?
  • 是否存在循环依赖?
  • 是否存在业务模块直连基础实现?
  • 页面跳转是否走路由表?
  • 依赖是否倒置(依赖抽象)?
  • 契约接口是否有完整类型定义?
  • 是否用 DI 解耦了实现?
  • core 变更是否有评审机制?
  • 低频业务是否用了 HSP 动态交付?
  • CI 是否检测依赖环?

六、总结与进阶

6.1 收益模型(参考实测)

指标 拆分前 拆分后 提升
增量编译 32 分钟 40 秒 -98%
周代码冲突 45 次 4 次 -91%
模块独立测试 不支持 全支持 100%
新功能交付 2 周 3 天 -79%

6.2 工程规范

  1. 契约先行:先定接口再开发;
  2. 依赖倒置:上层依赖抽象;
  3. 路由解耦:页面跳转走路由表;
  4. core 评审:基础层变更评审制;
  5. 架构守护:依赖环/边界 CI 自动检测(第 44 篇联动)。

6.3 进阶方向

  • HSP 动态交付深度:按需下载与版本管理(第 35 篇联动);
  • 微前端思路:页面级动态化交付;
  • 架构测试:架构规则自动化断言;
  • 多端模块复用:一套模块适配多设备(第 7 赛道联动)。

附:Demo 演示说明

Tab 演示内容
🧩 模块分层 HAP/HAR/HSP 三类模块 + 分层架构图
🔗 依赖DAG 依赖图优化前后对比(消除循环/收敛扩散)
📜 接口契约 契约接口定义 + 实现 + 依赖倒置代码演示
🔄 路由解耦 路由注册/解析/跳转 流程演示
📊 架构治理 腐化信号清单 + 拆分收益对比
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐