軟體工程筆記 | method chaining / fluent interface 讓你的代碼更容易理解和使用

更新於 發佈於 閱讀時間約 8 分鐘

某次請 GPT 幫我把原本要作為訊息使用的代碼封裝起來,它也完美完成
但意外的他給了我一個從沒看過的寫法
簡化後像是如下

from typing import Self

class MessageBuilder:
def __init__(self):
self.message = ''

def add_line(self, line: str) -> Self:
self.message += line + '\n\n'

# why return self ??
return self

def build(self) -> str:
return self.message


我的疑問是為什麼明明我更改物件狀態,卻還是要回傳物件本身(self)呢?
研究後才知道是為了實現 fluent interface(流暢接口) 所以使用 method chaining (方法鏈) 的形式來設計

這種模式可以使代碼更具可讀性,並使其看起來更像自然語言。

舉個例子

例如,以下是使用 `add_line` 的典型用法:

message_builder = MessageBuilder()
(
message_builder
.add_line("line 1")
.add_line("line 2")
.add_line("line 3")
)


但如果 `add_line` 不返回 `self`,那麼每次調用 `add_line` 方法都需要單獨的一行代碼:

message_builder = MessageBuilder()
message_builder.add_line("line 1")
message_builder.add_line("line 2")
message_builder.add_line("line 3")


雖然兩者做相同的是,但是讀起來的流暢程度和優雅程度就有點差別了
這就是使用 fluent interface (返回 self )的好處。

補充

方法鏈(Method Chaining)

方法鏈接是一個編程技巧,它允許對同一個對象進行多個操作調用,而不需要每次調用都引用該對象。通過方法鏈接,可以在同一條語句中鏈接多個方法調用。通常,每個方法調用返回對象的參考,使得可以繼續調用該對象的其他方法。

這個技巧通常讓程式碼變得更簡潔、更易讀。

方法鏈的好處:
1. 讓調用過程更接近自然語言。
2. 把原本參數列表複雜的方法化作多個參數列表簡單的方法來使用。
3. 減少不必要的代碼量。

這個三點都是有益於開發的,所以方法鏈的存在很有意義。

以上第二點再舉個更具體的例子:把原本參數列表複雜的方法化作多個參數列表簡單的方法來使用

沒有使用方法鏈

假設你有一個 Computer 類,你可以用一個方法來設置所有屬性:

class Computer:
def __init__(self, processor, memory, storage, graphics):
self.processor = processor
self.memory = memory
self.storage = storage
self.graphics = graphics

def specs(self):
return f"Processor: {self.processor}, Memory: {self.memory}, Storage: {self.storage}, Graphics: {self.graphics}"

my_computer = Computer('Intel i7', '16GB', '512GB SSD', 'NVIDIA GTX 1080')
print(my_computer.specs())


這個方法可能造成代碼難以閱讀和維護,特別是當參數變得更多或更複雜時。

使用方法鏈

你可以使用方法鏈,將每個設置拆分為獨立的方法:

class Computer:
def __init__(self):
self.processor = None
self.memory = None
self.storage = None
self.graphics = None

def set_processor(self, processor):
self.processor = processor
return self

def set_memory(self, memory):
self.memory = memory
return self

def set_storage(self, storage):
self.storage = storage
return self

def set_graphics(self, graphics):
self.graphics = graphics
return self

def specs(self):
return f"Processor: {self.processor}, Memory: {self.memory}, Storage: {self.storage}, Graphics: {self.graphics}"


my_computer = (
Computer()
.set_processor('Intel i7')
.set_memory('16GB')
.set_storage('512GB SSD')
.set_graphics('NVIDIA GTX 1080')
)
print(my_computer.specs())


Python 有可以指定參數的寫法,所以我覺得還好,但是當我用 Java 又要再 function 中傳入多個參數時候就有點痛苦了
不過同時也造成複雜度增加,我覺得還是要看情境使用,並不適合用在每個情況
如果你的 function 需要傳入那麼多參數,其實可以把他包成一個物件,或是看看是不是真的需要


限制:

方法鏈的一個限制是,只能用在不需要返回其他值的方法上,因為你需要返回self 對象。即使Python支持用一個return語句返回多個值,也可能無法解決這個問題。


流暢接口(Fluent Interface)

流暢接口是一種編程接口設計方法,使得對象的使用更符合自然語言的結構,提高了程式碼的可讀性和可維護性。流暢接口通常使用方法鏈接來實現。

流暢接口的目標是讓程式碼的讀者能夠更容易理解程式的功能。流暢接口通常用在建構器模式、查詢建立或任何你想以更描述性、自然的方式表示的地方。

總結

方法鏈接和流暢接口在許多現代編程語言和框架中都有使用。這兩個概念有時互相重疊,因為流暢接口通常使用方法鏈接來實現。使用這些技巧可以提高程式碼的可讀性和維護性,使得編碼更符合人類語言的結構。這對於在專案中協同工作的團隊尤為重要,因為它可以讓每個人更容易理解和使用代碼。

