引言
做Flutter做得稍微久一点,你大概率会发现一件挺有意思的事。几乎没有人不会起项目,大家也都知道怎么接路由、怎么接网络、怎么写页面,感觉就是Flutter这件事挺简单的,几天就能把一个应用壳子跑起来。
但问题往往不出在第一个版本,问题出在第二个版本、第三个版本,出在项目从“能跑”开始慢慢变成“要长期维护”的那个阶段。你会发现,一开始写得很顺手的结构,后来越来越难改;一开始觉得灵活的做法,后来开始互相打架;一开始觉得没必要抽的东西,后来每个业务都在重复写。
更麻烦的事,业务变多之后结构会不会散;人变多之后边界会不会乱;平台变多之后能力接入会不会到处泄漏;基础设施变多之后会不会每个模块都自己造一套。所以一个可用的脚手架真正要解决的问题,不是今天能不能把项目起起来,而是半年后、一年后,这个项目在复杂性增长的情况下,会不会失控。
什么是可用的脚手架
1. 可扩展
当你要往这个项目里继续加业务、加模块、加平台能力的时候,不需要频繁去推翻原来的结构。一个项目当然都能加功能,问题不在能不能加,而在加的时候代价有多大。如果你每增加一块能力,都得去改入口、改全局依赖、改公共代码、甚至改一堆已有页面,那这个结构其实是不稳的。可用的脚手架,应该让变化尽量局部化。你加一个业务模块,应该主要改业务模块;你加一个基础设施能力,应该能找到它在工程里的合理归属。它不是不允许变化,而是能够承受变化。
2. 可复用
这个好理解,但最容易被低估。很多项目的问题不是没有公共能力,而是公共能力没有真正沉淀成脚手架资产。主题一套一套写,国际化一页一页补,日志和异常处理看谁想起来谁加,工具方法复制来复制去,最后每个人都觉得自己在快速开发,实际上是在反复生产重复代码。可用脚手架存在的一个很现实的意义,就是把那些跨业务、跨页面、跨模块都会不断被用到的东西收敛起来,让业务层少重复,让团队少内耗。复用不只是代码复用,还是决策复用、约束复用、接入方式复用。
3. 可协作
这个维度是很多单人项目最难感知,但团队项目最痛的地方。单人开发的时候,很多结构问题不明显,因为你脑子里知道所有上下文,你知道这个工具类为什么放在这里,知道这个状态为什么先这么写,知道这个平台逻辑为什么暂时塞在页面里。可一旦团队里有三个人、五个人、十个人,这种隐形知识很快就会失效。工程如果没有清晰的边界、稳定的依赖关系和明确的能力分层,协作成本会非常高。很多项目后来难维护,并不是代码写不动,而是没有人敢动,因为谁都不确定一改会影响哪里。所以一个可用脚手架,一定是面向协作设计的,而不是只面向作者自己设计的。
4. 可演进
这个标准特别重要。因为所有架构设计在今天看起来都可能是合理的,但合理不代表能长久。项目在第一个阶段可能只有几个页面,第二个阶段开始接支付,第三个阶段开始拆模块,第四个阶段开始接新的平台,后来还可能要做埋点、监控、环境切换、性能治理。问题不是你一开始能不能把这些都考虑进去,而是当这些需求真的出现时,你的结构能不能平滑调整,而不是每次都推倒重来。一个可用的脚手架,未必一开始功能最全,但它一定要允许自己升级。它必须有演进空间,而不是一开始看起来很轻,后来每走一步都很疼。
总结下来
脚手架需要的其实不是“搭工程能力”,而是“隔离问题的能力”。
根据这几年的工作经验,写了一个差不多的脚手架用于交流 分层图如下
项目分层图
第 1 层:应用入口层
flutter_demo
├── main.dart
├── lib/entry/
├── demo_app_context.dart
└── app_observer.dart
作用:
负责应用启动、全局初始化、ProviderScope 注入、路由启动、应用上下文编排。
第 2 层:应用编排层
modules/app_demo
├── 页面示例
└── 路由注册
作用:
承载当前 Demo 应用的页面、交互和示例业务,是“可运行应用层”。
第 3 层:基础设施层
modules/app_foundation
├── foundation_base
│ └── 应用上下文、模块上下文、基础框架抽象
├── app_router
│ └── 路由能力
├── app_theme
│ └── 主题能力
├── app_localizations
│ └── 国际化能力
├── app_ui
│ └── 通用组件体系
├── app_util
│ └── 日志、网络、设备、加密、存储等工具
└── file_access
└── 文件访问与平台通道封装
作用:
提供所有可复用的基础能力,不直接承载具体业务页面,是整个脚手架的“公共底座”。
第 4 层:能力模块层
modules/app_pay
├── 微信支付
└── 支付宝支付
作用:
把具有明确领域边界、可独立接入的能力抽成模块,避免污染应用入口层和基础设施层。
第 5 层:预留业务层
modules/business_module
作用:
预留给未来真实业务域拆分。
第 6 层:依赖聚合层
modules/third_deps
作用:
统一管理三方依赖,包括 Riverpod、BLoC、Dio、Sentry、TDesign 以及大量 OHOS 适配插件。
这一层不直接承载业务逻辑,而是给上层模块提供一致的依赖入口。
简介
最上面是应用入口,负责把应用真正拉起来。
往下一层是 Demo 应用本身,承载页面和交互。
再往下是基础设施层,主题、国际化、路由、工具、UI 组件都沉在这里。
支付这种独立能力,不直接塞进基础层,而是单独做能力模块。
未来真实业务,预留在 business_module 这一层。
所有三方库不分散管理,而是通过 third_deps 统一收口。