> For the complete documentation index, see [llms.txt](https://docs.zongsoft.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.zongsoft.com/overview/pluginization/evolutionary-delivery.md).

# 从局部改造到可验证的插件交付

用可独立验收的业务切口渐进引入插件，让每一步都可运行、可观察、可回退。

运行中的业务系统很少有机会停掉所有需求来做一次彻底重构。引入 Zongsoft 插件化也一样：不必一次把所有代码都搬进新结构，而是选一条责任清晰的业务路径，验证它的服务、装配与部署，再逐步扩大范围。每一步都应留下可运行、可观察、出了故障知道如何处置的版本。

## 先固定基线，再选切口

改造前先固定可观察的行为：给定输入返回什么、哪些身份允许调用、异常如何表现、资源消耗大致如何。后续每一步都与这个基线比较，才能知道结构调整是否悄悄改变了业务。

首个切口最好具备这些特征：

* 输入输出明确，调用链可以追踪；
* 数据所有权与依赖相对清楚；
* 有独立的验收方式，不依赖整套环境才能验证；
* 尽量先选无副作用或副作用可控的路径。

论坛的用户导出是一个可以参照的例子：现有[模板模型提供者](https://github.com/Zongsoft/discussions/blob/main/src/Features/Archiving/UserDataTemplateModelProvider.cs)通过用户服务取得数据。若要改造类似能力，可以先保留调用入口和业务规则，把模板适配与资源交付组织成插件，再验证结果、筛选范围和权限。导出是“只读”也不意味着可以绕过数据范围约束。

## 让每一步都有可运行的结果

| 阶段     | 主要改变           | 继续推进的依据              |
| ------ | -------------- | -------------------- |
| 提取业务入口 | 原入口改为调用职责明确的服务 | 原有结果、权限和失败行为仍可验证     |
| 声明插件装配 | 补齐清单、依赖和必要扩展   | 在目标宿主中能加载并解析服务       |
| 固定交付文件 | 编写部署规则，收集配置与资源 | 在干净运行目录中完成一次真实调用     |
| 切换调用路径 | 新实现接管明确范围的调用   | 能观察错误、时延和新旧结果差异      |
| 收回旧实现  | 清理重复入口和不再需要的依赖 | 调用者已迁移，运行记录证明旧路径不再使用 |

“切换”是一项发布安排，可以通过应用路由、配置或发布批次实现，不表示框架自动支持在线替换已加载的程序集。若需要并行比较新旧实现，优先从无副作用且允许比较的数据读取开始：写操作不能各自执行一遍来比对结果，重复发送通知、重复扣减或重复创建文件，可能造成无法靠回退程序集恢复的业务影响。

## 把发布组合当成验证对象

![从选择版本组合到组装产物、验证运行，并贯穿数据兼容检查](https://847714710-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FdTV8LtunzSisrDXg3zNv%2Fuploads%2Fgit-blob-4170e57fad6e50f9938fc37446e26ef0073a799e%2Fzongsoft-plugin-evolutionary-delivery.png?alt=media)

*宿主与插件版本确定以后，还要交付配置、映射和资源，并验证启动、业务调用与恢复方案。数据兼容与迁移需要单独设计，不能由文件回退替代。*

论坛的[领域部署文件](https://github.com/Zongsoft/discussions/blob/main/src/Zongsoft.Discussions.deploy)包含清单、选项、映射和程序集规则；[Web 部署文件](https://github.com/Zongsoft/discussions/blob/main/src/api/Zongsoft.Discussions.Web.deploy)另含 Web 清单与模板。这说明可用的交付单元要覆盖运行所依赖的元数据和资源，而不只是 DLL。

对有多种客户方案的产品，建议记录每种受支持组合使用的宿主、插件版本、数据驱动、配置要求和迁移步骤。发布验证至少要覆盖实际支持的最小组合与关键扩展组合，并区分“遗漏可选插件”与“遗漏必需插件”的结果。不必把理论上所有排列都宣称成产品能力。

独立发布一个插件包，意味着可以单独产出和管理它；该版本能否投入使用，仍取决于宿主、共享依赖、扩展契约和数据结构是否兼容。同一进程内共享程序集版本冲突，不能靠给插件目录改名解决。

## 数据变化决定恢复边界

插件版本回退只覆盖程序文件时，数据库与外部文件可能已经改变。发布前需要回答：新增映射字段后旧版本能否忽略它；转换存储格式后旧版本能否继续读取；新版本是否已发出不可撤回的外部通知。

可以按需求采用“先增加兼容字段、逐步迁移数据、切换读写、最后移除旧结构”的过程。对无法兼容旧版本的数据变化，应明确恢复方案和维护窗口。部署工具负责交付产物，不会替应用推导数据迁移与业务补偿，分工见[部署模型](/overview/deployment.md)与[升级接入与故障恢复](/framework/upgrading/workflow.md)。

## 何时值得进一步拆成独立进程

插件化帮助组织代码与运行时装配；进程拆分则增加新的故障与通信边界。二者可以按实际需要组合：

| 出现的需求          | 首先评估的方案        | 额外成本或限制         |
| -------------- | -------------- | --------------- |
| 多产品选用不同能力      | 插件与部署方案组合      | 需要管理受支持的版本组合    |
| 多种入口共享业务规则     | 分离业务服务与宿主适配    | 仍需接续身份、配置及运行依赖  |
| 某项工作需独立扩容或故障隔离 | 把相关能力放入独立宿主进程  | 需要协议、超时、观测及故障恢复 |
| 不可信扩展需要权限隔离    | 在部署与运行环境建立安全边界 | 同进程插件不能提供这类安全保证 |

把本地调用迁到网络后，失败不再只有成功或异常两种直观结果：请求超时时，远端可能已经完成写入。需要重新约定幂等、重试、数据所有权和结果查询，而不是只把接口实现换成远程客户端。进程拆分不应成为每个插件必须经历的终点。

## 用一次发布检验设计效果

完成首个切口后，检查下一次需求能否主要落在自己的业务范围内、运行目录能否重复组装、故障能否定位到服务调用或装配阶段、交付负责人能否说明恢复步骤。这些结果比“新增了多少个项目”更能反映改造是否有效。

边界尚不清楚时，返回[从业务变化确定模块边界](/overview/pluginization/business-boundaries.md)重新检查变化与规则的归属；模块间的扩展约定见[把扩展点设计成协作契约](/overview/pluginization/extension-contracts.md)。实践路径从[编写第一个业务插件](/get-started/first-business-plugin.md)和[部署第一个插件](/get-started/deploy-first-plugin.md)开始。

## 延伸阅读

* Elux 作者关于[拆解大型前端应用](https://www.cnblogs.com/hiisea/p/16914890.html)的文章用“分层与切块”讨论了渐进式拆分大型应用的思路，与本篇的服务端插件化演进相呼应；前端模块的加载机制不等于插件升级保证。
* 部署模型见[部署模型](/overview/deployment.md)，宿主交付见[部署宿主](/hosting/deployment.md)。
* 运行问题的分层排查见[运行与调试](/get-started/run-and-debug.md)。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.zongsoft.com/overview/pluginization/evolutionary-delivery.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
