副作用よりも結果を返す純粋関数を優先する

Contents

Prefer pure functions that return results rather than causing side effects. Use pointers only when necessary (e.g., large slices or shared transactions). (副作用を起こすのではなく、結果を返す純粋関数を優先する。ポインタは必要な場合のみ使用する(例:大きなスライスや共有トランザクション))

解説

純粋関数は、同じ入力に対して常に同じ出力を返し、外部状態を変更しません。これにより、関数の振る舞いが予測可能になり、テストが容易になります。副作用を持つ関数は、呼び出し順序や状態に依存するため、デバッグが困難です。ポインタを多用すると、意図しない状態変更が発生しやすくなるため、必要な場合のみ使用すべきです。純粋関数は並行処理でも安全です。

具体例

// 悪い例(副作用を持つ関数)
var globalCounter int

func ProcessItem(item *Item) {
    item.Price *= 1.1  // 引数を直接変更(副作用)
    globalCounter++    // グローバル状態を変更(副作用)
}

func CalculateTotal(items []*Item) float64 {
    total := 0.0
    for _, item := range items {
        ProcessItem(item)  // 元のデータが変更される
        total += item.Price
    }
    return total
}

// 良い例(純粋関数)
func ApplyTax(price float64) float64 {
    return price * 1.1  // 新しい値を返す
}

func CalculateTaxedPrice(item Item) Item {
    // 元のitemを変更せず、新しいItemを返す
    return Item{
        Name:  item.Name,
        Price: ApplyTax(item.Price),
    }
}

func CalculateTotal(items []Item) float64 {
    total := 0.0
    for _, item := range items {
        taxedPrice := ApplyTax(item.Price)
        total += taxedPrice
        // 元のitemsは変更されない
    }
    return total
}

// ポインタが必要な例(大きなデータ構造の効率的な処理)
type LargeDataSet struct {
    Data []byte // 数MBのデータ
}

func ProcessLargeData(data *LargeDataSet) error {
    // 大きなデータのコピーを避けるためポインタを使用
    return processBatch(data.Data)
}

// トランザクション内での共有が必要な例
func UpdateWithTransaction(tx *sql.Tx, user User) error {
    // トランザクションは共有する必要がある
    return tx.Exec("UPDATE users SET name = ?", user.Name)
}

参考リンク

Show Text to Share
副作用よりも結果を返す純粋関数を優先する
https://www.tricrow.com/core/coding-standard/pure-functions.html
この記事を書いた人
T.Nakamura
T.Nakamura
AIが大好きなクラウドエンジニア。IT業界歴10年以上。標準化と効率化を追求している。技術ネタを発信中。フォローお気軽にどうぞ!フォローはこちら

カテゴリ

タグ