14 · 架构、编程风格与可配置 SQL
本章概述 Factuzam 演进所遵循的技术规则,面向开发人员、高级支持人员和实施人员。
仓库的完整参考资料位于 LIBRO_DE_ESTILO_DELPHI.md、
LIBRO_DE_ESTILO_BBDD.md、PLAN_SOLID.md 和 MANUAL_SQL_PERFILES.md。
1. 编程风格
Factuzam 使用 Object Pascal/Delphi VCL 编写,优先确保代码可读、可预测, 并与现有安装基础兼容。
主要规则:
- 代码、自定义名称、注释和提交使用西班牙语;保留 Delphi 和第三方组件前缀。
- 每行一条语句。
if、while和for的条件与操作分别放在不同的行。 - 新代码避免使用
Exit和Continue,让方法的完整流程保持可见。 - 每个类的分区中先声明字段,再声明方法,以符合 Delphi 要求。
- 注释应简短,用于解释决策、限制或业务规则,不重复显而易见的代码。
- 方法以西班牙语动词命名,并表示一个连贯步骤。扩展大型类之前, 先提取协作者、策略或领域函数。
- 维护表单继承自
TfrmMtoGen,模态窗口继承自TfrmBase; 独立工具保留各自项目。 - UniDAC、DevExpress、JEDI 和 FastReport 是既定架构决策, 没有充分理由不得用新依赖替换。
数据库变更以幂等脚本形式放在 DESARROLLOS EN CURSO/。
不得修改 factuzam_original.sql 转储。
2. 渐进式应用 SOLID
Factuzam 正在以分册方式,从旧版核心逐步迁移到 SOLID 架构。 这并不是一次已经完成的重写:每次提取都先通过测试固定行为, 再减少耦合,并避免混入功能变更。
| 原则 | 在 Factuzam 中的应用 |
|---|---|
| SRP — 单一职责 | 表单协调界面,data module 负责持久化,库执行业务规则。大型职责会提取为 TGestor* 协作者或专用服务。 |
| OCP — 开闭原则 | 采购、销售、打印或单据差异通过配置和策略建模,避免为每种情况复制完整表单。 |
| LSP — 里氏替换 | 基类公开一致的契约和 hook;如果派生类必须用空方法取消行为,则不继续扩展该基类。 |
| ISP — 接口隔离 | 每个消费者只获得所需能力。自有接口保持精简、带 GUID,并且只在共享同一实现时组合。 |
| DIP — 依赖倒置 | 领域依赖 inLib*Intf 契约;UniDAC 实现在外部创建,并从组合根注入。 |
每个分册的顺序是:用测试固定行为、提取一项职责、编译 Win32/Win64、 运行 DUnitX 测试组,并检查自动架构棘轮。
3. 分层与依赖方向
fzam.dpr / Core (composición)
|
v
Forms / Modals (presentación y coordinación)
|
v
UniData* (persistencia) ---> inLib* (dominio y colaboradores)
|
v
inLib*Intf (contratos)
| 层 | 职责 |
|---|---|
| Core / 组合 | 创建连接、仓库、服务和表单;将实现与契约连接。 |
| Forms / Modals | 显示数据、请求确认、协调标签页,并将业务结果转换为界面操作。 |
| UniData / DataModules | 通过 UniDAC 查询和持久化,控制数据集和事务边界。 |
| inLib | 计算、验证、转换、编排器和可复用协作者。 |
| **inLib*Intf** | 不依赖 VCL、表单或持久化实现的稳定接口和类型。 |
领域库不会创建仓库、不了解表单,也不会获取全局连接。 它通过构造函数或参数接收所需契约。连接、身份和凭据都有明确的所有者和生命周期。
影响多张表的写入是原子的:遵循现有事务,或在同一层执行 Commit/Rollback。
线程不会与界面共享数据集或连接。
4. 可配置、可查询的 SQL
按配置文件管理的 SQL 目录允许修正特定读取查询,而无需重新编译或替换
fzam.exe。领域向仓库请求业务操作;持久化实现会选择:
- 可执行文件内置并经过测试的基础 SQL。
fza_usuarios_perfiles中启用的自定义 SQL。
领域不会接收 SQL 文本,也不提供通用 Ejecutar(SQL) 方法。
每个操作使用以下格式的稳定键:
KEY_USUPER = SQL_REPOSITORIOS
SUBKEY_USUPER = SQL__Repositorio__Operacion
按界面启用
配置属性 oGetSQLFromDB 为每个使用表单启用目录。打开界面时:
- Factuzam 加载共享目录定义。
- 发布尚缺少的基础操作,但不覆盖已有自定义内容。
- 针对活动配置或基础 SQL 解析每次读取。
在一个表单中停用开关,不会改变同一操作的其他消费者。
读取开关、发布配置或向目录提供定义的单元清单,以及 data module 的历史流程,
见 MANUAL_SQL_PERFILES.md。
验证与安全回退
执行自定义内容前会检查:
- 不为空;
- 是有效读取(
SELECT或返回数据集的CALL); - 精确保留声明的参数;
- 返回全部必需字段和别名;
- 不包含多条语句;
- 不包含
DROP、ALTER或TRUNCATE。
验证失败时,会放弃自定义查询、记录原因,并执行基础 SQL。 如果验证通过,但打开失败或返回错误结构,Factuzam 会用基础 SQL 重试一次。 如果基础查询也失败,则按正常方式显示错误。
写入不会使用此自动重试:未来任何写入自定义都必须受事务保护,
并在切换实现前执行 Rollback。
检查、审计与回退
目录管理员可发布、检查和导出基础定义及配置定义。 检查会显示状态、策略、版本、指纹、验证和最后回退原因。 每行还保存修改时间和用户。
要立即恢复可执行文件内置行为,可以:
- 将操作状态从
S改为N,使其停用。 - 只删除该自定义行。
- 为整个界面设置
oGetSQLFromDB=False。
无需部署其他可执行文件。编辑查询前应备份 SQL 及其元数据; 绝不能更改契约要求的参数或别名。
5. 测试与防回归规则
- DUnitX 覆盖领域函数、协作者和虚假仓库,无需真实数据库。
- 集成测试覆盖存储过程、SQL 和事务。
- 棘轮脚本阻止重新引入跨层依赖、领域中的新 SQL、全局变量, 或类和方法超过当前上限的增长。
- 重构不会混入功能变更、大规模重命名或格式标准化。
- 关闭跨模块变更前,验证受影响的 Win32 和 Win64 平台。
目标是让每次改进都留下自动屏障,使后续代码无法再次越过。