构建稳健的系统模型需要对信息的捕获、移动和保留方式采取严谨的方法。在数据流图(DFD)的背景下,数据存储代表了系统持久性的核心。如果没有明确的数据存储位置设计,信息的流动将保持抽象且无法实现。本指南探讨了在DFD中设计数据存储的核心原则,确保清晰性、准确性以及与系统架构的一致性。
有效的建模不仅仅是画出形状之间的连线。它要求对数据完整性、访问模式以及系统内信息生命周期有深入的理解。通过遵循既定的设计原则,分析人员可以生成可靠的蓝图,为开发团队提供指导。

🏷️ 定义数据存储 🏷️
数据存储是数据流图中的一个被动元素。与转换数据的处理过程不同,数据存储用于保存静止状态的数据。它代表文件、数据库、纸质记录或任何用于保存信息以备后续检索的存储库。
- 被动性:除非某个过程明确请求,否则数据不会从存储中流出。
- 存储身份:它本身不是过程;它不会改变数据,只是保存数据。
- 视觉表示:通常根据所使用的符号标准,表示为一个开口的矩形或双竖线。
在设计这些元素时,重点必须放在逻辑需求上,而非物理实现。DFD描述的是什么数据需求,而不是如何它在硬盘上如何被物理索引或存储。
📝 清晰命名规范 📝
命名是防止混淆的第一道防线。模糊的标签会导致设计阶段出现误解。一个命名良好的数据存储能立即提供其所包含信息的上下文。
1. 单数与复数
一致性是关键。有些团队偏好使用单数名词(例如,客户),而另一些团队则使用复数(例如,客户们)。关键在于整个模型必须使用相同的命名规范。
- 建议: 对数据集合使用复数名词(例如,订单, 产品)以暗示其为一个集合。
- 例外:如果存储仅包含一种记录类型,则单数名称适用于特定实例(例如,配置).
2. 描述的精确性
避免使用像这样的通用术语数据 或 信息。这些标签对内容没有任何启示作用。
- 不良示例: 系统数据
- 良好示例: 活跃用户账户
具体的命名有助于利益相关者立即识别存储的范围。这减少了理解图表所需的认知负荷。
3. 时态与状态
名称应反映数据的状态。如果存储包含历史记录,名称应体现这一点。
- 交易日志 暗示过去事件的记录。
- 待处理订单 暗示等待处理的数据。
🔗 连接规则 🔗
数据进入和离开存储的流动受到严格的逻辑规则约束。违反这些规则会破坏DFD的完整性。
1. 过程连接要求
数据存储必须始终至少连接一个过程。它不能孤立存在。
- 输入: 过程必须将数据写入存储(例如,保存新记录)。
- 输出: 过程必须从存储中读取数据(例如,检索记录)。
如果存储未连接任何内容,则它是一个无功能的幽灵元素。如果它连接到多个过程,则每个连接的数据流必须明确界定。
2. 无直接的数据存储间流动
数据不能在没有中间处理过程的情况下,直接从一个数据存储移动到另一个数据存储。此规则强制执行数据在存储之前必须经过转换或验证的原则。
- 错误: 连接 存储A 直接连接到 存储B.
- 正确: 处理X 从 存储A 读取数据,进行转换,然后写入 存储B.
这种分离确保了在数据持久化之前,业务逻辑、验证或格式化已得到应用。它防止模型暗示数据只是被简单复制而缺乏监督。
3. 数据流标注
连接处理过程与数据存储的每条线都必须标注。标签描述了跨越该边界的特定数据。
- 示例: 从 订单处理 到 订单存储 可能被标注为 订单详情.
- 示例: 从 订单存储 到 报告流程 可能会被标记为 订单历史.
标签为正在传输的数据量和类型提供了上下文。它们有助于开发人员日后理解模式需求。
🎯 细粒度与范围 🎯
决定如何将数据拆分为存储单元是一个关键的设计决策。存储单元过多会分散模型,而过少则会形成一个庞大的信息块。
1. 基于实体的分组
按逻辑实体对数据进行分组。如果系统跟踪客户、产品和发票,这些数据通常应分别存放在不同的存储中。
- 优势: 简化维护。客户数据的更改不会影响发票存储逻辑。
- 优势: 降低更新过程中意外数据损坏的风险。
2. 读写分离
考虑一个存储单元主要是用于读取还是写入。高流量的交易日志通常需要与参考数据不同的存储处理方式。
- 参考数据: 如 国家代码 读取频繁且很少更改。
- 交易数据: 如 销售日志 写入频繁且随时间增长。
即使DFD仍为逻辑模型,区分这些类型也有助于规划容量和访问模式。
3. 临时与永久
并非所有数据存储都代表永久保留。有些是临时缓冲区。
- 会话数据: 用于登录过程中临时用户会话的存储。
- 缓存存储: 用于频繁访问数据的临时存放区域。
明确标记临时存储可以防止对数据保留策略产生混淆。流程完成后,应清空或清除临时存储。
🔄 数据流与过程交互 🔄
过程与数据存储之间的关系在许多情况下是双向的,但并非总是如此。理解方向性对于准确建模至关重要。
1. 只读访问
某些存储仅用于读取。一个过程可能查询存储以显示信息,而不会对其进行修改。
- 示例: 一个 显示个人资料 过程从 用户个人资料存储.
- 约束:对于同一事务,不应存在从存储指向过程再返回过程的数据流箭头,除非它暗示了写操作。
2. 只写访问
某些过程在无需先检索数据的情况下写入数据。
- 示例: 一个 事件日志 过程写入到 系统审计存储.
- 约束:确保该过程具备正确写入数据所需的上下文,而无需外部输入。
3. 读写访问
大多数业务流程都涉及数据的检索、修改和保存。
- 示例: 更新库存读取当前库存,计算新数量,并保存。
- 建模:为读取和写入使用独立的流程,以明确操作顺序。
这种区分有助于开发人员理解数据库事务是否需要立即加锁或提交。
📊 数据流图的层级与数据存储可见性 📊
数据流图通常被分解为多个层级,从上下文图(第0层)到详细分解图(第2层、第3层)。数据存储在每一层中的表现形式不同。
1. 上下文层(第0层)
在最高层级,通常会省略数据存储以保持简洁。重点在于外部实体和主系统边界。
- 原因:过多的细节会掩盖高层次的数据交换。
- 例外情况:如果关键外部数据库对系统边界至关重要,可以将其显示出来。
2. 第1层分解
随着系统被分解为主要过程,数据存储变得可见。这是定义主要存储架构的地方。
- 重点:识别每个主要功能所需的主存储库。
- 细节:确保每个过程都有其输出数据的存储目的地。
3. 第2层及更深层次
进一步分解可能将大型数据存储拆分为更小、更具体的存储。
- 示例: 客户存储在第1层可能拆分为联系信息存储和账单存储在第2层。
- 一致性:确保低层级的数据与高层级的数据保持一致。不要引入父图中未出现的新数据类型。
⚠️ 常见陷阱 ⚠️
即使经验丰富的分析师在设计数据存储时也会犯错。避免这些常见错误可确保图表的准确性。
- 黑洞:一个接收数据但不将其写入任何地方的过程。这暗示了数据丢失。
- 火灾风暴: 一个接收数据输入但不通过存储就产生数据输出的处理过程。这意味着数据凭空产生(奇迹)。
- 幽灵存储: 没有连接任何处理过程的数据存储。这些是死胡同。
- 流量不平衡: 从第1层移动到第2层时,输入和输出必须匹配。如果在第2层添加了存储,则必须由父处理过程的输入/输出来证明其合理性。
- 过度设计: 试图将每个数据库表都建模为第1层图中的独立存储。应坚持使用逻辑实体,而非物理表。
📚 与数据模型保持一致 📚
尽管DFD侧重于流程,但必须与实体关系图(ERD)或逻辑数据模型保持一致。DFD中的数据存储应与ERD中的实体相对应。
- 一致性检查: 如果DFD中包含产品存储,那么ERD中应包含一个产品实体。
- 属性映射: 处理过程与存储交互所需的属性必须存在于数据模型中。
- 规范化: 尽管DFD不强制规范化,但设计应避免明显的冗余,因为这暗示了糟糕的数据库设计。
这种一致性确保了逻辑设计(DFD)可以转换为物理实现(数据库模式),而无需大量返工。
🔍 设计验证检查清单 🔍
在最终确定数据流图之前,请使用以下检查清单来验证数据存储设计。
| 原则 | 检查项 | 状态 |
|---|---|---|
| 命名 | 所有存储名称是否都具有描述性且一致? | ☐ |
| 连接性 | 每个存储是否都至少连接到一个过程? | ☐ |
| 流向方向 | 箭头在过程和存储之间指向是否正确? | ☐ |
| 标注 | 数据是否沿着标有内容名称的线条流动? | ☐ |
| 无直接存储连接 | 是否存在直接连接存储到存储的线条? | ☐ |
| 一致性 | 低层级的存储是否与父层级的范围一致? | ☐ |
| 完整性 | 所有过程的数据需求是否都由可用的存储满足? | ☐ |
🔄 维护与演进 🔄
系统需求会变化。数据存储必须能够适应这些变化,而不会破坏模型。
- 版本控制:跟踪存储定义的变更。如果一个存储被拆分,需记录迁移路径。
- 遗留数据:规划当存储模式变更时,旧数据如何处理。这通常需要一个归档存储。
- 反馈循环:利用开发团队的反馈来优化存储的粒度。如果开发人员发现某个存储过于宽泛,就将其拆分;如果发现过于碎片化,就将其合并。
静态模型是一种负担。每当业务规则变更或引入新的合规要求时,都应审查数据存储设计。这确保了DFD始终是一个动态文档,准确反映系统的数据需求。
📝 实施结论
在数据流图中设计数据存储是系统分析的基础任务。它弥合了抽象过程与具体数据持久化之间的差距。通过遵循严格的命名规范、连接规则和粒度原则,分析人员可以创建既易于阅读又可操作的模型。
目标不是完美复制数据库模式,而是捕捉数据存储的逻辑必要性。当DFD准确时,向开发阶段的过渡会更加顺畅,数据丢失或错位的风险也会显著降低。专注于清晰性、一致性和信息的逻辑流动,以生成高质量的系统设计。











