资讯详情

资讯详情

不用数据库的MVP:File-Based架构在医字号项目中的实践

做医疗健康类产品的人应该都有同感面对一个需求并不完全明确、合规要求却一大堆的赛道从零写一个业务系统最耗时间的往往不是逻辑本身而是基础设施的搭建——数据库表结构怎么设计、接口要拆多细、部署环境怎么搞。而这些在MVP阶段很可能都是浪费。我自己在跑一个医字号项目的前期验证时试验了一套反常规的做法完全不用数据库一切业务数据都以结构化文件为核心存储也就是File-Based App的概念。这套组合配合MVP的迭代节奏效果出乎意料地好。先解释一下File-Based App是什么。它本质上是一个以文件系统为核心存储引擎的应用业务记录以JSON、CSV或Markdown等格式落盘通过文件读写完成数据的增删改查用文件目录结构来模拟数据表之间的关联关系。听起来很“古早”但在MVP阶段它比传统数据库方案在速度、可移植性和心智负担上都有明显优势。这篇文章我不打算讲大道理就结合自己做医字号MVP项目的真实过程把File-Based架构的选型逻辑、数据层设计、权限处理、踩坑记录和后续演进路线一次性说清楚。对于正在考虑MVP方案、或者被数据库设计搞得头痛的开发者应该会有参考价值。1. 为什么MVP阶段反而应该优先考虑File-Based架构大部分开发者在做MVP时有个惯性思维不管需求多模糊先把MySQL或者PostgreSQL建起来设计十几张表然后开始写CRUD。但说实话这在医字号项目里是个挺危险的开局。医疗健康领域有个特点需求方可能是医生、运营或者患者端用户描述的场景经常是跳跃的业务规则一变数据库表结构就要跟着大改。一次两次还行到了第三个星期你会发现大量的时间不是花在业务逻辑上而是花在迁移表和修复关联关系上了。文件型应用在这个阶段有天然优势。核心原因可以归纳为三点一是存储结构灵活JSON文件天然支持嵌套和稀疏字段字段增删不需要执行ALTER TABLE二是版本控制友好整个数据目录可以直接丢进Git每次迭代改了哪些文件一目了然出问题随时回滚三是部署极度轻量应用跑起来只是一个进程加一个文件夹没有数据库服务需要安装和维护在演示现场、临时测试环境都能随时拉起来跑。尤其对于医字号MVP有一件事容易被忽略验证期可能需要反复向不同合作方展示产品每一次展示都可能要调整一部分数据口径或者界面流程。用文件存储的话你改的是数据文件本身连数据迁移脚本都不需要。我还遇到过一种情况现场演示时客户临时想看一个自定义维度的统计报表传统方案得现写SQL现联表而File-Based架构下数据全是JSON一条命令用jq或者写个几行脚本就提取出来了当场就能跑出结果。这种灵活性在MVP阶段的价值远高于数据库带来的所谓架构规范。当然不用数据库不代表不设计数据。File-Based的核心在于把文件系统当作一个可编程的存储层来使用它要求开发者具备更强的信息架构能力——你需要把目录结构、命名规范、字段格式设计得足够自洽。这才是真正的难点也是本篇文章后续要重点展开的地方。2. 医字号MVP项目的边界界定与核心路径梳理很多人觉得MVP就是砍功能只要功能少就算MVP这是一个比较大的误解。MVP的核心是围绕一个关键假设做最小闭环验证而不是简单地把所有功能砍掉一半。我做的项目方向是面向轻问诊场景的患者档案管理工具初衷是验证“医生是否愿意通过结构化的患者自述文件快速生成首诊摘要”。在这个前提下第一步不是写代码而是界定MVP的业务边界。我先把完整的业务场景拆成了一堆功能点然后按照“是否支撑核心假设”和“是否影响演示观感”两个维度做筛选。最终进入MVP范围的只有四个模块患者基础档案录入姓名、年龄、主诉、既往史等核心字段问诊记录的追加与时间线展示首诊摘要的自动生成基于模板拼装档案的导入导出用于医生离线查阅和其他系统对接像药品库存管理、预约排班、在线支付、消息推送这类功能虽然真实场景迟早要加但在MVP阶段一律砍掉。每砍掉一个功能就意味着数据模型里少一张表、交互界面少一个分支、测试矩阵少一层组合。这个过程中一个关键的启发MVP的数据模型不需要面面俱到但必须做到“核心闭环不绕路”。什么意思呢就是用户在使用产品完成核心任务时每一步操作的数据流转路径都不应该出现断裂。比如医生录完一条主诉后要生成摘要摘要要能保存并导出——这三步之间的数据关系在文件架构里必须是一气呵成的而不是录完之后还要人工去编辑某个文件才能继续下一步。也因为这点File-Based架构的目录设计几乎成了MVP蓝图的可视化映射。我设计的数据目录结构如下data/ ├── patients/ │ ├── p_10001.json │ ├── p_10002.json └── consultations/ │ ├── c_50001.json │ ├── c_50002.json └── templates/ ├── first_visit.md患者文件和问诊文件分开存放通过患者ID建立关联。模板目录放摘要生成的模板文件。整个结构跟业务的动词和名词一一对应产品在验证期改功能时这个目录跟着微调就行了远不需要像数据库一样搞Migration。3. 文件即API数据层的落地设计与实现数据层是整个File-Based MVP的核心它的设计质量直接决定了后续业务开发的幸福感。我在这套系统里自己规定了一条原则除了启动时的配置加载业务代码一律不允许直接读写文件系统所有数据访问都通过统一的数据访问服务完成。这个服务就是所谓的“文件即API”层。为什么非要加这一层因为文件系统不是数据库没有查询引擎也没有事务机制如果每个业务方法都直接去操作JSON文件很快就会陷入路径硬编码和格式不一致的泥潭。而通过一个集中的Repository层封装所有读写操作至少可以做到文件路径单一来源管理、统一处理文件锁与并发、序列化与校验逻辑可复用。我用Python来实现这一层。选Python没有特别复杂的理由写起来快处理JSON顺手而且医字号项目后续要做简单的文本处理比如摘要提取Python生态也方便。当然用Node.js或者Go也完全可以核心思路是通用的。在数据访问服务里最核心的是两个组件存储引擎和查询入口。存储引擎负责管理文件与业务对象之间的映射。患者档案按一个文件一条记录的方式存储数据结构大致是这样{ id: p_10001, name: 张女士, age: 34, chief_complaint: 间断性头痛两周加重三天, past_history: 无特殊病史, created_at: 2025-01-12T10:30:00Z, updated_at: 2025-01-12T10:30:00Z }问诊记录则独立存成文件与患者通过patient_id建立关联{ id: c_50001, patient_id: p_10001, doctor_id: d_001, visit_date: 2025-01-12, chief_complaint: 头痛加剧伴恶心, assessment: 疑似偏头痛建议进一步检查, plan: 开具止痛药建议睡眠调整, created_at: 2025-01-12T14:00:00Z }查询入口方面我实现了一个极简的Repository基类核心方法包括get_by_id、list、save、delete、find_by_field。find_by_field做的事情其实就是遍历目录下所有JSON文件、按字段匹配听着原始但在MVP阶段单目录下几千个文件、每文件几千字节的体量下性能完全不是问题单次遍历基本也就是几十毫秒的事。这个方案还有一个附加的好处数据文件本身具有自描述性。在任何一台机器上打开data目录不用启动任何软件人就能直接读懂业务数据的全貌。我甚至直接在医生的电脑上把data目录拷给他他用VS Code打开就可以审查或修改数据这种透明感在数据敏感的医字号场景里对建立信任很有帮助。4. 权限、安全与并发File-Based不容回避的三个硬骨头File-Based架构依赖文件系统就必然要面对一些数据库天然解决的问题。这三个问题分别是访问控制、数据安全和写并发。它们任何一个处理不好都会成为MVP演示现场翻车的导火索。访问控制方面我采用的是进程内角色校验加目录权限双层防护。应用层代码里通过登录态判断用户的角色admin、doctor、staff每个角色能访问的API路由是固定的。与此同时系统启动时会把不同角色的可访问目录显式设置成不同权限组。比如接待人员只能读写patients目录中标记为“待完善”的档案医生可以读写全部患者档案和问诊记录管理员才能访问templates目录。这样做虽然不如数据库行级权限那么细腻但在文件层级上实现了最基本的隔离足够应付多数演示场景。数据安全方面最敏感的是患者健康信息。在本地开发阶段我用的是全明文文件因为方便调试但到了要部署到演示服务器或者给合作方试用的阶段就必须对敏感文件做加密。我采用的方案是项目级加密通过环境变量传入密钥在数据访问服务中增加一个透明加解密层读写时自动执行AES-GCM加解密。这个加密粒度是文件级别牺牲了一点灵活性但换来了“数据目录即使被整个拷走没有密钥也无法解开”的安全基线。另外所有导出操作都会在文件名中加入批次号和日期方便追踪数据流向。写并发方面File-Based架构天然弱于数据库。早期我遇到过两个医生同时更新同一条患者档案记录后写入的一方直接覆盖了先写入的内容。解决思路分两步走应用入口处给患者粒度的操作加上线程锁同一个进程内使用Python的threading.RLock保证同一患者档案的写操作是串行的跨进程场景则依赖文件锁fcntl在写前lock文件。这个方案严格来说牺牲了一部分吞吐量但MVP阶段的并发量本来就不高保证数据不错乱才是首要目标。处理完这三个问题之后这套File-Based方案从架构角度已经达到可演示、可试用、可临时部署的标准。安全这种事情在MVP阶段做到“相对安全”即可但要明确哪些数据是必须保护的底线比如患者的身份信息和主诉病情绝对不能被非授权人员拿到明文。这也是我用加密层的初衷。5. 从MVP到可扩展File-Based架构的演进路线与踩坑实录如果这篇博文只讲File-Based怎么成、不说它怎么败那就不够诚实。认真讲File-Based架构在数据量膨胀、需要复杂关联查询、多端并发写入这三个信号出现之后就应该启动向数据库的迁移。但在那之前它确实能帮你省下大量前期成本。说说我实际踩过的坑基本集中在三个场景第一个坑是把文件系统当关系型数据库用。当时想要在问诊记录里按“诊断结果”字段做聚合统计直接在Python里遍历所有文件算出结果。数据量几十条时挺快到了几百条也能接受但当问诊记录长到几千条、字段里还有大段文本时聚合查询明显变慢内存开销也上来了。后来我用了一个补救方案在写入时同步维护轻量索引文件一个JSON字段值到文件ID列表的映射让聚合查询只做一次映射查找而不是全量扫描。如果用好这个思路纯文件方案的承载力能往上抬高不少。第二个坑是字段设计的“随意性”。JSON文件用起来太灵活了导致我前两周写下的字段名前后风格不统一比如created_at和createTime混用后来不得不写脚本做数据清洗。这个坑的根源不是格式问题而是缺少一个显式定义的Schema。后来我引入JSON Schema做启动时校验所有数据文件在应用启动时先做字段校验不合格的及时报警让问题在开发阶段就暴露出来。第三个坑是跨平台兼容性。开发时在Mac上运行的路径处理逻辑到了Windows演示机器上目录分隔符不一致直接导致部分文件访问失败。解决方案是统一用pathlib管理路径禁止手工拼接路径字符串。这类问题很蠢但确实只有挨过一次才知道哪里会出问题。关于演进路线我的建议是分层演进而不是推倒重来。数据访问服务层保留把底层实现从“读写文件”替换成“读写SQLite”或者“读写PostgreSQL”上层业务代码基本不用动。如果一开始就把所有数据访问封装在Repository层里这个替换过程是平滑的。File-Based不是终点它只是一个聪明的起点。用最低的成本验证业务模型是否成立等验证通过了再根据数据规模和发展阶段决定是否要引入重型存储。就我目前的使用体验来说File-Based架构特别适合有明确数据边界、但需求还在快速摇摆期的项目。医字号MVP用它来做省下来的时间不是一星半点而且整个开发过程让人对业务数据的流转路径有了清晰认知。如果你也在做类似的轻量级项目不妨抛开“必须上数据库”的惯性思维试试这套更接近信息本质的做法。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →