为什么参数设计很重要
Ruby API 的可读性很大程度来自参数设计。参数规则不清晰,代码会出现:
- 调用方式混乱。
- 升级版本后不兼容。
- 调试困难。
本篇聚焦 Ruby 3 常见参数模式和最佳实践。
1. 位置参数(Positional Arguments)
def add(a, b)
a + b
end
add(1, 2) # => 3
最直接,但当参数变多时可读性下降。
2. 默认参数
def connect(host, port = 5432)
"#{host}:#{port}"
end
connect("db.local") # => "db.local:5432"
适合稳定默认值,减少调用方样板代码。
3. 可变参数 *args
*args 把多余位置参数收集成数组。
def sum(*args)
args.sum
end
sum(1, 2, 3) # => 6
常用于包装器、事件回调、DSL。
4. 关键字参数(Keyword Arguments)
关键字参数可读性高,推荐用于配置型参数。
def create_user(name:, email:, admin: false)
{ name: name, email: email, admin: admin }
end
create_user(name: "Lin", email: "[email protected]")
优势:
- 调用语义清晰。
- 参数顺序不敏感。
- 更适合长期维护 API。
5. 双星号 **kwargs
用于收集额外关键字参数。
def log_event(event:, **meta)
{ event: event, meta: meta }
end
log_event(event: "login", user_id: 10, ip: "127.0.0.1")
适合扩展字段较多的场景。
6. 参数解构与转发
解构
def point((x, y))
x * y
end
point([3, 4]) # => 12
转发(Ruby 2.7+)
def wrapper(...)
target(...)
end
代理方法和中间件非常常见。
7. Hash 参数与关键字参数的区别
旧代码常把最后一个 Hash 当作选项参数。Ruby 3 中关键字参数和普通 Hash 分离更严格。
def f(opts)
opts
end
f(a: 1) # Hash
def g(a:)
a
end
g(a: 1) # keyword
升级 Ruby 2 到 Ruby 3 时,这是常见兼容问题来源。
8. Symbol Key 与 String Key
h1 = { name: "bill" } # symbol key
h2 = { "name" => "bill" } # string key
它们不是同一个 key。
调用方式:
login(name: "bill")使用 symbol key。login("name": "bill")语法上也是 symbol key(:"name")。
这点容易误解。
9. 常见坑位
- 可变参数和关键字参数顺序写错。
- 包装方法忘记转发关键字参数。
- 在公开 API 中混用过多参数风格。
- 使用模糊的
options = {}导致调用歧义。
10. 参数设计最佳实践
- 核心输入用位置参数。
- 可选配置用关键字参数。
- 对外 API 优先显式关键字。
- 包装器方法使用
...保持透传一致。 - 为复杂参数写边界测试。
实战示例:更可维护的 API
def send_email(to:, subject:, body:, retry_count: 3, timeout: 5)
# send logic
end
send_email(
to: "[email protected]",
subject: "Build Status",
body: "All green",
timeout: 10
)
调用意图清晰,后续扩展也更安全。
小结
Ruby 参数机制灵活,但灵活也意味着需要团队约束。把位置参数用于必要输入,把关键字参数用于配置语义,再配合 *args/**kwargs 和参数转发,你可以设计出可读、稳定、易扩展的 Ruby API。
Comments