文章目录
-
-
- 每日一句正能量
- 一、引言:当嵌入式固件遇上领域驱动设计
- [二、DDD 核心概念在嵌入式中的映射](#二、DDD 核心概念在嵌入式中的映射)
-
- [2.1 四层架构的嵌入式适配](#2.1 四层架构的嵌入式适配)
- [2.2 限界上下文:划分业务边界](#2.2 限界上下文:划分业务边界)
- 三、聚合根:业务一致性的守护者
-
- [3.1 聚合根的本质](#3.1 聚合根的本质)
- [3.2 嵌入式 C 语言实现:电机控制聚合根](#3.2 嵌入式 C 语言实现:电机控制聚合根)
- 四、防腐层:隔离外部依赖
-
- [4.1 防腐层(ACL)设计](#4.1 防腐层(ACL)设计)
- 五、领域事件:跨上下文通信
-
- [5.1 领域事件机制](#5.1 领域事件机制)
- [六、HarmonyOS 中的 DDD 实践](#六、HarmonyOS 中的 DDD 实践)
- [七、DDD 在嵌入式中的价值评估](#七、DDD 在嵌入式中的价值评估)
- 八、实践建议与常见陷阱
-
- [8.1 实践建议](#8.1 实践建议)
- [8.2 常见陷阱](#8.2 常见陷阱)
- 九、总结
-

每日一句正能量
幸福的本质不是惊天动地的狂喜,而是持续收集微小雀跃的能力。
大脑对剧烈刺激会快速适应,但对日常生活中细小的积极体验------阳光、好听的歌、一杯热茶------如果能刻意留意并品味,幸福感会持续累积。幸福不是山顶的烟花,而是沿途捡拾的闪亮石子。
一、引言:当嵌入式固件遇上领域驱动设计
嵌入式开发有一个长期存在的痛点:业务逻辑与硬件细节深度耦合 。一个典型的"反模式"是:温度控制算法直接调用 HAL_ADC_Read(),电机调速逻辑里硬编码了 PWM 寄存器地址,状态机里混杂了按键扫描和 I2C 通信代码。当需要更换传感器型号、迁移到新的 MCU 平台、或者让非嵌入式背景的业务专家理解代码时,这种"面条式"代码的维护成本呈指数级增长。
领域驱动设计(Domain-Driven Design, DDD)由 Eric Evans 于 2003 年提出,最初面向企业级软件。其核心思想是:让软件结构匹配业务领域的结构,用业务语言(通用语言,Ubiquitous Language)驱动代码设计。
在 HarmonyOS 生态中,随着设备类型从单一 MCU 扩展到分布式多终端协同,固件的业务复杂度急剧上升。一个智能家居控制器可能需要同时管理传感器网络、执行器控制、用户交互、云端通信、OTA 升级等多个业务领域。DDD 提供了一套系统化的方法,帮助我们在资源受限的嵌入式环境中,依然保持代码的清晰结构和业务表达能力。
本文将深入探讨 DDD 的核心概念------限界上下文(Bounded Context)和聚合根(Aggregate Root)------如何在 C 语言嵌入式固件中落地,并给出完整的工程实践。
二、DDD 核心概念在嵌入式中的映射
2.1 四层架构的嵌入式适配

标准 DDD 推荐四层架构:用户接口层、应用层、领域层、基础设施层。 在嵌入式场景中,我们将其映射为:
| DDD 标准层 | 嵌入式映射 | 典型内容 |
|---|---|---|
| 用户接口层 | 交互接口层 | 按键扫描、串口命令解析、蓝牙 GATT 服务、LCD 菜单 |
| 应用层 | 应用协调层 | 任务调度、状态机编排、用例流程控制、跨聚合协调 |
| 领域层 | 领域核心层 | 聚合根、实体、值对象、领域服务、业务规则、不变性约束 |
| 基础设施层 | 硬件抽象层 | HAL 驱动、RTOS 接口、文件系统、网络协议栈、第三方 SDK |
核心原则:领域层不依赖任何具体技术实现,只通过抽象接口与硬件抽象层交互。这种"依赖倒置"确保了业务逻辑可以在不修改的情况下,更换底层硬件平台。
2.2 限界上下文:划分业务边界
限界上下文(Bounded Context)是 DDD 战略设计的核心概念。它定义了一个明确的边界,在这个边界内,领域模型、术语、业务规则具有唯一确定的含义。

以智能家居控制器为例,我们可以识别出以下限界上下文:
核心域(Core Domain):
- 设备管理上下文:管理传感器和执行器的生命周期、状态监控、配置管理
支撑域(Supporting Domain):
- 网络通信上下文:WiFi/蓝牙连接管理、协议解析、数据包收发
- 电源管理上下文:电池监测、功耗优化、休眠唤醒策略
- 固件升级上下文:OTA 下载、固件校验、版本管理
通用域(Generic Domain):
- 日志上下文:分级日志、环形缓冲区、远程输出
- 配置上下文:参数存储、持久化、运行时加载
- 安全上下文:加密解密、签名验证、访问控制
上下文映射关系:
- 核心域 ← 支撑域:通过**防腐层(ACL)**隔离,支撑域适配核心域接口
- 核心域 ← 通用域:通过**共享内核(Shared Kernel)**直接复用通用能力
- 支撑域之间:通过**领域事件(Domain Event)**异步通信,避免紧耦合
三、聚合根:业务一致性的守护者
3.1 聚合根的本质
聚合(Aggregate)是一组生命周期强一致、修改规则强关联的实体和值对象的集合。聚合根(Aggregate Root)是聚合中最核心的实体,外部只能通过聚合根来访问和修改聚合内的对象。

聚合根的核心职责:
- 身份标识 :具有全局唯一标识(如
motor_id) - 不变性约束守护:确保聚合内的业务规则始终满足
- 事务边界:所有对聚合内对象的修改必须通过聚合根,保证原子性
- 生命周期管理:创建、销毁聚合内的实体和值对象
3.2 嵌入式 C 语言实现:电机控制聚合根
c
/* motor_aggregate.h - 电机控制聚合根 */
#ifndef MOTOR_AGGREGATE_H
#define MOTOR_AGGREGATE_H
#include <stdint.h>
#include <stdbool.h>
/* ============================================================
* 值对象 (Value Object):不可变,通过属性值定义相等性
* ============================================================ */
/* 转速值对象 */
typedef struct {
int32_t rpm; /* 转速值 */
uint32_t max_rpm; /* 最大允许转速 */
} MotorSpeed_t;
/* 位置值对象 */
typedef struct {
int32_t angle_deg; /* 角度值 */
int32_t min_angle; /* 最小角度限制 */
int32_t max_angle; /* 最大角度限制 */
} MotorPosition_t;
/* 电流值对象 */
typedef struct {
uint32_t milliamps; /* 电流值(mA) */
uint32_t overcurrent_threshold; /* 过流阈值 */
} MotorCurrent_t;
/* 温度值对象 */
typedef struct {
int16_t celsius; /* 温度值(摄氏度) */
int16_t thermal_limit; /* 热保护阈值 */
} MotorTemperature_t;
/* ============================================================
* 实体 (Entity):具有本地标识,生命周期从属于聚合根
* ============================================================ */
/* 转速控制器实体 */
typedef struct {
uint8_t controller_id; /* 本地标识 */
MotorSpeed_t target_speed;
MotorSpeed_t actual_speed;
uint32_t kp, ki, kd; /* PID参数 */
void (*update_pid)(struct MotorSpeedController_* self,
MotorSpeed_t target, MotorSpeed_t actual);
} MotorSpeedController_t;
/* 位置反馈实体 */
typedef struct {
uint8_t encoder_id;
MotorPosition_t current_position;
uint32_t resolution; /* 编码器分辨率 */
int32_t (*read_encoder)(void); /* 读取编码器回调 */
} MotorPositionFeedback_t;
/* 电流监测实体 */
typedef struct {
uint8_t monitor_id;
MotorCurrent_t current;
uint32_t sampling_rate_hz;
void (*sample)(struct MotorCurrentMonitor_* self);
} MotorCurrentMonitor_t;
/* 温度保护实体 */
typedef struct {
uint8_t protector_id;
MotorTemperature_t temperature;
bool thermal_shutdown_active;
void (*check_thermal)(struct MotorThermalProtection_* self);
} MotorThermalProtection_t;
/* ============================================================
* 聚合根 (Aggregate Root):MotorAggregate_t
* 外部只能通过聚合根访问和修改聚合内对象
* ============================================================ */
typedef struct {
/* 聚合根全局唯一标识 */
uint32_t motor_id;
char motor_name[32];
/* 聚合内的实体(只能通过聚合根访问) */
MotorSpeedController_t speed_controller;
MotorPositionFeedback_t position_feedback;
MotorCurrentMonitor_t current_monitor;
MotorThermalProtection_t thermal_protection;
/* 聚合状态 */
bool is_enabled;
bool is_faulted;
uint32_t fault_code;
/* 领域事件(内部使用) */
void (*on_domain_event)(uint32_t motor_id, uint8_t event_type, void* data);
} MotorAggregate_t;
/* ============================================================
* 聚合根工厂方法
* ============================================================ */
MotorAggregate_t* MotorAggregate_Create(uint32_t motor_id,
const char* name,
uint32_t max_rpm,
int32_t min_angle,
int32_t max_angle,
uint32_t overcurrent_ma,
int16_t thermal_limit_c);
/* ============================================================
* 聚合根业务方法(唯一的外部访问入口)
* 所有方法内部保证不变性约束
* ============================================================ */
/* 设置目标转速(业务方法,非简单setter) */
int MotorAggregate_SetTargetSpeed(MotorAggregate_t* agg, int32_t rpm);
/* 设置目标位置(业务方法,包含运动规划) */
int MotorAggregate_SetTargetPosition(MotorAggregate_t* agg, int32_t angle_deg);
/* 使能/禁用电机 */
int MotorAggregate_Enable(MotorAggregate_t* agg, bool enable);
/* 周期更新(主循环调用) */
int MotorAggregate_Update(MotorAggregate_t* agg, uint32_t dt_ms);
/* 获取聚合状态(只读快照) */
int MotorAggregate_GetStatus(const MotorAggregate_t* agg,
MotorSpeed_t* speed,
MotorPosition_t* position,
MotorCurrent_t* current,
MotorTemperature_t* temp);
/* 清除故障 */
int MotorAggregate_ClearFault(MotorAggregate_t* agg);
/* 销毁聚合 */
void MotorAggregate_Destroy(MotorAggregate_t* agg);
#endif /* MOTOR_AGGREGATE_H */
c
/* motor_aggregate.c - 聚合根实现 */
#include \"motor_aggregate.h\"
#include <string.h>
#include <assert.h>
/* ============================================================
* 不变性约束检查(私有函数)
* ============================================================ */
/* 检查转速约束 */
static bool CheckSpeedInvariant(const MotorSpeed_t* speed) {
return (speed->rpm >= -(int32_t)speed->max_rpm) &&
(speed->rpm <= (int32_t)speed->max_rpm);
}
/* 检查位置约束 */
static bool CheckPositionInvariant(const MotorPosition_t* pos) {
return (pos->angle_deg >= pos->min_angle) &&
(pos->angle_deg <= pos->max_angle);
}
/* 检查电流约束 */
static bool CheckCurrentInvariant(const MotorCurrent_t* current) {
return current->milliamps < current->overcurrent_threshold;
}
/* 检查温度约束 */
static bool CheckTemperatureInvariant(const MotorTemperature_t* temp) {
return temp->celsius < temp->thermal_limit;
}
/* ============================================================
* 工厂方法
* ============================================================ */
MotorAggregate_t* MotorAggregate_Create(uint32_t motor_id,
const char* name,
uint32_t max_rpm,
int32_t min_angle,
int32_t max_angle,
uint32_t overcurrent_ma,
int16_t thermal_limit_c) {
MotorAggregate_t* agg = (MotorAggregate_t*)malloc(sizeof(MotorAggregate_t));
if (!agg) return NULL;
memset(agg, 0, sizeof(MotorAggregate_t));
/* 初始化聚合根标识 */
agg->motor_id = motor_id;
strncpy(agg->motor_name, name, sizeof(agg->motor_name) - 1);
/* 初始化值对象(不可变属性) */
agg->speed_controller.target_speed.max_rpm = max_rpm;
agg->speed_controller.actual_speed.max_rpm = max_rpm;
agg->position_feedback.current_position.min_angle = min_angle;
agg->position_feedback.current_position.max_angle = max_angle;
agg->current_monitor.current.overcurrent_threshold = overcurrent_ma;
agg->thermal_protection.temperature.thermal_limit = thermal_limit_c;
/* 初始化实体状态 */
agg->speed_controller.controller_id = 1;
agg->position_feedback.encoder_id = 1;
agg->current_monitor.monitor_id = 1;
agg->thermal_protection.protector_id = 1;
agg->is_enabled = false;
agg->is_faulted = false;
agg->fault_code = 0;
Log_Info(\"MotorAggregate created: id=%u, name=%s\", motor_id, name);
return agg;
}
/* ============================================================
* 业务方法实现
* ============================================================ */
/* 设置目标转速 */
int MotorAggregate_SetTargetSpeed(MotorAggregate_t* agg, int32_t rpm) {
if (!agg) return -EINVAL;
/* 业务规则1:故障状态下不允许设置转速 */
if (agg->is_faulted) {
Log_Warn(\"Motor %u: Cannot set speed while faulted (code=%u)\",
agg->motor_id, agg->fault_code);
return -EFAULT;
}
/* 业务规则2:未使能时允许设置但不生效 */
if (!agg->is_enabled) {
Log_Debug(\"Motor %u: Speed set to %d but motor not enabled\",
agg->motor_id, rpm);
}
/* 业务规则3:转速必须在允许范围内 */
MotorSpeed_t new_speed = {
.rpm = rpm,
.max_rpm = agg->speed_controller.target_speed.max_rpm
};
if (!CheckSpeedInvariant(&new_speed)) {
Log_Error(\"Motor %u: Speed %d exceeds limit +/-%u\",
agg->motor_id, rpm, new_speed.max_rpm);
return -ERANGE;
}
/* 业务规则4:转速变化率限制(防冲击) */
int32_t delta = rpm - agg->speed_controller.target_speed.rpm;
int32_t max_delta = (int32_t)new_speed.max_rpm / 10; /* 每周期最大变化10% */
if (delta > max_delta) {
rpm = agg->speed_controller.target_speed.rpm + max_delta;
Log_Warn(\"Motor %u: Speed change rate limited to %d\", agg->motor_id, rpm);
} else if (delta < -max_delta) {
rpm = agg->speed_controller.target_speed.rpm - max_delta;
Log_Warn(\"Motor %u: Speed change rate limited to %d\", agg->motor_id, rpm);
}
/* 应用变更 */
agg->speed_controller.target_speed.rpm = rpm;
/* 发布领域事件 */
if (agg->on_domain_event) {
uint8_t event_data[4];
memcpy(event_data, &rpm, sizeof(rpm));
agg->on_domain_event(agg->motor_id, EVENT_SPEED_CHANGED, event_data);
}
Log_Info(\"Motor %u: Target speed set to %d RPM\", agg->motor_id, rpm);
return 0;
}
/* 周期更新(主循环调用) */
int MotorAggregate_Update(MotorAggregate_t* agg, uint32_t dt_ms) {
if (!agg) return -EINVAL;
if (!agg->is_enabled) return 0;
if (agg->is_faulted) return -EFAULT;
/* 步骤1:读取传感器(通过抽象接口,不直接访问硬件) */
if (agg->position_feedback.read_encoder) {
int32_t raw = agg->position_feedback.read_encoder();
agg->position_feedback.current_position.angle_deg =
raw * 360 / (int32_t)agg->position_feedback.resolution;
}
/* 步骤2:电流采样 */
if (agg->current_monitor.sample) {
agg->current_monitor.sample(&agg->current_monitor);
}
/* 步骤3:温度检查 */
if (agg->thermal_protection.check_thermal) {
agg->thermal_protection.check_thermal(&agg->thermal_protection);
}
/* 步骤4:不变性约束检查 */
if (!CheckCurrentInvariant(&agg->current_monitor.current)) {
agg->is_faulted = true;
agg->fault_code = FAULT_OVERCURRENT;
Log_Error(\"Motor %u: OVERCURRENT fault! %u mA\",
agg->motor_id, agg->current_monitor.current.milliamps);
return -EFAULT;
}
if (!CheckTemperatureInvariant(&agg->thermal_protection.temperature)) {
agg->is_faulted = true;
agg->fault_code = FAULT_THERMAL;
agg->thermal_protection.thermal_shutdown_active = true;
Log_Error(\"Motor %u: THERMAL fault! %d C\",
agg->motor_id, agg->thermal_protection.temperature.celsius);
return -EFAULT;
}
if (!CheckPositionInvariant(&agg->position_feedback.current_position)) {
agg->is_faulted = true;
agg->fault_code = FAULT_POSITION_LIMIT;
Log_Error(\"Motor %u: POSITION LIMIT fault! %d deg\",
agg->motor_id, agg->position_feedback.current_position.angle_deg);
return -EFAULT;
}
/* 步骤5:PID控制计算 */
if (agg->speed_controller.update_pid) {
agg->speed_controller.update_pid(&agg->speed_controller,
agg->speed_controller.target_speed,
agg->speed_controller.actual_speed);
}
/* 步骤6:执行输出(通过抽象接口) */
/* ... 调用PWM输出接口 ... */
return 0;
}
/* 获取聚合状态(只读快照) */
int MotorAggregate_GetStatus(const MotorAggregate_t* agg,
MotorSpeed_t* speed,
MotorPosition_t* position,
MotorCurrent_t* current,
MotorTemperature_t* temp) {
if (!agg) return -EINVAL;
if (speed) memcpy(speed, &agg->speed_controller.actual_speed, sizeof(MotorSpeed_t));
if (position) memcpy(position, &agg->position_feedback.current_position, sizeof(MotorPosition_t));
if (current) memcpy(current, &agg->current_monitor.current, sizeof(MotorCurrent_t));
if (temp) memcpy(temp, &agg->thermal_protection.temperature, sizeof(MotorTemperature_t));
return 0;
}
四、防腐层:隔离外部依赖
4.1 防腐层(ACL)设计

防腐层(Anti-Corruption Layer, ACL)是 DDD 中用于隔离核心域与外部系统(第三方库、遗留系统、硬件驱动)的关键模式。其核心思想是:领域层只依赖抽象接口,具体实现由适配器提供。
c
/* sensor_reader_interface.h - 领域层定义的抽象接口 */
#ifndef SENSOR_READER_INTERFACE_H
#define SENSOR_READER_INTERFACE_H
#include <stdint.h>
/* 领域层定义的传感器读取接口 */
typedef struct {
/* 读取温度 */
int (*read_temperature)(void* self, int16_t* temp_c);
/* 读取湿度 */
int (*read_humidity)(void* self, uint16_t* humidity_pct);
/* 读取压力 */
int (*read_pressure)(void* self, uint32_t* pressure_pa);
/* 获取传感器状态 */
int (*get_status)(void* self, uint32_t* status);
/* 私有数据 */
void* private_data;
} SensorReader_Interface_t;
#endif
c
/* sht30_adapter.c - 防腐层:SHT30传感器适配器 */
#include \"sensor_reader_interface.h\"
#include \"sht30_driver.h\" /* 第三方厂商SDK */
/* 适配器私有数据 */
typedef struct {
uint8_t i2c_addr;
uint32_t last_read_time;
SHT30_Handle_t* driver_handle;
} SHT30_AdapterData_t;
/* 实现领域层接口:读取温度 */
static int SHT30_ReadTemperature(void* self, int16_t* temp_c) {
SensorReader_Interface_t* iface = (SensorReader_Interface_t*)self;
SHT30_AdapterData_t* data = (SHT30_AdapterData_t*)iface->private_data;
/* 调用第三方SDK */
float temp_raw;
int ret = SHT30_ReadTemperatureRaw(data->driver_handle, &temp_raw);
if (ret != 0) return ret;
/* 数据转换:浮点转定点(嵌入式优化) */
*temp_c = (int16_t)(temp_raw * 100); /* 0.01度分辨率 */
data->last_read_time = Platform_GetTickMs();
return 0;
}
/* 实现领域层接口:读取湿度 */
static int SHT30_ReadHumidity(void* self, uint16_t* humidity_pct) {
SensorReader_Interface_t* iface = (SensorReader_Interface_t*)self;
SHT30_AdapterData_t* data = (SHT30_AdapterData_t*)iface->private_data;
float hum_raw;
int ret = SHT30_ReadHumidityRaw(data->driver_handle, &hum_raw);
if (ret != 0) return ret;
*humidity_pct = (uint16_t)(hum_raw * 100); /* 0.01%分辨率 */
return 0;
}
/* 实现领域层接口:读取压力(SHT30无压力传感器,返回不支持) */
static int SHT30_ReadPressure(void* self, uint32_t* pressure_pa) {
(void)self;
(void)pressure_pa;
return -ENOTSUP; /* 该传感器不支持压力测量 */
}
/* 实现领域层接口:获取状态 */
static int SHT30_GetStatus(void* self, uint32_t* status) {
SensorReader_Interface_t* iface = (SensorReader_Interface_t*)self;
SHT30_AdapterData_t* data = (SHT30_AdapterData_t*)iface->private_data;
SHT30_Status_t drv_status;
int ret = SHT30_GetDriverStatus(data->driver_handle, &drv_status);
if (ret != 0) return ret;
/* 将厂商状态码映射为领域通用状态 */
*status = 0;
if (drv_status.is_busy) *status |= SENSOR_STATUS_BUSY;
if (drv_status.has_error) *status |= SENSOR_STATUS_ERROR;
if (drv_status.is_calibrated) *status |= SENSOR_STATUS_CALIBRATED;
return 0;
}
/* 工厂方法:创建SHT30适配器 */
SensorReader_Interface_t* SHT30_Adapter_Create(uint8_t i2c_addr) {
SensorReader_Interface_t* iface = (SensorReader_Interface_t*)malloc(sizeof(SensorReader_Interface_t));
SHT30_AdapterData_t* data = (SHT30_AdapterData_t*)malloc(sizeof(SHT30_AdapterData_t));
if (!iface || !data) {
free(iface);
free(data);
return NULL;
}
data->i2c_addr = i2c_addr;
data->driver_handle = SHT30_Init(i2c_addr); /* 初始化厂商SDK */
iface->read_temperature = SHT30_ReadTemperature;
iface->read_humidity = SHT30_ReadHumidity;
iface->read_pressure = SHT30_ReadPressure;
iface->get_status = SHT30_GetStatus;
iface->private_data = data;
Log_Info(\"SHT30 adapter created at I2C addr 0x%02X\", i2c_addr);
return iface;
}
防腐层的价值:
- 当从 SHT30 更换为 BME280 传感器时,只需替换适配器实现,领域层代码完全不变
- 领域层单元测试可以使用 Mock 适配器,无需真实硬件
- 第三方 SDK 的版本升级不会影响领域层
五、领域事件:跨上下文通信
5.1 领域事件机制

领域事件(Domain Event)表示领域中发生了某些重要的事情,通常用过去时态命名,如 DeviceOnline、ConfigChanged、MotorFaulted。
在嵌入式场景中,领域事件用于:
- 跨限界上下文的异步通信
- 状态变更的广播通知
- 审计日志的记录触发
- 告警系统的触发源
c
/* domain_event.h - 领域事件框架 */
#ifndef DOMAIN_EVENT_H
#define DOMAIN_EVENT_H
#include <stdint.h>
#define MAX_EVENT_LISTENERS 8
#define MAX_EVENT_QUEUE_SIZE 32
/* 领域事件类型 */
typedef enum {
EVENT_NONE = 0,
EVENT_DEVICE_ONLINE,
EVENT_DEVICE_OFFLINE,
EVENT_CONFIG_CHANGED,
EVENT_MOTOR_SPEED_CHANGED,
EVENT_MOTOR_FAULTED,
EVENT_SENSOR_READING,
EVENT_BATTERY_LOW,
EVENT_OTA_AVAILABLE,
EVENT_MAX
} DomainEventType_t;
/* 领域事件 */
typedef struct {
DomainEventType_t type;
uint32_t timestamp;
uint32_t source_id; /* 事件源(如聚合根ID) */
uint8_t payload[32]; /* 事件载荷 */
uint8_t payload_len;
} DomainEvent_t;
/* 事件监听器回调 */
typedef void (*EventListener_t)(const DomainEvent_t* event, void* user_data);
/* API */
int DomainEvent_Init(void);
int DomainEvent_Subscribe(DomainEventType_t type, EventListener_t listener, void* user_data);
int DomainEvent_Unsubscribe(DomainEventType_t type, EventListener_t listener);
int DomainEvent_Publish(const DomainEvent_t* event);
int DomainEvent_Process(void); /* 主循环中调用,分发事件 */
#endif
c
/* domain_event.c - 领域事件实现 */
#include \"domain_event.h\"
#include <string.h>
/* 环形事件队列 */
static DomainEvent_t g_eventQueue[MAX_EVENT_QUEUE_SIZE];
static uint8_t g_queueHead = 0;
static uint8_t g_queueTail = 0;
static uint8_t g_queueCount = 0;
/* 监听器注册表 */
typedef struct {
EventListener_t listener;
void* user_data;
bool active;
} ListenerEntry_t;
static ListenerEntry_t g_listeners[EVENT_MAX][MAX_EVENT_LISTENERS];
int DomainEvent_Init(void) {
memset(g_eventQueue, 0, sizeof(g_eventQueue));
memset(g_listeners, 0, sizeof(g_listeners));
g_queueHead = g_queueTail = g_queueCount = 0;
return 0;
}
int DomainEvent_Subscribe(DomainEventType_t type, EventListener_t listener, void* user_data) {
if (type >= EVENT_MAX || !listener) return -EINVAL;
for (uint8_t i = 0; i < MAX_EVENT_LISTENERS; i++) {
if (!g_listeners[type][i].active) {
g_listeners[type][i].listener = listener;
g_listeners[type][i].user_data = user_data;
g_listeners[type][i].active = true;
Log_Info(\"Event listener registered for type %u\", type);
return 0;
}
}
return -ENOSPC; /* 监听器已满 */
}
int DomainEvent_Publish(const DomainEvent_t* event) {
if (!event || event->type >= EVENT_MAX) return -EINVAL;
/* 检查队列是否满 */
if (g_queueCount >= MAX_EVENT_QUEUE_SIZE) {
Log_Warn(\"Event queue full, dropping event type %u\", event->type);
return -EAGAIN;
}
/* 写入队列 */
uint8_t idx = g_queueTail % MAX_EVENT_QUEUE_SIZE;
memcpy(&g_eventQueue[idx], event, sizeof(DomainEvent_t));
g_eventQueue[idx].timestamp = Platform_GetTickMs();
g_queueTail++;
g_queueCount++;
return 0;
}
/* 主循环中调用,分发事件 */
int DomainEvent_Process(void) {
while (g_queueCount > 0) {
uint8_t idx = g_queueHead % MAX_EVENT_QUEUE_SIZE;
DomainEvent_t* event = &g_eventQueue[idx];
/* 分发到所有监听器 */
for (uint8_t i = 0; i < MAX_EVENT_LISTENERS; i++) {
if (g_listeners[event->type][i].active) {
g_listeners[event->type][i].listener(event,
g_listeners[event->type][i].user_data);
}
}
g_queueHead++;
g_queueCount--;
}
return 0;
}
使用示例:
c
/* 日志上下文订阅设备状态变更 */
static void OnDeviceStateChanged(const DomainEvent_t* event, void* user_data) {
(void)user_data;
switch (event->type) {
case EVENT_DEVICE_ONLINE:
Log_Info(\"Device %u came online at %u\", event->source_id, event->timestamp);
break;
case EVENT_DEVICE_OFFLINE:
Log_Warn(\"Device %u went offline at %u\", event->source_id, event->timestamp);
break;
case EVENT_MOTOR_FAULTED:
Log_Error(\"Motor %u faulted! Code: %u\", event->source_id, event->payload[0]);
break;
default:
break;
}
}
/* 初始化时注册监听器 */
void LoggingContext_Init(void) {
DomainEvent_Subscribe(EVENT_DEVICE_ONLINE, OnDeviceStateChanged, NULL);
DomainEvent_Subscribe(EVENT_DEVICE_OFFLINE, OnDeviceStateChanged, NULL);
DomainEvent_Subscribe(EVENT_MOTOR_FAULTED, OnDeviceStateChanged, NULL);
}
六、HarmonyOS 中的 DDD 实践
在 HarmonyOS 生态中,DDD 可以与分布式能力深度结合:
c
/* harmonyos_ddd_device_manager.c - HarmonyOS分布式设备管理 */
#include \"distributed_scheduler.h\"
#include \"softbus_bus_center.h\"
/* 设备聚合根(分布式场景) */
typedef struct {
/* 本地标识 */
uint32_t local_device_id;
char device_name[64];
/* 分布式标识 */
char network_id[64];
NodeState_t distributed_state;
/* 能力集合(值对象) */
DeviceCapability_t capabilities;
/* 子设备聚合(本地连接的设备) */
MotorAggregate_t* motors[4];
SensorReader_Interface_t* sensors[8];
/* 领域事件发布 */
void (*publish_event)(DomainEventType_t type, uint32_t source_id, const void* data, uint8_t len);
} DistributedDeviceAggregate_t;
/* 分布式设备发现(领域服务) */
int DistributedDevice_DiscoverPeers(DistributedDeviceAggregate_t* device) {
/* 通过HarmonyOS软总线发现同组设备 */
DeviceInfo* peers = NULL;
uint32_t peer_count = 0;
int ret = SoftBus_GetAllNodeDeviceInfo(device->network_id, &peers, &peer_count);
if (ret != 0) return ret;
for (uint32_t i = 0; i < peer_count; i++) {
/* 为每个发现的设备创建领域事件 */
DomainEvent_t event = {
.type = EVENT_DEVICE_ONLINE,
.source_id = HashDeviceId(peers[i].devId),
.payload_len = strlen(peers[i].devId)
};
memcpy(event.payload, peers[i].devId, event.payload_len);
DomainEvent_Publish(&event);
}
SoftBus_FreeNodeDeviceInfo(peers);
return 0;
}
/* 分布式任务迁移(跨聚合协调) */
int DistributedDevice_MigrateTask(DistributedDeviceAggregate_t* from_device,
uint32_t task_id,
const char* target_device_id) {
/* 1. 保存任务状态 */
TaskStateSnapshot_t snapshot;
Task_SaveState(task_id, &snapshot);
/* 2. 序列化状态 */
uint8_t serialized[256];
uint16_t len = SerializeTaskState(&snapshot, serialized, sizeof(serialized));
/* 3. 通过软总线发送迁移请求 */
SoftBusMessage_t msg = {
.type = SOFTBUS_MSG_TYPE_DATA,
.channel = \"task_migration\",
.payload = serialized,
.payloadLen = len
};
int ret = SoftBus_SendMessage(target_device_id, &msg, NULL, 0);
if (ret != 0) {
Log_Error(\"Task migration failed: %d\", ret);
return ret;
}
/* 4. 发布领域事件 */
DomainEvent_t event = {
.type = EVENT_TASK_MIGRATED,
.source_id = from_device->local_device_id,
.payload_len = sizeof(task_id)
};
memcpy(event.payload, &task_id, sizeof(task_id));
DomainEvent_Publish(&event);
return 0;
}
七、DDD 在嵌入式中的价值评估

| 维度 | 传统分层 | DDD分层 | 提升说明 |
|---|---|---|---|
| 可维护性 | 5 | 8 | 业务逻辑集中,修改影响范围可控 |
| 可测试性 | 4 | 9 | 依赖接口可Mock,无需真实硬件 |
| 可移植性 | 5 | 9 | 硬件抽象隔离,换平台只需换适配器 |
| 业务清晰度 | 3 | 9 | 代码结构直接反映业务结构 |
| 团队协作 | 4 | 8 | 业务专家与开发者使用同一语言 |
| 资源效率 | 8 | 6 | 函数指针和抽象层带来轻微开销 |
结论 :DDD 在嵌入式中的核心价值不是性能优化,而是长期可维护性和团队协作效率。对于业务复杂、生命周期长、需要多人协作的嵌入式项目,DDD 的投入产出比极高。
八、实践建议与常见陷阱
8.1 实践建议
- 从核心域开始:不要试图一次性对所有代码应用 DDD,先选择业务最复杂、变更最频繁的核心域
- 保持适度:嵌入式资源受限,不要过度设计。值对象可以用结构体,聚合根可以用结构体+函数指针
- 接口优先:领域层只依赖接口,具体实现放在硬件抽象层
- 事件异步:领域事件使用环形缓冲区,避免阻塞主循环
- 文档同步:用 ADR(架构决策记录)记录限界上下文的划分理由
8.2 常见陷阱
| 陷阱 | 表现 | 解决方案 |
|---|---|---|
| 贫血模型 | 聚合根只有数据没有行为,变成"结构体容器" | 将业务方法放入聚合根,实现充血模型 |
| 过度聚合 | 一个聚合包含过多实体,事务边界过大 | 按业务不变性约束拆分聚合 |
| 跨聚合引用 | 直接持有其他聚合根的指针 | 使用 ID 引用,通过领域服务协调 |
| 领域泄漏 | 应用层直接调用硬件驱动 | 严格分层,应用层只调用领域层接口 |
| 事件滥用 | 所有通信都用事件,导致系统难以追踪 | 只在真正需要解耦的场景使用事件 |
九、总结
领域驱动设计不是 Java 或 C# 的专利,在 C 语言嵌入式固件中同样可以落地。通过限界上下文划分业务边界、通过聚合根保证业务一致性、通过防腐层隔离外部依赖、通过领域事件实现跨上下文通信,我们可以在资源受限的 MCU 上构建出结构清晰、业务表达力强、长期可维护的固件架构。
在 HarmonyOS 分布式生态中,DDD 的价值更加凸显:当多个设备协同工作时,清晰的领域边界和一致的通用语言,是避免"分布式 spaghetti code"的关键。
转载自:https://blog.csdn.net/u014727709/article/details/162629758
欢迎 👍点赞✍评论⭐收藏,欢迎指正