ADR-0001:Classic 与 Next 双轨独立发展
- 状态:已接受
- 日期:2026-08-22
- 决策者:WePush 项目维护者
背景
当前 WePush 是一个已经稳定运行和发布的 Java Swing 客户端,具备完整的消息配置、用户导入、任务调度和批量推送能力。项目计划在 next/ 目录中建设新的目标架构,包括 Core Engine、Agent、Java SDK、Service、Desktop UI 和 WebUI。
如果直接在现有客户端中持续拆分,会同时影响现有用户、发布节奏和新架构设计。另一方面,为了强制消除重复代码而建立跨项目公共模块,也会重新产生构建、版本和架构耦合,限制两条产品线的独立演进。
因此,需要明确 Classic 与 Next 之间的长期关系,以及对代码重复的处理原则。
决策
WePush 采用 Classic 与 Next 双轨独立发展的模式。
- 当前仓库根目录下的客户端视为 Classic,继续按照现有产品定位、技术架构和发布流程独立发展。
next/是自包含的新项目,用于实现新的目标架构,并拥有独立的构建入口、模块结构、依赖管理、测试和发布流程。- Classic 与 Next 之间不建立运行时或编译期依赖。Next 不依赖 Classic 的 Java 包、数据库实体、静态工具类或内部实现,Classic 也不依赖 Next 的模块。
- 不为了复用代码而建立跨两条产品线的
shared、common等公共模块,也不使用软链接、共享源码目录或其他隐式源码复用方式。 - 两边允许出现相同或相似代码。复制代码是被接受的工程选择;代码一旦复制到另一条产品线,即成为该产品线独立维护的代码,不要求后续自动同步。
- 新功能、缺陷修复和安全修复根据实际需要决定进入 Classic、Next 或同时进入两边,不设置强制双向移植规则。
- Classic 与 Next 可以采用不同的数据模型、API、依赖版本和具体实现,也允许产品行为逐渐产生差异,不以内部实现兼容为目标。
- 两边可以共享需求理解、协议资料、供应商行为样例、设计经验和测试思路,但这些内容按需分别落入各自项目,不形成共享运行时制品。
- Classic 主要承担稳定桌面客户端和新消息类型快速实验场景;Next 按新的组件化、服务化目标发展,不为兼容 Classic 的内部架构而妥协。
- 两套应用使用独立的版本号、配置目录、数据存储、网络端口和安装标识,确保可以在同一环境中并行安装和运行。
结果
正面影响
- Classic 的稳定发布不会被 Next 的架构建设阻塞。
- Next 可以自由选择适合目标架构的模型、协议和技术实现。
- 两条产品线的依赖、版本和发布边界清晰,局部改动不会隐式影响另一边。
- 消息类型可以先在 Classic 快速验证,再按 Next 的 Provider SPI 和配置 Schema 重新实现。
- 避免公共模块逐渐演变为新的耦合中心。
接受的代价
- 某些 Provider、工具函数、协议适配和缺陷修复可能需要分别实现。
- 两边的相似代码可能随时间产生差异。
- 同时维护两条产品线会增加测试、发布和问题跟踪成本。
- 不能假设在一边完成的修复会自动覆盖另一边。
这些代价是本决策明确接受的,不应仅以“消除重复代码”为理由重新引入跨项目依赖。
实施约束
- Classic 保持当前根目录构建方式;Next 使用
next/下的独立构建入口。 - CI 按目录和产品线分别执行,任何一边都不能依赖另一边的构建产物才能完成测试或发布。
- Issue、提交和发布说明应标明适用范围:
classic、next或both。 - 从一边复制实现到另一边时,应同时复制或重写必要测试,并按照目标产品线的架构规范完成适配。
- 数据迁移通过显式迁移工具完成,Next 不直接操作或依赖 Classic 的运行时数据库。
- 如果未来需要改变本决策、引入共享模块或建立编译期依赖,必须提交新的 ADR 说明收益、边界和迁移方案。
非目标
- 不要求 Classic 与 Next 在任意时间点保持完整功能对等。
- 不要求相同消息类型在两边使用相同实现。
- 不建设自动代码同步机制。
- 不将 Classic 逐步改造成 Next;两者是独立产品线,而不是临时分支关系。