只提供值且無可見副作用的函式,非常寶貴, 這也是命令查詢分離原則(CQS, Command-Query Separation)的精神。

Separate Query from Modifier

sequenceDiagram
    participant Client
    participant Service

    rect rgb(255, 230, 230)
        Note over Client,Service: ❌ 混合查詢與修改
        Client->>Service: sendAndConfirmEmail()
        Service-->>Client: 回傳已發送清單 + 執行發送
    end

    rect rgb(230, 255, 230)
        Note over Client,Service: ✅ 分離查詢與修改
        Client->>Service: sendEmail() [Command]
        Service-->>Client: void
        Client->>Service: getEmailStatus() [Query]
        Service-->>Client: 回傳狀態(無副作用)
    end

強調「可見」,是因像快取這類雖會改變物件狀態,仍讓查詢都回傳相同結果就是被允許的。

# Before
def send_and_confirm_email(emails, message):
    sent_emails = []
    for email in emails:
        print(f"Sending email to {email}")
        sent_emails.append(email)
    return sent_emails

emails = ["john@example.com", "jane@example.com"]
sent_emails = send_and_confirm_email(emails, "Hello!")

# After
def send_email(emails, message):
    for email in emails:
        print(f"Sending email to {email}")

def confirm_sent_emails(emails):
    return emails

emails = ["john@example.com", "jane@example.com"]
send_email(emails, "Hello!")
sent_emails = confirm_sent_emails(emails)