軟體工程筆記 | 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)

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

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

總結

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

參考資料

對我來說 人生就是一個遊戲 活得開心,活得漂亮,活得成功,活得有意義 都是這場遊戲的一個個任務 我想要把這個遊戲打通關 在這裡我會分享一些我自己的經驗 把遊戲打通關的一些技巧 打通關的過程 和我自己發現的小 bug,或捷徑 遇到的喜怒哀樂 遇到的困難 遇到的挫折 歡迎大家一起來摸透和想受 這場人生遊戲
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
本文靈感來自:How to Document Your Code Like a Pro 以下範例程式均為 Python 推薦插件:better comment 前言 程式碼的有效文件化是編程最重要的部分之一 Python 提升可讀性有以下方式: 註釋 類型提示 文檔字串 這些實踐可以提高程式碼的可讀
在程式設計中,我們通常會遇到一個問題: 何時應該使用具有方法的類別,何時應該在模組中使用函式? 如果選擇不當,你的程式碼可能比需要的更複雜,這使得維護更困難 首先,我們需要更好地理解函式和類別的差異。 函式接收輸入參數,然後進行一些操作,並返回結果。你可以將這個結果傳遞給其他函式。在像Haskell
本文靈感來自:How to Document Your Code Like a Pro 以下範例程式均為 Python 推薦插件:better comment 前言 程式碼的有效文件化是編程最重要的部分之一 Python 提升可讀性有以下方式: 註釋 類型提示 文檔字串 這些實踐可以提高程式碼的可讀
在程式設計中,我們通常會遇到一個問題: 何時應該使用具有方法的類別,何時應該在模組中使用函式? 如果選擇不當,你的程式碼可能比需要的更複雜,這使得維護更困難 首先,我們需要更好地理解函式和類別的差異。 函式接收輸入參數,然後進行一些操作,並返回結果。你可以將這個結果傳遞給其他函式。在像Haskell
你可能也想看
Google News 追蹤
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
我想要一天分享一點「LLM從底層堆疊的技術」,並且每篇文章長度控制在三分鐘以內,讓大家不會壓力太大,但是又能夠每天成長一點。 回顧我們在 AI說書 - 從0開始 - 110,介紹了 BLEU 使用方法與公式,現在我們再跑一個例子: #Example 3 reference = [['the
Thumbnail
Pair programming,譯為「結對編程」,是敏捷軟體開發的一種方式,由兩位軟體工程師同時開發一個程式,簡單來說,原本一個人可以完成的工作,找了兩個人來做,人力成本直接變成兩倍! |本篇報導同步刊登於 科技島 在大量運用 AI 人工智慧的時代,為何外商軟體公司仍積極運用結對編程進行
Thumbnail
default methods 似乎也引起不小的討論,因為 default methods 加上可以實作多個介面,已經有點像 C++ 的多重繼承了,只差在沒辦法繼承成員變數而已,是好是壞就看怎麼使用了。我個人覺得還蠻方便的
Thumbnail
今天來介紹python的函式 函式在python中是非常重要的一環,因為到了後期,程式會越來越複雜。 而函式可以想成是容易管理的小程式,當我們需要使用時,只需呼叫即可。
對於程序式編程來說,程式是由一系列的指令組成,例如計算數值、印出訊息、修改變數、呼叫子程序、配置變數的記憶體空間等。定義函式是為了讓一些程序可以重複利用,因此稱為子程序,其中參數為子程序中特別的變數,讓我們能夠透過它們控制子程序的行為。函式的回傳值只是一種方便將結果帶回來的方法,但一般只能回傳一個值
Thumbnail
先前我們談論到靜態方法就像是定義工具箱一樣,那麼抽象方法就像是共用表格的概念,例如註冊帳號時會填寫的一些基本資料,就有包含制式的表格,裡面有需填寫的欄位,例如姓名,性別等。
Thumbnail
先前學到自定函式的使用方法,那如果在一個很龐大的程式架構中發散了一推自定函式,有沒有辦法可以整理一下,讓程式結構整齊又簡潔呢? 可以使用裝飾器staticmethod 定義靜態方法,全部整理到一個類別去,想像成是一個工具箱的概念,工具箱就是類別,靜態方法就像是裡面的工具一樣。
Thumbnail
本文介紹了串列運算式的應用,以及與Lambda匿名函式方法的比較,並提供了程式範例。串列運算式提供了一種簡潔的語法,用於創建、轉換和過濾列表。lambda函式用於創建匿名函式,通常用於簡單的操作。建議在比較複雜的情況下使用一般for迴圈加if來表示。
Thumbnail
lambda 函式,又稱為“匿名函式”,是一種在 Python 中快速定義單行函式的方法,與 def 定義函式不同,lambda 函式不需要命名。本文將介紹 lambda函式的基礎語法,以及實際應用範例演示。
Thumbnail
本文將介紹自定函式及應用,利用程式範例解釋為什麼要用到自定函式 自定函式好處當然就是,讓你的程式碼看起來比較簡潔,在重複使用到的程式碼區塊,可以包裝成函式,讓你重複使用它。
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
我想要一天分享一點「LLM從底層堆疊的技術」,並且每篇文章長度控制在三分鐘以內,讓大家不會壓力太大,但是又能夠每天成長一點。 回顧我們在 AI說書 - 從0開始 - 110,介紹了 BLEU 使用方法與公式,現在我們再跑一個例子: #Example 3 reference = [['the
Thumbnail
Pair programming,譯為「結對編程」,是敏捷軟體開發的一種方式,由兩位軟體工程師同時開發一個程式,簡單來說,原本一個人可以完成的工作,找了兩個人來做,人力成本直接變成兩倍! |本篇報導同步刊登於 科技島 在大量運用 AI 人工智慧的時代,為何外商軟體公司仍積極運用結對編程進行
Thumbnail
default methods 似乎也引起不小的討論,因為 default methods 加上可以實作多個介面,已經有點像 C++ 的多重繼承了,只差在沒辦法繼承成員變數而已,是好是壞就看怎麼使用了。我個人覺得還蠻方便的
Thumbnail
今天來介紹python的函式 函式在python中是非常重要的一環,因為到了後期,程式會越來越複雜。 而函式可以想成是容易管理的小程式,當我們需要使用時,只需呼叫即可。
對於程序式編程來說,程式是由一系列的指令組成,例如計算數值、印出訊息、修改變數、呼叫子程序、配置變數的記憶體空間等。定義函式是為了讓一些程序可以重複利用,因此稱為子程序,其中參數為子程序中特別的變數,讓我們能夠透過它們控制子程序的行為。函式的回傳值只是一種方便將結果帶回來的方法,但一般只能回傳一個值
Thumbnail
先前我們談論到靜態方法就像是定義工具箱一樣,那麼抽象方法就像是共用表格的概念,例如註冊帳號時會填寫的一些基本資料,就有包含制式的表格,裡面有需填寫的欄位,例如姓名,性別等。
Thumbnail
先前學到自定函式的使用方法,那如果在一個很龐大的程式架構中發散了一推自定函式,有沒有辦法可以整理一下,讓程式結構整齊又簡潔呢? 可以使用裝飾器staticmethod 定義靜態方法,全部整理到一個類別去,想像成是一個工具箱的概念,工具箱就是類別,靜態方法就像是裡面的工具一樣。
Thumbnail
本文介紹了串列運算式的應用,以及與Lambda匿名函式方法的比較,並提供了程式範例。串列運算式提供了一種簡潔的語法,用於創建、轉換和過濾列表。lambda函式用於創建匿名函式,通常用於簡單的操作。建議在比較複雜的情況下使用一般for迴圈加if來表示。
Thumbnail
lambda 函式,又稱為“匿名函式”,是一種在 Python 中快速定義單行函式的方法,與 def 定義函式不同,lambda 函式不需要命名。本文將介紹 lambda函式的基礎語法,以及實際應用範例演示。
Thumbnail
本文將介紹自定函式及應用,利用程式範例解釋為什麼要用到自定函式 自定函式好處當然就是,讓你的程式碼看起來比較簡潔,在重複使用到的程式碼區塊,可以包裝成函式,讓你重複使用它。