sml

SML { ❄ }

第 8 章:实战——完整项目配置

第 8 章:实战:完整项目配置

把所有学到的拼起来:一个接近真实的部署配置,覆盖契约、片段、include、环境变量、嵌套块、数组。

8.1 拆文件

common.sml(公共片段 + 契约):

@contract Service loose {
    name:    str
    port:    int  default 8080 min 1 max 65535
    debug:   bool default false
    peers:   array[str] ?
}

@base {
    region: cn-north-1
    timeout: 30
}

app.sml(主配置):

@version v1

include "common.sml"

# 顶层应用契约
@is Service
name: gateway
port: 9090
debug: true
peers: [ auth billing ]

# 片段继承复用
service auth { &base port: 7100 name: auth-svc }
service billing { &base port: 7200 name: billing-svc }

# 嵌套块 + 数组
database: {
    url: $env.DATABASE_URL
    pool: { min: 2 max: 16 }
}
features: [ logging metrics tracing ]

解析后你会得到一棵完整、结构正确、且经过契约校验的树:

8.2 渐进增强:命名空间隔离

当模块变多,把每个模块放独立文件并用命名空间:

include "auth.sml" as modules.auth
include "billing.sml" as modules.billing

gateway {
    auth: modules.auth.config
    billing: modules.billing.config
}

这样 auth.sml 内部随便定义 @contract / @name,都不会污染主文件作用域。

8.3 校验心智模型

写 SML 配置时,按这个顺序想:

  1. 结构:用块 {} 和数组 [] 把数据分层。
  2. 复用:重复的字段抽成 @name 片段,用 &name 引用。
  3. 拆分:文件太大就 include;要隔离就 as ns
  4. 约束:配置是给程序读的,用 @contract + @is 锁住结构,把错误消灭在解析期。
  5. 解耦:敏感 / 环境相关的值用 $env.VAR

8.4 下一步

恭喜你读完这本教科书!现在你已经能用 SML 写生产级配置了。→ 第 9 章:进阶

动手练习

读完本章,在下面的编辑器里直接修改 SML 并点“运行”,立刻看到解析结果或校验错误——有输出才能高效学习。

✍ 动手练习 写一份接近真实的部署配置:@contract Service 定义在主文件,@is Service 写 name/port/debug;service auth 与 billing 都 &base 并覆盖 port/name;database 块含 url($env) 与 pool{min,max};features 数组。
💡 提示:这是一个接近真实的部署配置:契约 + 片段 + $env 一起用(契约定义放在主文件,避免跨文件引用)。
✍ 自测考题:第 8 章自测:实战项目 得分 0 / 3
Q1. 一个真实部署配置通常会组合哪些能力?
Q2. peers: [ auth billing ] 是什么类型?
Q3. 判断:database: { url: $env.DATABASE_URL } 把敏感信息留在源码外,是好的实践。