前两篇聊了为什么要做、跟别人的区别在哪。这篇是动手前最重要的一步:拆需求。
你接到的需求是"做一个数字标牌管理系统"。八个字。但系统长什么样?一个字都没说。
这就是独立开发者和外包的区别——外包会去反复确认需求,独立开发者要学会自己拆。
从一句话到一张图
"管屏幕"这三个字,听起来简单,仔细想其实有四层:
第一层:屏幕本身。有几块屏幕?什么型号?分辨率多少?横着还是竖着?在线还是离线?——这是设备管理。
第二层:屏幕上放什么。图片、视频、轮播图、文档。这些东西从哪来?怎么分类?——这是素材管理。
第三层:什么时候放什么。工作日放促销广告,周末放品牌宣传。早上 9 点员工上班放欢迎页,晚上打烊放"明日营业时间"。——这是节目编排。
第四层:放了之后呢。播了没有?播了几次?有没有报错?——这是播放统计。
还有一个横切面:谁来操作?老板能删素材,店员只能看。——这是用户权限。
五块东西,在纸上画就是一张图:
┌─ 用户权限 (横切) │ 设备管理 ──┤ 素材管理 ──┼── 节目编排 ──→ 播放统计 │从图到数据库
画完图,下一步是把每个模块变成表。
这一步没什么高深的——就是问自己:这个东西有什么属性?
设备有什么属性?编号、名称、型号、分辨率、布局模板、IP 地址、在线状态、上次心跳时间、属于哪个分组。
翻译成 SQL:
CREATETABLEt_device(idBIGINTPRIMARYKEY,device_noVARCHAR(50)NOTNULL,-- 设备编号nameVARCHAR(100)NOTNULL,-- 设备名称modelVARCHAR(50),-- double_side/stand/wallresolutionVARCHAR(20),-- 1920x1080layout_templateVARCHAR(50),-- single/split_h/split_vstatusVARCHAR(20)DEFAULT'offline',-- online/offline/errorgroup_idBIGINT,-- 属于哪个分组last_heartbeatDATETIME,-- 最后心跳时间...);素材有什么属性?名称、类型(图片/视频/轮播/文档)、属于哪个分类、文件地址、缩略图、文件大小、播放时长。
节目有什么属性?名称、开始时间、结束时间、排期类型(单次/每天/每周/自定义)、状态(草稿/已发布/已过期)。
中间还有个关键表:节目和素材的关联。一个节目里有多个素材,每个素材有一个播放顺序(sort_order)。多分区屏幕的话,每个素材还有一个区域编号(zone_index)。
这就多了一张关联表:
CREATETABLEt_program_material(program_idBIGINT,material_idBIGINT,zone_indexINTDEFAULT0,-- 在屏幕哪个区域sort_orderINTDEFAULT0,-- 播放顺序durationINT-- 这个素材播几秒);最终,9 张表:
| 表 | 干什么的 |
|---|---|
| t_user | 登录用户 |
| t_device_group | 设备分组 |
| t_device | 设备信息 + 心跳 |
| t_material_category | 素材分类(树形) |
| t_material | 素材文件 |
| t_program | 节目单 |
| t_program_material | 节目里有哪些素材 |
| t_device_command | 设备远程指令 |
| t_play_log | 播放记录 |
拆需求的两个原则
做了几个项目之后,我拆需求有两个原则。
第一,一张表只干一件事。
素材分类和素材是两张表。设备分组和设备是两张表。不要因为"可以用一个字段代替"就合并——分开之后,你改分类名称,素材表一行都不用动。
第二,先想"查什么",再定"怎么存"。
设计t_play_log的时候,我先想的不是字段,是查询场景:“查这台设备昨天的播放记录”“查这个素材总共被播了多少次”“哪个设备报错最多”。
然后才加索引:(device_id, created_at)、(program_id)。
下篇开始动手写代码。第一件事:搭开发环境。JDK 装不上、Maven 配不对、MySQL 密码忘了——这些我都踩过。
关于作者:无羡,独立开发者,全栈工程师,专注 AI 应用与微服务架构。
📌 分类:技术复盘
🔗 个人博客 — 更多技术文章
✨ 开发者福利整理 — 云服务资源汇总
📂 软件工坊 — 我的技术分享
🌐 个人门户 — 独立开发作品全集