功能函数与模块:组合层的单一职责

单一职责在接口层体现为原子化接口(只做封装+异常处理);在组合层体现为功能函数和模块——功能函数 = 数据结构 + 算法 + 接口,三个部分各司其职;模块 = 一个功能的完整组合。这一篇讲组合层的单一职责:数据、算法、接口怎么分开,怎么组合成一个完整的功能。


一、组合层的单一职责

接口层的单一职责是「原子化接口只做封装库接口 + 异常处理」:

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 组合层:
原子化接口(封装+异常,不含数据算法)
功能函数/模块(数据+算法+接口的组合)

功能是目的,模块是功能的工程化封装

组合层的单一职责 = 数据结构、算法、接口各司其职,组合成一个完整功能。 这是单一职责在组合层的实现。