參考資料

留言
avatar-img
留言分享你的想法!
avatar-img
我人生遊戲的通關討論區
35會員
97內容數
對我來說 人生就是一個遊戲 活得開心,活得漂亮,活得成功,活得有意義 都是這場遊戲的一個個任務 我想要把這個遊戲打通關 在這裡我會分享一些我自己的經驗 把遊戲打通關的一些技巧 打通關的過程 和我自己發現的小 bug,或捷徑 遇到的喜怒哀樂 遇到的困難 遇到的挫折 歡迎大家一起來摸透和想受 這場人生遊戲
2023/08/05
在Python的typing模組中,NewType用來創建新的類型,其實是一個現有類型的變體。這對於型別檢查(Type Checking)非常有用,能夠幫助我們更清楚地理解我們的代碼和預期的行為。
Thumbnail
2023/08/05
在Python的typing模組中,NewType用來創建新的類型,其實是一個現有類型的變體。這對於型別檢查(Type Checking)非常有用,能夠幫助我們更清楚地理解我們的代碼和預期的行為。
Thumbnail
2023/06/15
本文靈感來自:How to Document Your Code Like a Pro 以下範例程式均為 Python 推薦插件:better comment 前言 程式碼的有效文件化是編程最重要的部分之一 Python 提升可讀性有以下方式: 註釋 類型提示 文檔字串 這些實踐可以提高程式碼的可讀
Thumbnail
2023/06/15
本文靈感來自:How to Document Your Code Like a Pro 以下範例程式均為 Python 推薦插件:better comment 前言 程式碼的有效文件化是編程最重要的部分之一 Python 提升可讀性有以下方式: 註釋 類型提示 文檔字串 這些實踐可以提高程式碼的可讀
Thumbnail
2023/06/11
在程式設計中,我們通常會遇到一個問題: 何時應該使用具有方法的類別,何時應該在模組中使用函式? 如果選擇不當,你的程式碼可能比需要的更複雜,這使得維護更困難 首先,我們需要更好地理解函式和類別的差異。 函式接收輸入參數,然後進行一些操作,並返回結果。你可以將這個結果傳遞給其他函式。在像Haskell
Thumbnail
2023/06/11
在程式設計中,我們通常會遇到一個問題: 何時應該使用具有方法的類別,何時應該在模組中使用函式? 如果選擇不當,你的程式碼可能比需要的更複雜,這使得維護更困難 首先,我們需要更好地理解函式和類別的差異。 函式接收輸入參數,然後進行一些操作,並返回結果。你可以將這個結果傳遞給其他函式。在像Haskell
Thumbnail
看更多
你可能也想看
Thumbnail
透過蝦皮分潤計畫,輕鬆賺取零用金!本文分享5-6月實測心得,包含數據流程、實際收入、平臺優點及注意事項,並推薦高分潤商品,教你如何運用空閒時間創造被動收入。
Thumbnail
透過蝦皮分潤計畫,輕鬆賺取零用金!本文分享5-6月實測心得,包含數據流程、實際收入、平臺優點及注意事項,並推薦高分潤商品,教你如何運用空閒時間創造被動收入。
Thumbnail
單身的人有些會養寵物,而我養植物。畢竟寵物離世會傷心,植物沒養好再接再厲就好了~(笑)
Thumbnail
單身的人有些會養寵物,而我養植物。畢竟寵物離世會傷心,植物沒養好再接再厲就好了~(笑)
Thumbnail
不知你有沒有過這種經驗?衛生紙只剩最後一包、洗衣精倒不出來,或電池突然沒電。這次一次補貨,從電池、衛生紙到洗衣精,還順便分享使用心得。更棒的是,搭配蝦皮分潤計畫,愛用品不僅自己用得安心,分享給朋友還能賺回饋。立即使用推薦碼 X5Q344E,輕鬆上手,隨時隨地賺取分潤!
Thumbnail
不知你有沒有過這種經驗?衛生紙只剩最後一包、洗衣精倒不出來,或電池突然沒電。這次一次補貨,從電池、衛生紙到洗衣精,還順便分享使用心得。更棒的是,搭配蝦皮分潤計畫,愛用品不僅自己用得安心,分享給朋友還能賺回饋。立即使用推薦碼 X5Q344E,輕鬆上手,隨時隨地賺取分潤!
Thumbnail
身為一個典型的社畜,上班時間被會議、進度、KPI 塞得滿滿,下班後只想要找一個能夠安靜喘口氣的小角落。對我來說,畫畫就是那個屬於自己的小樹洞。無論是胡亂塗鴉,還是慢慢描繪喜歡的插畫人物,那個專注在筆觸和色彩的過程,就像在幫心靈按摩一樣,讓緊繃的神經慢慢鬆開。
Thumbnail
身為一個典型的社畜,上班時間被會議、進度、KPI 塞得滿滿,下班後只想要找一個能夠安靜喘口氣的小角落。對我來說,畫畫就是那個屬於自己的小樹洞。無論是胡亂塗鴉,還是慢慢描繪喜歡的插畫人物,那個專注在筆觸和色彩的過程,就像在幫心靈按摩一樣,讓緊繃的神經慢慢鬆開。
Thumbnail
本文將介紹自定函式及應用,利用程式範例解釋為什麼要用到自定函式 自定函式好處當然就是,讓你的程式碼看起來比較簡潔,在重複使用到的程式碼區塊,可以包裝成函式,讓你重複使用它。
Thumbnail
本文將介紹自定函式及應用,利用程式範例解釋為什麼要用到自定函式 自定函式好處當然就是,讓你的程式碼看起來比較簡潔,在重複使用到的程式碼區塊,可以包裝成函式,讓你重複使用它。
Thumbnail
在 Kotlin 程式語言中,使用關鍵字「interface」來定義介面。在介面中,每個函數預設都是開放的,不需要額外使用「open」關鍵字來宣告。但是,如果你要實作介面中的屬性與函數,就需要使用「override」關鍵字。 介面只定義了方法的名稱、參數和返回值,沒有方法的具體實現。
Thumbnail
在 Kotlin 程式語言中,使用關鍵字「interface」來定義介面。在介面中,每個函數預設都是開放的,不需要額外使用「open」關鍵字來宣告。但是,如果你要實作介面中的屬性與函數,就需要使用「override」關鍵字。 介面只定義了方法的名稱、參數和返回值,沒有方法的具體實現。
Thumbnail
嗨!今天我們來深入探討鏈式方法模式,也就是讓你可以一路連續調用方法,看起來好像在鏈接它們似的。那麼,讓我們馬上進入主題吧!
Thumbnail
嗨!今天我們來深入探討鏈式方法模式,也就是讓你可以一路連續調用方法,看起來好像在鏈接它們似的。那麼,讓我們馬上進入主題吧!
Thumbnail
在許多複雜的程式設計問題中,如何將抽象與其具體實現分離開來,往往是一個重要的挑戰。橋接模式正是為了解決這樣的問題而生。透過橋接模式 (Bridge Pattern),不僅可以確保抽象和實現在結構上分離,還能提供一套彈性的機制來適應變化。
Thumbnail
在許多複雜的程式設計問題中,如何將抽象與其具體實現分離開來,往往是一個重要的挑戰。橋接模式正是為了解決這樣的問題而生。透過橋接模式 (Bridge Pattern),不僅可以確保抽象和實現在結構上分離,還能提供一套彈性的機制來適應變化。
Thumbnail
方法鏈接和流暢接口在許多現代編程語言和框架中都有使用。這兩個概念有時互相重疊,因為流暢接口通常使用方法鏈接來實現。使用這些技巧可以提高程式碼的可讀性和維護性,使得編碼更符合人類語言的結構。這對於在專案中協同工作的團隊尤為重要,因為它可以讓每個人更容易理解和使用代碼。
Thumbnail
方法鏈接和流暢接口在許多現代編程語言和框架中都有使用。這兩個概念有時互相重疊,因為流暢接口通常使用方法鏈接來實現。使用這些技巧可以提高程式碼的可讀性和維護性,使得編碼更符合人類語言的結構。這對於在專案中協同工作的團隊尤為重要,因為它可以讓每個人更容易理解和使用代碼。
Thumbnail
本文靈感來自:How to Document Your Code Like a Pro 以下範例程式均為 Python 推薦插件:better comment 前言 程式碼的有效文件化是編程最重要的部分之一 Python 提升可讀性有以下方式: 註釋 類型提示 文檔字串 這些實踐可以提高程式碼的可讀
Thumbnail
本文靈感來自:How to Document Your Code Like a Pro 以下範例程式均為 Python 推薦插件:better comment 前言 程式碼的有效文件化是編程最重要的部分之一 Python 提升可讀性有以下方式: 註釋 類型提示 文檔字串 這些實踐可以提高程式碼的可讀
Thumbnail
C# 介面 ( C# Interface ) – (C#教學) – 介面就是類別的接口, 就好像在電插一樣, 不同的電器有同一類與電力的接口. 要編程就像一個布局, 當引用一個class時, 會引用不同的method, property. 如果method的class可以轉換, 就大大簡化了編程.
Thumbnail
C# 介面 ( C# Interface ) – (C#教學) – 介面就是類別的接口, 就好像在電插一樣, 不同的電器有同一類與電力的接口. 要編程就像一個布局, 當引用一個class時, 會引用不同的method, property. 如果method的class可以轉換, 就大大簡化了編程.
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News