【译】设计优雅的 Rust 库 API

本文探讨了如何设计优雅的Rust库API,包括一致的命名、文档测试、避免使用字符串类型、错误处理、公共类型别名、转换trait、惰性、易用性trait和建造者模式等技术。建议遵循Rust RFC的命名方案,使用文档测试提供示例代码,避免在API中使用字符串,而使用枚举或类型别名。同时,强调正确处理错误,利用类型系统防止逻辑错误,提供有意义的错误信息。最后,文章提供了案例学习和其他设计模式的参考。
摘要由CSDN通过智能技术生成

一篇讲述 Rust API 设计原则的经典老文,虽然老但仍然值得阅读。前几天有事情把它从旮旯里翻出来了,虽然是经典老文但我估计很多人都没有读过,最近闲着没事干脆用我的辣鸡英语水平翻译一下,也算为 Rust 中文社区做一点贡献。

原文见:https://deterministic.space/elegant-apis-in-rust.html

第一次在论坛发博客,不知道论坛的 markdown 支持怎么样,也不知道支不支持修改。如果阅读有问题的话请访问:https://www.aloxaf.com/2019/11/elegant_apis_in_rust/

设计优雅的 Rust 库 API

在选择一门编程语言时,是否拥有简洁易用的库也是一个重要的考量因素。这篇文章会教授你如何为你的 Rust 库编写优雅的 API。(不过文中的许多观点也适用于其他语言。)

你也可以观看我在 Rustfest 2017 上的演讲!

什么是优雅的 API

  • 方法名清晰易懂,以让调用了这个 API 的代码易于阅读。

  • 有规律、可猜测的方法名在使用 API 时也很有用,可以减少阅读文档的需求。

  • 每个 API 都有至少要有文档和一小段示例代码。

  • 用户几乎不需要编写样板代码(boilerplate code)来使用这个 API,因为

    • 它广泛接受各种输入类型(当然类型转换是显式的)

    • 并且也有足以应付大部分常用情况的一键 API

  • 充分利用类型来防止逻辑错误,但不会太妨碍使用。

  • 返回有意义的错误,并且在文档中注明会导致 panic 的情况。

技术

一致的命名

有一些 Rust RFC 描述了标准库的命名方案。你也应该遵循它们,以让用户能迅速上手使用你的库。

  • RFC 199 解释说应该使用 mutmove 或 ref 作为后缀,来根据参数的可变性区分方法。

  • RFC 344 定义了一些有意思的约定,比如:

    • 如何在方法名称中引用类型名称(如 &mut [T] 变成 mut_slice*mut T 变成 mut ptr),

    • 如何命名返回迭代器的方法,

    • getter 方法应该被命名为 field_name 而 setter 方法应该被命名为 set_field_name

    • 如何命名 trait:“优先选择(及物)动词、名词,然后是形容词;避免语法后缀(如 able)”,而且“如果这个 trait 只有一个主要方法,可以考虑用方法名称来命名 trait 本身”,

    • RFC 430 描述了一些通用的大小写约定(总结:CamelCase 用于类型级别,snake_case 用于变量级别)。

    • RFC 445 希望你为扩展 trait(extension trait)添加 Ext 后缀。

更多的方法名称约定

除了 RFC 199 和 RFC 344 (见上)规定的以外,还有一些其他的关于如何选择方法名称的约定,目前还没有在 RFC 中提及。这些约定大部分都在旧的 Rust 风格指南和 @llogiq 的文章 Rustic Bits 以及 clippy 的 wrong_self_convention 检测项中提到了。这里总结一下。

方法名称 参数 备注 举例
new 无 self,通常 >= 1 [^1] 构造器,另参见 Default Box::newstd::net::Ipv4Addr::new
with_... 无 self,>= 1 其他构造器 Vec::with_capacityregex::Regex::with_size_limit
from_... 1 参见转换 trait(conversion traits) String::from_utf8_lossy
as_... &self 无开销的转换,返回数据的一个视图(view) str::as_bytesuuid::Uuid::as_bytes
to_... &self 昂贵的转换 str::to_stringstd::path::Path::to_str
into_... self(消耗) 可能昂贵的转换,参见 转换 trait(conversion traits) std::fs::File::into_raw_fd
is_... &self(或无) 期望返回 bool slice::is_emptyResult::is_okstd::path::Path::is_file
has_... &self (或无) 期望返回 bool regex_syntax::Expr::has_bytes

文档测试

编写带有示例代码的文档可以展示 API 的用法而且还能获得自动测试——一石二鸟。详见第一版 TRPL(The Rust Programming Language)的文档一节。

/// 使用魔法操作数字
///
/// # 示例
///
/// ```rust
/// assert_eq!(min( 0, 14), 0);
/// assert_eq!(min( 0, -127), -127);
/// assert_eq!(min(42, 666), 42);
/// ```(由于 hexo markdown 渲染辣鸡,此处加点文字避免被渲染为单独代码块)
fn min(lhs: i32, rhs: i32) -> i32 {
if lhs < rhs { lhs } else { rhs }
}

你还可以使用 #![deny(missing_docs)] 来强制保证每个公开 API 都有文档。你可能也会对我的这篇提

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值