功能函数与模块:组合层的单一职责
单一职责在接口层体现为原子化接口(只做封装+异常处理);在组合层体现为功能函数和模块——功能函数 = 数据结构 + 算法 + 接口,三个部分各司其职;模块 = 一个功能的完整组合。这一篇讲组合层的单一职责:数据、算法、接口怎么分开,怎么组合成一个完整的功能。
一、组合层的单一职责
接口层的单一职责是「原子化接口只做封装库接口 + 异常处理」:
1 2 3 4
| 原子化接口 = 封装库接口 + 异常处理 ✗ 不定义数据结构 ✗ 不实现算法 ✗ 不做业务逻辑
|
组合层的单一职责是「功能函数 = 数据结构 + 算法 + 接口」——三个部分各司其职:
1 2 3 4
| 功能函数 ├── 数据结构 ← 数据怎么表示(一个职责) ├── 算法 ← 怎么计算(一个职责) └── 接口 ← 怎么被调用(一个职责)
|
每个部分职责单一,组合起来是一个完整功能。
二、功能函数 = 数据结构 + 算法 + 接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| typedef struct { uint8_t* bytes; size_t size; } MemoryBlock;
ScanResult search_pattern(const MemoryBlock* mem, const uint8_t* pat, size_t len);
ScanResult scan_memory(const char* path, const uint8_t* pattern, size_t len) { int fd = open(path, O_RDONLY); MemoryBlock block = { (uint8_t*)mem, st.st_size }; ScanResult r = search_pattern(&block, pattern, len); close(fd); return r; }
|
三个部分分开的原因——单一职责:
1 2 3
| 数据结构:只负责「数据长什么样」,不关心怎么算 算法:只负责「怎么计算」,不关心数据在哪存、接口怎么调 接口:只负责「怎么被调用」,不关心实现
|
改数据结构不影响算法,换算法不影响数据结构,改接口不影响内部实现——这就是组合层单一职责的价值。
三、模块 = 一个功能的组合
模块是组合层更高一层的单元:
1 2 3 4
| 模块(一个功能) ├── 数据结构 ← 这个功能的数据 ├── 算法 ← 这个功能的计算 └── 原子化接口 ← 这个功能怎么被调用
|
1 2 3 4 5 6 7 8 9
| process_list 模块(进程列表功能): data/ ProcessInfo algorithm/ enum_processes api/ list_processes()
memory_scan 模块(内存扫描功能): data/ MemoryBlock / ScanResult algorithm/ search_pattern api/ scan_memory()
|
模块的单一职责 = 只负责一个功能。 一个模块只做一件事,模块内部三个部分各司其职。
四、模块 vs 组件 vs 子系统
组合层的粒度阶梯:
1 2 3 4 5
| 功能函数 = 数据 + 算法 + 接口(最小组合) 模块 = 一个功能的完整组合 组件 = 数据 + 算法 + 原子化接口(功能单元,模块的工程化) 子系统 = 一组相关功能(框架化/接口化后被调用) 系统 = 完整程序
|
1 2 3
| 功能 = 目的(解决什么问题) 模块/组件 = 功能的工程化封装(数据+算法+接口) 子系统 = 一组相关组件(有生命周期则框架化)
|
功能是目的,模块/组件是功能的工程化封装。 单一职责在每个粒度上都成立。
五、组合层的单一职责 vs 接口层的单一职责
1 2 3 4 5 6 7
| 接口层(原子化接口):只做封装 + 异常处理 → 一个原子化接口 = 一个库接口 + 异常处理 → 不含数据、不含算法
组合层(功能函数/模块):组合数据 + 算法 + 接口 → 一个功能 = 数据结构 + 算法 + 原子化接口 → 三个部分各司其职
|
1 2 3 4
| 原子化接口:safe_open / safe_mmap / safe_close(封装层) 功能函数:scan_memory = MemoryBlock + search_pattern + safe_*(组合层)
原子化接口被功能函数调用,功能函数被模块组合
|
六、和其他内容的关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 功能函数与模块 ←→ 单一职责原则(本主题 01) 01 讲原则,本线讲原则在组合层的实现
功能函数与模块 ←→ 原子化接口(本主题 02) 原子化接口是接口层(封装+异常) 功能函数/模块是组合层(数据+算法+接口)
功能函数与模块 ←→ 从指令到系统主线 主线第十二章讲模块三要素 = 本线核心
功能函数与模块 ←→ 数据结构 数据结构的 Domain/Core/Infrastructure 三层分类 就是模块内部「数据结构」部分的组织
功能函数与模块 ←→ 算法 算法类型与描述形式 = 模块内部「算法」部分的组织
|
收束
1 2 3 4 5 6 7 8 9 10 11 12 13
| 组合层的单一职责: 功能函数 = 数据结构 + 算法 + 接口(三个部分各司其职) 模块 = 一个功能的完整组合
分开的原因:改数据不影响算法,换算法不影响数据
粒度阶梯:功能函数 → 模块 → 组件 → 子系统 → 系统
接口层 vs 组合层: 原子化接口(封装+异常,不含数据算法) 功能函数/模块(数据+算法+接口的组合)
功能是目的,模块是功能的工程化封装
|
组合层的单一职责 = 数据结构、算法、接口各司其职,组合成一个完整功能。 这是单一职责在组合层的实现。