Rust 編程範式最佳實踐
面向對象的 Rust
與前面討論的函數式和命令式示例相反,讓我們引入一個新的結構體 FileFilter,它封裝了過濾文件和文件迭代的邏輯。
pub struct FileFilter {
predicates: Vec<Box<Predicate>>,
start: Option<PathBuf>,
stack: Vec<fs::ReadDir>,
}
每個 FileFilter 對象都攜帶其狀態:用於過濾的謂詞集合、起始路徑和用於迭代的目錄棧。
Predicate 是這樣定義的:
type Predicate = dyn Fn(&Path) -> bool;
你可能會驚訝地發現這裏有一個 dyn。在 Rust 中,沒有兩個閉包具有相同的類型,即使它們完全相同!
爲了在 Vec 集合中適應這一點,我們使用帶有動態分派的 trait 對象。通過 “裝箱” 這些閉包,我們創建了一個 Box 類型 (本質上是 Box<dyn Fn(&Path) -> bool>),這允許我們在同一個 Vec 中存儲不同的 Predicate 閉包,儘管它們的類型不同。
在函數式編程中,我們利用迭代器和閉包的強大功能來過濾文件。在命令式風格中,我們直接使用循環和條件來操作向量。在面向對象風格中,結構體 FileFilter 抽象掉了這些細節。
看一下 add_filter 方法:
pub fn add_filter(mut self, predicate: impl Fn(&Path) -> bool + 'static) -> Self {
self.predicates.push(Box::new(predicate));
self
}
這允許我們通過鏈接調用輕鬆地添加多個過濾器:
let filter = FileFilter::new()
.add_filter(|path| {
// 檢查路徑是否以“foo”開頭
path.file_name()
.and_then(OsStr::to_str)
.map(|name| name.starts_with("foo"))
.unwrap_or(false)
})
.add_filter(|path| path.extension() == Some(OsStr::new("xml")));
真正展示 Rust 中面向對象方法的是 FileFilter 的 Iterator trait 的實現:
impl Iterator for FileFilter {
type Item = Result<PathBuf>;
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
這樣,FileFilter 就成爲了一個構建塊,它與 Rust 強大的迭代器生態系統完美地集成在一起,可以像其他任何迭代器一樣在所有相同的地方使用,這種設計允許將複雜的迭代邏輯封裝在對象中。
FileFilter 示例說明了 Rust 中的 OOP 如何進行可靠的封裝和模塊化,我們將內容 (謂詞) 與方式 (迭代和過濾邏輯) 分開。trait 系統輕鬆地將自定義迭代器與生態系統的其餘部分集成在一起,使用這些工具可以使代碼更易於組合和重用。
編程範式最佳實踐
在 Rust 中混合不同的編程風格不僅是可能的,而且是鼓勵的!從 Rust 對其語言設計的主要理念中也可以看出這一點。C、Haskell、OCaml 和 Erlang 等各種各樣的影響塑造了 Rust 的設計。
一開始,Rust 在本質上更偏向於函數式,但後來它演變成了一種更加平衡的語言,支持各種風格,問題是如何在不同的編程範例之間劃清界限。
以下是一些最佳實踐:
-
利用函數式風格進行數據轉換,尤其是在函數和閉包等較小的範圍內,map、filter 或縮減等函數式方法可以使代碼既簡潔又清晰。
-
對於組織較大的應用程序,請考慮面向對象的風格。使用結構體或枚舉可以封裝相關的數據和函數,提供一個清晰的結構。
-
使用命令式風格進行粒度控制,在接近硬件的場景中,或者需要明確的分步執行時,命令式風格通常是必要的。它允許對操作進行精確控制,特別是對可變數據。這種風格在性能關鍵部分或與外部系統接口時特別有用,因爲在這些地方需要精確的順序。但是,始終要權衡其性能收益與潛在的可讀性權衡。如果可能,將命令式代碼封裝在有限的範圍內。
-
優先考慮可讀性和可維護性,無論你選擇哪種編程範式,都要始終編寫簡單且易於維護的代碼。這不僅有利於未來的自己,而且也有利於在同一代碼庫上工作的同事。
-
避免過早優化,不要過早地以可讀性爲代價來優化性能,真正的瓶頸可能在其他地方。先測量,再優化。優雅的解決方案可以轉化爲快速的解決方案,但反過來並不總是正確的。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/q4gZ4emk6y0hqNXnwTW2ZQ