ER图、功能结构图、用例图这三张图,几乎是所有做系统设计的人绕不开的基本功。但现实情况是,很多人第一次画图时拿到的只是一句"把系统设计画出来",既不知道先画哪张,也不知道每张图画到什么程度算合格,最后交上去的图连自己都说服不了。我见过太多这样的稿子:ER图里实体和属性混在一个框里,功能结构图画成了一棵页面树,用例图里塞满了判断分支,看上去挺满,实际上谁也读不懂。
这篇内容想解决的就是这件事——把这三张图各自的职责切清楚,把画法拆到可以照着做的粒度,再补上几条能明显提速的生成路径。不管你是刚接触建模的学生,还是要交设计文档的开发者,或者是需要评审别人图纸的技术负责人,都能从里面找到能直接抄走的东西。文中涉及的工具栏、布局、命名规则都是行业里的通用做法,具体工具用哪个反而不重要。
1. 三张图各管一摊:先分清职责再动鼠标
画图之前最该做的一件事,是把三张图的边界想明白。这三张图经常被当成"设计文档三件套"一起交,但它们回答的问题完全不一样,混着画的结果就是每张都不到位。我的习惯是先问自己三个问题:数据长什么样、系统能做什么、谁在什么场景下用它。第一个问题的答案落到ER图,第二个落到功能结构图,第三个落到用例图。
1.1 ER图回答的是"数据怎么存"
ER图本质上是数据模型的可视化,它描述的是业务世界里有哪些稳定的对象、这些对象各自有哪些特征、对象之间怎么互相牵连。一张合格的ER图里,矩形代表实体(比如用户、订单、商品),椭圆或者字段列表代表属性,菱形或者连线代表联系,连线两端标着一对一、一对多、多对多这些基数。
很多人画ER图时容易犯一个错:把"登录"“支付”这种动作也画成实体。动作不是数据,它不会在数据库里留下一张表,除非这个动作本身需要被记录(比如支付流水、登录日志),那它才升级成实体。判断标准很简单——这个东西会不会在数据库里有一张对应的表、有独立的主键?会,就是实体;不会,就别画进去。
ER图的价值在于它先于建表语句存在。你在图上发现订单和商品是多对多关系,就会自然而然地想到需要一张中间表来承载数量和单价;你在图上发现某个属性在三个实体里重复出现,就会想到把它抽出来做成独立的字典表。这些判断如果等到写完建表语句再回头改,成本要高好几倍。
1.2 功能结构图回答的是"系统拆成几块"
功能结构图是一棵树,根节点是系统,往下逐层拆成模块、子模块、功能点。它不关心数据怎么存,也不关心用户怎么点,只关心一件事:这个系统由哪些功能组成,它们之间的从属关系是什么。
这张图最实际的用途是分工和估算。一个模块拆到叶子节点之后,每个叶子大概需要多少人天、由谁负责,立刻就能标上去。如果拆出来的某个叶子节点你没法估工作量,说明它要么粒度太粗,要么边界没想清楚——这本身就是个信号。
功能结构图还有个隐性作用:它是需求文档和技术实现之间的翻译层。产品侧看到的是需求条目,开发侧看到的是接口和表结构,功能结构图站在中间,把"用户能感知到的能力"组织成一个有层级的整体。评审时有人问"这个需求对应的功能在哪",顺着树往下找就行。
1.3 用例图回答的是"谁为了什么目标来用"
用例图属于行为建模,核心要素只有四个:参与者、用例、系统边界、它们之间的连线。参与者是站在系统外面跟系统交互的角色,用例是参与者为了达成某个目标而触发的一整段完整交互,系统边界框住的是"哪些事由本系统负责"。
关键在于"完整交互"这四个字。一个用例必须是一个能独立交付价值的目标,比如"提交报销单"是一个用例,"填写金额"“选择日期”“点击保存”都不是——它们是用例内部的步骤,属于用例描述或者活动图的地盘。把步骤画成用例,是把用例图变成流程图的典型症状。
用例图在沟通上的作用特别明显。它能让业务方一眼看到"我在这个系统里能干什么",也能让开发方确认"这些目标背后需要哪些接口和服务"。它不描述顺序、不描述条件判断、不描述异常分支,这些留给后续的时序图和状态图。
1.4 三张图放一起对比,选错图的代价很直接
| 对比维度 | ER图 | 功能结构图 | 用例图 |
|---|---|---|---|
| 核心问题 | 数据存什么、怎么关联 | 系统由哪些功能组成 | 谁为了什么目标使用系统 |
| 主要元素 | 实体、属性、联系、基数 | 模块、子模块、功能点 | 参与者、用例、系统边界 |
| 层级形态 | 网状 | 树状 | 星状(参与者到用例) |
| 典型读者 | 开发、数据库设计者 | 项目经理、开发负责人 | 业务方、测试、产品 |
| 画错的典型症状 | 把动作画成实体 | 把页面当模块 | 把判断分支画成用例 |
选错图的代价不是"图难看",而是沟通失效。你拿一张功能结构图去跟业务方确认需求,对方只会问"那我点进去之后能干嘛";你拿用例图去跟开发对表结构,对方只会问"所以订单表主键是什么"。图没有对错,只有用错场合。
2. ER图的落地画法:从业务话术里把实体抠出来
ER图难的不是画,是"找"。业务方给你的永远是一段话:客户下单之后,系统生成订单,订单里可以有多个商品,每个商品有各自的价格和库存,支付成功后生成支付记录。这段话里藏着实体、属性和关系,需要一层层剥出来。我一般按"名词筛实体、动词定联系、基数定结构"这个顺序推进,基本不会漏。
2.1 名词筛实体,形容词和数量词归属性
拿到业务描述后,先把所有名词圈出来。客户、订单、商品、价格、库存、支付记录——这些都是候选。然后做一轮筛选:能独立存在、有唯一标识、需要被长期保存的,升级为实体;依附于某个实体、离开它就失去意义的,降级为属性。
"价格"和"库存"就是典型的属性候选,它们依附于商品存在,不该单独成表。但如果业务里存在"不同会员等级看到不同价格"这种规则,价格就从一个字段升级成一张价格策略表,因为它的生命周期和变更逻辑独立了。同理,"库存"如果要在多个仓库之间分别记录,也会升级成"库存明细"实体。
这一步的经验是:不要追求一次到位。先把粗筛结果画成草图,再拿回去跟业务方确认"这个价格是所有客户都一样,还是分等级"——问题一问,实体的边界自然就清晰了。跳过确认直接定稿,后面返工的概率极高。
2.2 动词定联系,先把多对多找出来
名词筛完之后,句子里的动词就是联系的来源。“客户下单”对应客户和订单之间的一对多:一个客户可以有多个订单,一个订单只属于一个客户。“订单包含商品”对应订单和商品之间的多对多:一个订单可以有多个商品,一个商品也可以出现在多个订单里。
多对多是ER图里最需要警惕的结构,因为它在物理落地时必须拆成两张一对多。订单和商品的多对多,中间会插入一张"订单明细"表,除了两个外键,还要把属于这段关系的属性挂上去——数量、成交单价、折扣金额。这些属性既不属于订单也不属于商品,只属于"这个订单里的这个商品",位置放错就会导致数据冗余。
一对一的联系要单独说明。它在图上是存在的,但落地时经常被合并进某一张表,比如用户和用户详情,如果是一对一且总是同时访问,合成一张表更省事。ER图上保留这个联系是对的,它表达了业务语义;至于物理上合不合并,属于实现层面的优化决策,可以在图上加注释说明。
2.3 基数标注与参与度:把"必须有"和"可以有"分开
连线两端的基数只说了数量,没说是强制还是可选。客户和订单之间,一个客户可以有零个或多个订单(新注册用户还没下单),但一个订单必须属于且仅属于一个客户。这个"必须"和"可以"就是参与度,它直接决定了外键能不能为空、删除父记录时要不要级联。
我习惯在基数旁边用文字补一句,比如"订单.客户ID 非空"。这行字看着啰嗦,但能省掉后面无数次"这个字段能不能为空"的争论。对于"一个订单必须至少有一条明细"这种约束,数据库层面往往难以直接表达,更要在图上标清楚,让开发和测试都知道这是一条业务规则。
| 联系类型 | 图上的表现 | 物理落地方式 | 容易踩的坑 |
|---|---|---|---|
| 一对多 | 一端标1,多端标N | 多端表加外键 | 忘了给外键加索引 |
| 多对多 | 两端都标N | 拆中间表,关系属性挂中间表 | 关系属性错挂到实体上 |
| 一对一 | 两端都标1 | 合并或单独建表加唯一约束 | 双向都存外键导致不一致 |
| 自关联 | 同一实体两端连线 | 表内加父级ID字段 | 层级查询没做深度限制 |
2.4 布局与命名:让图在没人讲解时也能读懂
ER图的布局有个很实用的原则:把核心实体放中间,外围实体按业务流向排布。用户、订单、商品这三个高频实体放在画布中央,支付、物流、评价这些围绕订单展开的实体放在四周,连线就不会横穿整个画布。
命名统一用单数名词,实体名首字母大写或者全小写都行,但整张图必须一致。属性名建议直接沿用数据库字段风格,比如 user_id、created_at,这样图和表能对得上,评审时不用来回翻译。主键在属性列表里加粗或者标注 PK,外键标 FK,这个习惯看起来是小事,但在几十张表的系统里,它能救回大量时间。
还有一点:连线尽量走直角,避免斜线交叉。绕线看着麻烦,但当图上超过十五个实体之后,正交连线的可读性优势非常明显。画完之后把图缩到 50% 看一眼,如果还能大致看出结构,说明布局是合格的;如果缩完变成一团毛线,那就得重排。
3. 功能结构图的拆解尺度:切到能估算为止
功能结构图最怕两种情况:拆得太粗,一个"系统管理"下面什么都没有,谁也不知道要做多少事;拆得太细,细到每个按钮都单独占一个框,图变成了一张页面清单。合适的粒度有个很实在的判据——每个叶子节点都能估出人天,且都能指派给一个明确的负责人。
3.1 一级模块从哪里切:三种切法各有适用场景
一级模块的划分方式常见的有三种。第一种按业务对象切,比如商品管理、订单管理、用户管理、支付管理,这种切法最贴近业务语言,业务方看得懂,适合业务系统。第二种按角色切,比如买家端、卖家端、运营端,适合多角色、功能差异大的平台型系统。第三种按流程阶段切,比如售前、交易、售后,适合流程链条长、阶段边界清晰的业务。
三种切法可以组合,但一级只能选一种作为主轴,否则层级会乱。我个人的偏好是业务对象优先,因为对象最稳定,流程会变、角色会变,但"订单"这个东西长期存在。如果某个系统的角色差异确实大到功能几乎不重叠,那按角色切更合理。
这里要提醒一句:技术分层不是功能划分。把"前端层”“服务层”“数据层"画进功能结构图是常见错误,它表达的是实现架构,不是系统功能。功能结构图的读者是业务方和项目管理者,他们关心的是"能不能下单""能不能退款”,不关心你的代码分几层。
3.2 层级停在哪里:三层半原则
我自己的经验是把模块拆到三层,最多三层半。第一层是系统,第二层是模块,第三层是功能点,再往下的"子功能"如果能用一句话说清楚,就不用单独画框,写在功能点后面的括号里即可。
比如"订单管理 → 订单查询 → 按状态筛选","按状态筛选"已经是第三层的细节,再往下拆"按待付款筛选""按已发货筛选"就没有意义了,那些是界面上的选项,不是独立功能。这个边界感需要练,判断标准还是那个:这个节点能不能单独估工时、单独指派、单独验收。三个都能,就值得拆;有一个不能,就合并。
层级过深的另一个坏处是图形失控。四层以上的树在画布上会横向铺开得很宽,打印出来字小到看不清。如果确实需要表达四层结构,可以考虑把第四层做成独立的附表,主图只保留到第三层。
3.3 命名统一用"动词+名词",编号要能定位
功能结构图的节点命名建议统一成动宾结构:新增商品、编辑商品、下架商品、批量导入商品。这样一来看名字就知道这个功能干什么,二来同一模块下的功能点会自然形成一组,排列整齐。
纯名词命名("商品列表"“商品详情”)的问题在于它描述的是界面而不是能力,读者无法判断这是一个查询功能还是一个维护功能。如果确实要表达列表,写成"查询商品列表"更准确。
编号体系建议用点分层级:1 商品管理、1.1 商品维护、1.1.1 新增商品。这个编号不只是好看,它是后续所有文档的锚点——需求文档里写"对应功能 1.1.1",测试用例里写"覆盖 1.1.2 至 1.1.5",评审时所有人都能用编号快速定位,比说"就是那个商品下面的第三个"高效得多。
3.4 几个高频翻车点:页面当模块、功能重复挂载
第一个翻车点是把页面当模块。功能结构图里出现"首页""详情页”“个人中心页",这是把导航结构当成了功能结构。页面是功能的载体,一个页面可能承载多个功能,一个功能也可能跨多个页面,两者不是一一对应关系。
第二个翻车点是同一个功能挂在多个模块下。比如"导出"既挂在订单管理下,又挂在报表管理下,还挂在用户管理下。这种情况要么抽象出一个公共能力模块统一承载,要么在各自模块下明确写出导出的是什么东西("导出订单""导出用户"),避免读者以为是同一个功能。
第三个翻车点是模块之间没有边界。比如"商品管理"和"库存管理"都包含"调整库存",这就需要在拆分阶段就想清楚:库存的维护归库存模块,商品模块只读不写。边界一旦在图上定下来,后面接口设计、权限设计都会顺很多。
4. 用例图的语法边界:椭圆里到底该写什么
用例图看着简单,三个元素一画就成型,但它是最容易被画歪的一张。核心原因是很多人把它当成了"功能清单的图形版",于是椭圆里塞满了"查询""新增""删除"这类 CRUD 动作,参与者连了一堆线,图上密密麻麻却没有一个能讲清楚用户到底要达成什么。
4.1 参与者不只是人:外部系统和定时任务也要算
参与者(Actor)的定义是"站在系统边界之外、与系统交互的角色"。人不一定是参与者,参与者也不一定是人。外部系统是参与者——比如对账时需要从支付渠道拉取流水,那个渠道系统就是一个参与者。定时任务是参与者——每天凌晨触发一次数据汇总,触发源也是一个参与者,通常画在系统边界右侧。
同一个真人如果承担多种职责,可以拆成多个参与者。比如一个运营人员既负责商品上架,又负责订单审核,这两件事的目标和权限完全不同,拆成"商品运营"和"订单审核员"两个参与者会更清晰。反过来,多个真人如果承担完全相同的职责,可以合并成一个参与者,比如所有普通买家统一叫"买家"。
参与者之间可以有泛化关系,用带空心三角的连线表示。比如"会员买家"继承"买家"的所有用例,同时多了"使用积分抵扣"这个用例。这种画法能有效减少重复连线,但不要滥用,继承层级超过两层就该考虑是不是参与者划分有问题了。
4.2 用例粒度:一个用例对应一个可交付的用户目标
用例的判断标准我总结成一句话:参与者发起它、系统完成它、参与者拿到一个可感知的结果。发起是主动的,结果是可验证的,中间的过程不属于用例图。
拿"下单"举例。“提交订单"是一个用例,参与者是买家,结果是生成一笔待支付订单。”支付订单“是另一个用例,参与者是买家,结果是订单状态变为已支付。这两个用例前后相连,但它们是独立的两个目标,不该合并成一个”买东西“。反过来,”填写收货地址“不是用例,它是提交订单这个用例内部的步骤。
用例名同样建议动宾结构,长度控制在六到十个字之间。太短("查询")信息量不足,太长("买家在商品详情页选择规格后加入购物车")又变成了场景描述。中间那个度,就是"提交订单""申请退款”“取消订单"这种。
4.3 include、extend、泛化:三种关系各有严格前提
这三种关系是用例图里最容易用错的部分,用错了不如不画。
包含关系(include)表达的是"每次执行 A 都必然执行 B",B 是被抽出来的公共片段。典型例子是"提交订单"包含"校验库存",因为每次提交都必须校验。判断标准是"必然",如果只是"可能",那就不是 include。
扩展关系(extend)表达的是"在特定条件下,A 会被 B 增强",B 是可选的。典型例子是"提交订单"在使用了优惠券时扩展出"核销优惠券"。扩展关系要标清楚扩展点,也就是在 A 的哪一步发生扩展,否则读者不知道 B 插在哪里。
泛化关系(generalization)表达的是"B 是 A 的一种特殊情况",子用例继承父用例的行为并可以覆盖。比如"支付订单"泛化出"余额支付""银行卡支付",这两种支付方式在语义上是支付的特殊形式。泛化用得好能大幅简化图面,用得不好会让读者以为所有子用例都必须实现,所以一般只在上层需要抽象表达时才用。
| 关系类型 | 语义 | 判断口诀 | 用错的后果 |
|---|---|---|---|
| 关联 | 参与者与用例交互 | 谁发起,就连谁 | 参与者连到别人的用例上 |
| 包含 | 必然执行的公共片段 | 每次都要,才包含 | 把可选步骤画成包含 |
| 扩展 | 条件触发的增强 | 有时才做,才扩展 | 扩展点没标,读者看不懂 |
| 泛化 | 特殊化继承 | 是一种,才泛化 | 层级过深,图面失控 |
4.4 系统边界框画不画,多系统交互怎么表达
单个系统的用例图,边界框可画可不画。画的好处是明确职责范围,尤其在评审时能回答"这件事到底归不归我们做"。如果系统涉及多个子系统协作,边界框就变成必需品了——每个系统一个框,跨框的连线表示系统间的调用,参与者连到各个框内部的用例上。
多系统场景下有个细节要注意:跨系统的调用不该画成参与者。A 系统调用 B 系统的接口,如果 A 是参与者那侧的角色,可以画成参与者;但如果 A 本身也是被建模的系统之一,就应该用两个边界框加一条依赖线,而不是把 A 画成小人。这个区分在架构评审时经常被追问。
还有个小习惯值得养成:用例图下面附一张用例清单表,列出用例编号、名称、参与者、前置条件、简要说明。图负责让人一眼看懂全局,表负责承载细节。只有图没有表,评审时一定会被问"这个用例具体做什么",而你又不能把答案塞进椭圆里。
5. 快速生成的几条路径:别从空白画布开始
真正耗时间的从来不是画线,是想清楚画什么和排布。所以提速的关键不在工具技巧,而在于"先有结构化的文字,再让图从文字里长出来"。我常用的几条路径,覆盖了从零开始和从已有资产反推两种场景。
5.1 缩进大纲直接转成结构图
功能结构图天生就是一棵树,而树在文本里最简单的表达就是缩进。先在编辑器里把层级敲出来:
1 商品中心 1.1 商品维护 1.1.1 新增商品 1.1.2 编辑商品 1.1.3 上下架商品 1.2 类目管理 1.2.1 新增类目 1.2.2 调整类目层级 2 交易中心 2.1 购物车 2.1.1 加入购物车 2.1.2 修改数量 2.2 订单 2.2.1 提交订单 2.2.2 取消订单这段文本直接粘进支持大纲导入的绘图工具,能自动生成树状结构图。即使工具不支持导入,照着这段文本手动摆框,也比对着空白画布想快得多,因为层级关系已经确定了,剩下的只是拖拽。
这套方法的额外好处是版本可管理。文本可以进代码仓库、可以 diff、可以评审,图不行。改动的时候先改文本再重新生成,比在画布上挪框子可靠得多。
5.2 建表语句反向出ER图
如果数据库已经有一部分建好了,或者你能快速写出建表语句,那ER图可以直接从 DDL 反推。主流建模工具都支持导入 SQL 自动生成实体和关系,识别依据是主键、外键和唯一约束。
CREATE TABLE customer ( id BIGINT PRIMARY KEY, name VARCHAR(64) NOT NULL, phone VARCHAR(20) UNIQUE ); CREATE TABLE orders ( id BIGINT PRIMARY KEY, customer_id BIGINT NOT NULL, status TINYINT NOT NULL, created_at DATETIME NOT NULL, CONSTRAINT fk_orders_customer FOREIGN KEY (customer_id) REFERENCES customer(id) ); CREATE TABLE order_item ( id BIGINT PRIMARY KEY, order_id BIGINT NOT NULL, product_id BIGINT NOT NULL, quantity INT NOT NULL, unit_price DECIMAL(10,2) NOT NULL, CONSTRAINT fk_item_order FOREIGN KEY (order_id) REFERENCES orders(id) );导入之后会自动得到三张表、两条一对多关系。这时候需要人工做两件事:一是确认中间表 order_item 是不是被识别成了实体(它确实是实体,但语义上是关系表,可以在注释里说明),二是补上图上表达不了的业务约束,比如"一个订单至少一条明细"。
反过来也成立:先画ER图,再让工具导出建表语句的骨架。这个方向更适合设计阶段,因为图上的调整成本远低于改 SQL。导出之后人工补索引、补默认值、补字符集,比从零写 DDL 快很多。
5.3 用例清单表格批量出图
用例图最麻烦的是连线多。一个系统十几个用例、五六个参与者,连线能有二三十条。手工一条条拉,既慢又容易漏。
我的做法是先维护一张用例清单表:
| 用例编号 | 用例名称 | 主要参与者 | 关联参与者 | 包含用例 | 扩展用例 |
|---|---|---|---|---|---|
| UC-01 | 提交订单 | 买家 | 库存系统 | 校验库存 | 核销优惠券 |
| UC-02 | 支付订单 | 买家 | 支付渠道 | 校验订单状态 | 无 |
| UC-03 | 申请退款 | 买家 | 无 | 校验订单状态 | 无 |
| UC-04 | 审核退款 | 客服 | 支付渠道 | 无 | 无 |
表格填完之后,参与者、用例、关联关系、包含扩展关系全部齐了,剩下的就是把这些关系批量映射成图形元素。部分工具支持从表格导入节点和连线,即使不支持,照着表格拉线也比边想边画快,因为你不用再做决策了,只是在执行。
这张表还有个附带价值:它就是测试用例的源头。每个用例至少对应一条正向用例,每个扩展用例对应一条异常用例,测试覆盖率天然就有了保障。
5.4 模板、组件库和样式统一的提效细节
图纸的观感很大程度上取决于一致性,而一致性靠的是模板而不是手感。开工前先定好三件事:实体框、用例椭圆、模块矩形的固定尺寸和配色;连线的固定样式(线宽、箭头、是否正交);字体和字号。
把这些存成工具里的模板或者组件,每次新建图直接套用,能省掉大量"调半天觉得哪里不对"的时间。我见过有人一张图里用了五种蓝色,评审时被问"这几种颜色是代表不同含义吗",场面很尴尬。颜色的用途应该是编码信息,不是装饰——比如核心实体用一种色、辅助实体用灰色、外部系统用虚线框,这样颜色本身就在传递信息。
还有个小技巧:先摆框后连线。把所有节点一次性拖到画布上,按大致位置排好,再统一连线。边摆边连的问题是连线会干扰你对布局的判断,而且移动节点时连线跟着乱,很容易越画越烦。
5.5 自动生成之后的收尾:布局微调和人工校验
自动生成的图有个通病:布局是算法排的,不一定符合人的阅读习惯。常见的表现是核心实体被挤到角落、连线大量交叉、同层节点顺序混乱。
所以生成之后一定要做一轮手动整理:把核心实体挪到中央、把同一业务域的节点聚在一起、把交叉的连线改成直角绕行、把文字标签挪到不遮挡连线的位置。这一轮通常花不了十分钟,但对可读性的提升是决定性的。
校验环节也别省。自动生成最大的风险是"看起来对但其实是错的"——比如外键没识别出来导致关系缺失,比如同名不同义的两个实体被合并了。生成完先数一遍:实体数量对不对、关系数量对不对、有没有孤立的实体。三个数字对上了,再开始调布局。
6. 交付前的自查清单与返工重灾区
图纸画完不等于能交。我自己的习惯是交付前过一遍清单,很多问题在这一步就能拦住,不用等到评审现场被指出来。
6.1 三张图之间的一致性交叉验证
三张图不是孤立的,它们描述的是同一个系统,所以必须能互相印证。最实用的三条校验线是这样的:
第一条,ER图里的每个实体,都应该能在功能结构图里找到维护它的功能。如果 ER 图里有"优惠券"实体,但功能结构图里没有任何跟优惠券相关的模块,要么是漏了功能,要么是这个实体根本不该存在。
第二条,用例图里的每个用例,都应该能在功能结构图里找到对应的功能点。用例是用户目标,功能是系统能力,两者是多对多的关系,但不能有孤儿。反过来也成立:功能结构图里的每个功能点,至少要服务一个用例,否则就是没人用的功能。
第三条,用例图里的参与者,应该能在 ER 图或者权限设计里找到对应的角色。如果用例图里有个"审核员",但数据模型里完全没有审核相关的记录表,那审核动作产生的结果存在哪里?这个问题一问就露馅。
| 校验项 | 检查方法 | 常见问题 |
|---|---|---|
| 实体与功能对应 | 逐个实体找维护入口 | 有实体无功能,或有功能无实体 |
| 用例与功能对应 | 逐个用例找功能点 | 用例孤立,功能点无来源 |
| 参与者与角色对应 | 比对权限设计 | 参与者没有对应数据落点 |
| 关系与约束对应 | 检查基数标注 | 多对多没拆中间表 |
6.2 评审现场最常被追问的六个点
这些问题是评审时的高频问题,提前想好答案,能省掉大量现场卡壳。
第一个,"这个一对多是哪个方向"。基数标注一定要写清楚端,不能只在中间画个 1 和 N,得让人一眼看出 1 在哪头。
第二个,"这个用例的边界在哪"。回答要具体到"从用户点什么开始,到系统返回什么结束",含糊其辞会被继续追问。
第三个,"这个模块下面为什么没有再拆"。答案应该是"叶子节点已经可以估工时和指派",而不是"我觉得够了"。
第四个,"这个外部系统算不算我们的范围"。这直接关系到工作量,必须在图上用边界框明确表达。
第五个,"这个属性能不能为空"。ER 图上标了非空就要能说出理由,标了可空也要能说出场景。
第六个,"改一个地方要动几张图"。如果你的三张图耦合得很紧,改一处要同步改三处,那说明抽象层次没拉开,需要重新审视。
6.3 版本管理与导出格式的实际做法
图纸的版本管理是个容易被忽略的坑。很多人的做法是"另存为 最终版.docx"“另存为 最终版2.docx",过两周自己都分不清哪个是最新的。
我的做法是源文件和导出件分开管理。源文件(工具的原生格式)进版本库,命名带上日期和版本号,比如er-20240512-v3;导出件(PNG 或 PDF)只保留最新一版,用于嵌入文档和分享。这样既能追溯历史,又不会在分享时发错版本。
导出参数上有两个细节值得注意。一是分辨率,嵌入文档的图建议导出 2 倍图,否则打印出来会糊;二是背景,导出 PNG 时选透明背景,嵌到深色或者带底色的文档里不会出现白框。
另外建议在图的右下角加一个小的信息块:图名、版本号、最后修改日期、作者代称。这行小字在多人协作的场景下价值极大,能避免大量"这是哪一版"的来回确认。
最后分享一个我自己一直在用的小习惯:三张图不要分三天画,尽量在同一天内完成初稿。因为这三张图共享同一套业务理解,连续画的时候脑子里的模型是热的,实体、功能、用例能互相对上;隔几天再画第二张,往往要重新捡起上下文,还容易画出互相矛盾的结论。初稿完成后再分头细化,那时候一致性已经锁住了,改起来也不容易跑偏。