解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
大石头 authored at 2018-05-15 21:21:05
11.81 KiB
X
--- description: 'NewLife.Core 核心库研发约束:逻辑正确性绝对第一、精简覆盖与公共 API 最小化、跨 TFM 低版本 Stub 垫片体系、反炫技与证据驱动的优化、大/小版本破坏性变更分级、重构分析以简单直白问题清单呈现(并入功能清单待修复项)、库级验证与编辑安全。适用于 NewLife.Core 仓库内的任何代码修改、缺陷修复、重构、审计与性能优化任务。' applyTo: '**' --- # NewLife.Core 库级指令 本文件是 **NewLife.Core 核心库**的库级指令,叠加在 NewLife.Skills 全局约定(`newlife-global`、`development` 等)之上。 - **只写库级特有约束**;全局已说过的(加载标注、兼容性约束/条件编译符号、类型名与命名、代码风格、Region/日志、文档注释、内置工具优先、防御性注释、工作流、xUnit 测试、Markdown 与提交信息规范、关键禁止项、深度思考与独立立场、Agent 协作协议)**一律不重复**。 - 加载标注:本指令名为 `newlife-core`,命中本仓库任务时应在首行 `📋 生效` 标注中列出。 - **资料优先级**:代码 **XML 注释(Tier 1)第一** → 本仓 `Doc/*.md` 专题文档(`Doc/核心库目录.md` 可作索引) → 源码 → 联网。 - **适用边界**:本库是**基础类库**,不套用 `development` 指令的"新建系统"流程(需求文档 / 功能拆分 / 竞品分析 / 迭代任务台账);本仓 `Doc/需求文档.md`、`Doc/功能清单.md`、`Doc/架构设计.md` 是**库能力逆向盘点**,不是研发任务追踪。 - 与全局指令冲突时本指令优先;一切取舍以更安全、更正确的口径为准。 --- ## 1. 逻辑正确性绝对第一 **正确性优先于可读性、性能、风格与简洁**——任何取舍都不得以牺牲正确性为代价。核心库被海量生态以**二进制**方式引用,一处逻辑错误的影响面是全局的。 - **改动前必须做全场景枚举**:列出输入域与状态组合,逐条确认行为——`null` / 空 / 边界 / 越界 / 负值;**链式分片跨段**;**引用计数与所有权**;**并发多会话**;各 TFM 的**条件编译分支**;异常与关闭路径。 - **必须能解释"为什么这样是对的"**,而不是"我改了什么"。给不出正确性论证的改动,不做。 - **不确定就不改**:标 ❓ 待确认,或先只读审计;**禁止猜测式修改**(凭印象写 API、凭感觉断定语义)。 - **同源缺陷一并排查**:修一处时检查同源的其他实现是否同病(如 `IPacket` 四实现、多处解码路径、多份会话状态位、各包实现语义口径不一)。 --- ## 2. 精简覆盖与公共 API 最小化 > 精简覆盖(八二原则、约 90% 场景、长尾交扩展点、不为长尾堆代码)见全局 `newlife-global` §2.7,此处不重复。**库语境的增量只有一条:公共 API 是永久契约,必须最小化。** - 每个公开成员都要考虑"**以后能不能收回**";新增公共 API 必须能覆盖多数场景才值得固化——**宁少而稳**。 - 公开面一旦铺开就难收回:宁可先用扩展点(接口 / 虚方法 / 事件)承接,真实需求出现后再增量演进。 --- ## 3. 跨 TFM 与低版本支持(Stub 垫片体系) > **核心 TFM 是最新 LTS**(net8.0 / net10.0 等,含 `-windows` 变体);net45 / net461 / net462 / netstandard2.0 等**广兼容底线靠 stub 反向补齐**。 - 本库用 `NewLife.Core/Stub/` 为低版本**直接定义**缺失的 BCL 类型,高版本用 `*Forwards.cs` 的 `TypeForwardedTo` **转发到 BCL**(消除类型标识冲突——否则 ns2.0 编译的库在 net10 运行会 `TypeLoadException`)。已补齐 `SequenceReader`(+Extensions)、`IAsyncDisposable`、`IAsyncEnumerable` 系列、可空性注解族、`IsExternalInit` 等。 - 另散落垫片:`Common/TimeProvider.cs`、`Common/Index.cs`、`Common/Range.cs`、`Extension/ConcurrentDictionaryExtensions.cs`、`Threading/ITimer.cs`、`Threading/TaskEx.cs`、`Buffers/SequenceReaderHelper.cs`(清单为示意,新增垫片后同步更新本文件)。 - 本库**自研** `NewLife.Data.Pipe` / `PipeReader` / `PipeWriter`,命名形态对齐 `System.IO.Pipelines`(同名不同命名空间),**全 18 个 TFM 可用(含 net45)**——因为 BCL 的 `System.IO.Pipelines` 最低 netstandard2.0、net45 用不了。 - **禁止轻易断言"低版本不支持 X"**。做架构方案 / 评审前,先查 `Stub/`(含 `*Forwards.cs`)、`Common`/`Extension`/`Threading` 垫片与 `Data/Pipe*.cs`——本库大概率已补齐或用等价自有类型覆盖。 - 需要跨版本能力时,**优先复用既有 Stub 补齐 / 自有等价类型**;确需按框架差异处理时,再遵循全局的条件编译降级规范。 - **能力边界**:Stub 只能补齐**缺失的类型**(及高版本转发),**补不了** BCL 既有类型上**新增的成员 / 静态方法**(如 `ArgumentNullException.ThrowIfNull()`、`Enumerable.Chunk()`、`string.Split(Char, StringSplitOptions)`)——这些仍需条件编译降级或改用自有等价实现。 - 新增垫片必须遵循双模式:低版本直接定义 + 高版本 `TypeForwardedTo` 转发。 --- ## 4. 反炫技、反无据优化 - **默认用最直白、最简单的写法**;不为"看起来更聪明"改写。 - **优化必须证据驱动,并与场景匹配**:先看这行代码的**执行频率与竞争概率**。**低频、几乎不会有并发冲突的场景不值得为原子操作 / 锁 / 池化 / 缓存付出复杂度**——保持简单美。典型:`x ??= new X()` 本来满足要求,不要改成 `Interlocked` / CAS / `volatile`(仅当该处确为高并发热点、且**实测确有竞态**时才加固)。 - 明确标准:优化带来的复杂度与风险 **大于** 收益时不做;**无法用测量证明收益** 时不做。 - 全局已声明的热点约定(避免反射 / 复杂 Linq、`ArrayPool` 等)继续遵守,但同样以"确为热点"为前提,不无差别套用。 - **不做无实质变化的同义改写**(重命名、拆方法、换写法)——保持 Git diff 只反映实质变化。 --- ## 5. 版本兼容与破坏性变更(大 / 小版本分级) | 版本 | 允许的破坏性变更 | 兼容要求 | |---|---|---| | **大版本**(如 v12 网络库重构) | **模块级重构,大量破坏性变更** | 以更优架构为目标,不为兼容旧设计妥协;**不需要写生态迁移文档** | | **小版本** | **个别 API 变更,含新增参数** | **尽量兼容,优先避免** `TypeLoadException` / `MissingMethodException`,但**不 100% 保证**;**一般不允许删除 API 或删除参数**,除非出现**安全问题或严重逻辑错误** | - **评估下游影响时按序评估**:先看核心项目 **NewLife.Core / NewLife.Remoting / Stardust / NewLife.XCode / NewLife.Redis**,再看 `C:\X\` 下其它项目。 - 契约需要加能力时,**优先加在类上**(给类加成员对二进制安全)或**新建独立接口**;给既有公共接口**加成员 / 加继承**前必须先确认**是否有本库之外的实现者**——有(如 `IMessage` 被 Remoting 的 `HttpMessage` 实现)则**不可直接加**,只能新建接口 / 加在类上,或留到大版本;仅本库实现且生态零实现时才可加。 - **接口加成员 / 加继承 / 删方法 / 改返回类型 = 二进制灾区**:CLR 加载实现者类型时校验接口契约完整,缺一成员即 `TypeLoadException`(现象隐蔽:服务端静默、客户端超时);**只调用接口的消费方不受影响**。默认接口方法(DIM)虽不破坏实现者,但 net45 / netstandard2.0 不支持,本库不作为逃生通道。定位法:独立探针项目(新 Core.dll + 旧生态 dll)用 `Assembly.GetTypes()` 抓 `LoaderExceptions`。 - **删除 / 改名公开成员前必须先完成引用扫描**:扫本仓(含 **HEAD 版本** `git show HEAD:<file>`)与核心生态仓——并行会话的改写可能恰好移除工作区里唯一残留的引用,掩盖真实调用点。 - **版本字样**:源码与 XML 注释中**不出现** `v12` / `v13` 之类版本字样,用中性描述(如"简化模型""序列统一入口");版本号只出现在文档与提交信息中。 --- ## 6. 分析与重构的呈现方式(简单直白问题清单) - 被要求**分析 / 审计 / 重构 / 优化**时,**禁止直接抛出几十条密集晦涩的修改项**。 - 先产出**简单直白的问题清单**;**数量多时生成 Markdown 文档**,无论文档还是聊天回复都保持直白。 - 清单**并入 `Doc/功能清单.md` 的 `## 待修复项` 章节**(独立表,编码用 `FIX-`/`IMP-` 前缀),**不混入功能点表**——功能清单是长期能力盘点,问题清单是消费即销的工单队列:**只放未修条目,修完即删**(不写"已修"、不留修复过程叙述,历史由提交信息与代码注释承载;工程矩阵、覆盖范围、运行约定等永久信息放正式章节,不放待修复项)。 - 每条用**四要素**:**是什么问题**(一句人话)/ **有什么危害**(会不会算错、影响范围)/ **怎么修改**(一句话方向)/ **修改后的遗憾**(是否破坏性、变复杂、性能回退、需重构);附**编号 + 严重程度**(必改 / 建议 / 可选)。让用户做选择题。 - 用户挑选后:**逐项** 深入分析 → 修改 → 测试 → **单独提交**;一次只处理选中项,**不顺手扩大范围**。 --- ## 7. 库级验证清单 - **改动必须编译通过**:至少覆盖 **top 与 bottom TFM**(如 net10.0 与 net45 / netstandard2.0);涉及条件编译时全 TFM 验证。 - 编译期硬约束:`CA2007` 已设为 `WarningsAsErrors`(库内 `await` 必须 `ConfigureAwait(false)`);`Nullable` 已启用,空值语义用 NRT 真实建模,不用 `!` 压制。 - **逻辑改动必须有对应单元测试**;缺陷修复补**负向验证**(退回旧实现,新测试应变红),否则测试可能是假通过。 - 网络 / 并发改动要在**真实 TCP/UDP** 上验证,覆盖**链式分片、引用计数所有权、多会话并发不串包**。 - 跑全量测试**带超时**(Windows 上 testhost 可能测试跑完却不退出);本地全量并行跑测用根目录 `run-tests.ps1`(10 宿主并行 + 超时兜底 + trx 汇总)。 - **测试工程**:全量 `XUnitTest.Core`(net10.0);跨版本兼容 `XUnitTest.Compat`;热点优化以 `Benchmark/` 基准为准(见 `benchmark-testing` 技能)。 - **编辑安全**:用整块替换改代码时,**替换块避开结构起止符号**(类 / 方法 / 循环的花括号、`/// <summary>` 行等),首尾结构必须对齐;**大块替换后立刻 `get_errors` 并回读改动点**(本仓曾发生"类声明的 `{` 被删""方法的 `<summary>` 行被替换"两次事故)。 - 改动公开面后,对核心生态仓做引用扫描(`git grep`),再决定是否保留。 --- ## 8. 提交与收尾 - **每个问题项解决并测试通过后,独立提交**,不攒到最后;**只提交、不推送**——`git push` 始终由用户手工决定。 - **原因**:工作区常被多个并行会话共用,各会话必须**各自提交**自己的成果,否则所有改动堆在工作目录,无法区分归属。 - 提交前先查 `git diff --cached --stat` 确认暂存集,**只提交本会话的路径**(pathspec 隔离,如 `git commit -m "..." -- <path>`),避免裹入他人未提交 / 已暂存的改动。 - 小颗粒、按依赖顺序分组,**每组独立可构建**;提交后报告提交清单与"领先 origin N 个提交"。 - **审计 / 分析类临时文档一律放 `.tmp/`(已在 .gitignore 忽略),不写进 `Doc/`、不提交**;审计全部完成后另行决定归档或清理。 - 提交信息规范与文档规范见全局指令,不在此复述。 --- (完)