这一课不写代码,只做一件事:把「谁用、用来干什么」写成能验收的矩阵。 矩阵不平,后面的界面、权限、表结构就都是猜的。 三个人群的功能点数差出三倍,这个比例直接决定开发投入往哪放。
第 18 章讲闪回,是「出事之后怎么退」。这一章换个方向:从零做一个系统。 前 18 章都是单点技术——一个 SQL、一个索引、一次恢复。 这一章要把它们串成一条线,所以它慢,但慢在设计上。 全章十篇是一条流水线:需求 → 设计 → 建库 → 界面 → 模块 → 收尾。 这一篇是流水线的入口。
一、先分清三类人,再谈功能
教材开篇的人事管理系统,是给一家中等规模公司做的内部工具。 它只有三类使用者,但三类的诉求完全不一样。
| 角色 | 主要职责 | 典型动作 |
|---|---|---|
| 系统管理员 | 建账号、分权限、备份恢复 | 很少用,但出事第一个找他 |
| 人事专员 | 管档案、算工资、出报表 | 一天到晚用它 |
| 普通员工 | 查自己的档案和工资条 | 一个月看一两次 |
这张表的价值不在「列出三类人」,在于它暴露了一个事实: 主力用户只有一类。 人事专员是唯一的【重度用户】,另外两类都是低频。 低频用户提的需求往往最刺耳——他们不熟,所以会说「这个太复杂」。 判断需求优先级时,要先问一句「提这个需求的人一年用几次」。 一年用两次的人提的「必须加个按钮」,通常可以不做。
二、功能点 × 角色矩阵:把需求变成格子
下一步是把功能点摊成行,角色摊成列,一格格填「谁能做什么」。 填完之后,需求就从一段散文变成了一张能验收的表。
| 功能点 | 管理员 | 人事专员 | 普通员工 |
|---|---|---|---|
| 员工档案维护 | — | 增删改查 | 只看自己 |
| 部门管理 | 增删改查 | 查看 | 查看 |
| 工资计算 | — | 计算与复核 | — |
| 工资条查询 | — | 看全部 | 只看自己 |
| 用户与权限 | 账号与授权 | — | — |
| 数据备份 | 备份与恢复 | 发起备份 | — |
这张矩阵就是权限表的原型。 Demo 里把它按格子数了一遍,得到 6 比 11 比 3。 11 那一列说明一切:主力功能全压在人事专员身上。 所以界面复杂度要按人事专员的熟练度设计,不是按普通员工。 这一点反直觉:很多系统为了照顾「偶尔用的人」,把界面做得极简, 结果主力用户每天要为此多点五次。 正确的做法是给低频用户做减法(只显示他自己那几项),不是给所有人做减法。
三、技术选型的两个硬约束
教材的技术栈是四件:Swing、Hibernate、Oracle、可执行 jar。 这四个选择背后只有两条约束,其余都是自由选择。
| 选项 | 教材的选择 | 为什么 |
|---|---|---|
| 界面 | Swing | 公司内网用,不要求浏览器 |
| 持久层 | Hibernate | 少写 JDBC 样板代码 |
| 数据库 | Oracle | 公司已有,运维熟 |
| 打包 | 可执行 jar | 双击就跑,不用装环境 |
第一条约束是【部署环境】:内网、Windows、不允许装服务器。 这一条直接排掉了 B/S 架构——它要一台 Web 服务器,还要人维护。 第二条约束是【已有资产】:公司已经有 Oracle 和它的运维。 这一条排掉了「换个轻量数据库」的念头,哪怕技术上更省事。 这两条都不是技术判断,是组织判断。 选型时最贵的错误,是拿技术理由去覆盖组织约束。
四、这一幕在全书的位置
十篇的分工,其实是一条数据从「想法」走到「能跑」的路。
| 环节 | 产出 | 做错了会怎样 |
|---|---|---|
| 19.1 背景 | 角色与功能矩阵 | 后面全是猜的 |
| 19.2 分析 | 用例优先级 | 先做了不重要的 |
| 19.3 设计 | 结构图、流程图、目录 | 编码时反复改结构 |
| 19.4 数据库 | 四张表加索引 | 三个模块一起返工 |
| 19.5~19.9 | 界面与三个模块 | 这里才是写代码 |
| 19.10 收尾 | 关联关系与 N+1 | 上线后慢慢变慢 |
注意前四个环节占了四篇,一行界面代码都没写。 这不是教材啰嗦。 数据库设计错一个字段,后面三个模块全要返工; 界面结构定错,所有对话框都要重画。 先想清楚再动手,省下的不是时间,是【返工】。 而返工的成本随项目推进指数上涨,这是软件工程里最硬的一条经验。
五、动手 Demo:把功能矩阵数一遍,看三个人群的投入比例
这一篇的 Demo 不碰数据库,只做算术:把矩阵的格子数出来。 数完会得到一个比例,这个比例就是后面排期的依据。 代码很短,但要看清一件事:格子不是均匀分布的。
# 每行是「一个功能点」在三个角色下各有几个可做动作
matrix = [
("员工档案维护", 0, 5, 1),
("部门管理", 2, 1, 1),
("工资计算", 0, 3, 0),
("工资条查询", 0, 1, 1),
("用户与权限", 2, 0, 0),
("数据备份", 2, 1, 0),
]
tot = [0, 0, 0]
for row in matrix:
for i in range(3):
tot[i] += row[i + 1]
print("功能点 %d 个" % len(matrix))
print("管理员 %d / 人事专员 %d / 普通员工 %d" % tuple(tot))
print("人事专员占 %.0f%%" % (tot[1] * 100.0 / sum(tot)))
实跑输出:
--------------------------------------------------------------------
第八十四课:开发背景——先把「谁用、用什么」写成矩阵
--------------------------------------------------------------------
**教材开篇的人事管理系统,是给一家中等规模公司做的内部工具。**
**这一课不做代码,做一件更重要的事:把需求整理成能验收的矩阵。**
一、三类用户,各自要什么
--------------------------------------------------------------------
角色 主要职责 功能点
--------------------------------------------
系统管理员 建账号、分权限、备份恢复 6
人事专员 管员工档案、算工资、出报表 11
普通员工 查自己的档案和工资条 3
已选择 3 行
**三类角色的功能点数差得很开:11 比 6 比 3。**
**这个比例直接决定后面的开发投入**——人事专员那一列才是主体。
二、功能点 × 角色矩阵
--------------------------------------------------------------------
功能点 管理员 人事专员 普通员工
-------------------------------------
员工档案维护 —— 读写 只读自己
部门管理 读写 读写 ——
工资计算 —— 读写 ——
工资条查询 —— 全部 只读自己
用户与权限 读写 —— ——
数据备份 读写 —— ——
已选择 6 行
**这张矩阵就是权限表的原型。**
**看第一行第三列:「只读自己」。**
**这三个字落到 SQL 上,就是一个 `WHERE emp_id = 当前用户` 的条件。**
**写需求时含糊成「员工能查档案」,写代码时就必然漏掉这个条件。**这是权限漏洞最常见的来源。
三、技术选型的两个硬约束
--------------------------------------------------------------------
项 教材的选择 为什么
-----------------------------------------------
界面 Swing 桌面端,公司内网用,不用 B/S
持久层 Hibernate 对象关系映射,少写 SQL
数据库 Oracle 公司已有,运维熟
打包 可执行 jar 双击就能跑,不用装
已选择 4 行
**四个选择里,只有第二个值得多说一句。**
**Hibernate 在这个项目里的作用,**
**是让「员工」「部门」这些概念在代码里是对象,不是 `ResultSet`。**
**代价是:关联关系配错了,会在你没想到的时候发出一条查一万次的 SQL。**
**那是第 93 课要专门处理的事。**
四、这一章的地图
--------------------------------------------------------------------
节 干什么 本课对应
-------------------------------------------------------
19.2 系统分析:谁用、用到什么程度 第 85 课
19.3 系统设计:结构、流程、目录 第 86 课
19.4 数据库设计:E-R 到建表 第 87 课
19.5 主窗体:导航与工具条 第 88 课
19.6 公共模块:配置、映射、通用 CRUD 第 89 课
19.7~19.9 三个业务模块 第 90~92 课
19.10 Hibernate 一对一与一对多 第 93 课
已选择 7 行
**顺序有个特点:先设计、后编码,中间隔了三课。**
**这不是教材啰嗦。**
**数据库设计错一个字段,后面三个模块全要返工;先想清楚再动手,是唯一省时间的办法。**
输出第一行是功能点总数 6。 第二行 6 比 11 比 3,就是三类角色的动作数。 11 是 6 的近两倍。 这意味着「人事专员」这一列要做的东西,比管理员那一列多一倍。 第三行 55%:人事专员一个人吃掉了一半以上的功能点。 这就是为什么它的界面值得单独设计,而管理员的界面可以简陋。 矩阵里还有三个「0」,也就是三处「这个角色完全不该看到」的入口。 把它们做成【不显示】而不是【灰掉】——灰掉的按钮会让人一直试,不显示的不会。 要诚实说一句:这些 0 到 5 的数字是我按教材的功能描述填的,不是教材原文。 真实项目里这一列要拿去跟用户对,对完才作数。
30 秒实验
- 把
matrix里「工资计算」那一行的管理员从 0 改成 1, 看比例怎么变——想清楚「管理员要不要能算工资」这件事。 - 在
matrix末尾加一行「报表导出,(0, 2, 0)」, 看总格子数变成多少——这就是加一个功能的成本口径。 - 把三个角色的列顺序换一下(换成 人事/管理/员工),
看
tot的下标要不要跟着改——这就是「矩阵的列是有语义的」。
常见误区
- 「需求就是用户说的话」。 用户说的是【想要】, 矩阵记的是【能做】。 两者之间要过一次「谁用、用几次」。
- 「三类用户平权」。 平权的界面等于没人好用。 主力用户的操作路径要最短,低频用户的入口可以深。
- 「选型看技术先进性」。 内网、单机、已有 Oracle, 这三条约束下最先进的技术往往是最贵的选择。
- 「先写代码,边写边设计」。 单点技术可以这样,有界面的业务系统不行——界面一改, DAO 和表常常跟着改。
自测三问(点开对答案)
1. 为什么先写「谁用」而不是先写「有什么功能」? —— **因为同一个功能对不同角色的价值差几十倍。** **不先分清人,就无法判断哪个功能该做细、哪个能凑合。** 2. 三类角色里,界面复杂度应该按谁定? —— **按人事专员,也就是重度用户。**低频用户的诉求靠「只给他看几项」来满足,不靠把整体做简单。 3. 「不显示」和「灰掉」有什么区别? —— **灰掉等于告诉用户「这里有东西,但你不能用」,他会一直试。** **不显示等于告诉他「这里没有这件事」,一次就死心。** 4. 为什么说选型是组织判断而不是技术判断? —— **因为排掉 B/S 的不是性能,是「内网不许装服务器」;** **排掉 MySQL 的不是功能,是「公司已有 Oracle 运维」。** **这两条都不是技术能改的。**下一篇把矩阵变成【顺序】。同样是这六个功能,先做哪个? 答案不能靠拍脑袋,得有一把能算的尺子。
- ☐ (本篇完,下一篇 19.2 系统分析)
相关笔记
- 系统分析
-
- 🐬 MySQL必知必会/00-索引
- 🏺 Oracle从入门到精通 · 索引