各関数は100行以内に収める

Contents

Keep each function to 100 lines or fewer (logical lines; wrapped lines count as one). (各関数は100行以内に収める(論理行;折り返された行は1行とカウント))

解説

長い関数は、複数の責任を持っている可能性が高く、理解とテストが困難です。100行を超える関数は、処理を小さな関数に分割することで、可読性と再利用性が向上します。短い関数は、単一の責任を持ち、名前から目的が明確になります。論理行でカウントするため、コメントや空行、折り返しは複数行とはみなされません。適切な粒度の関数は、バグの発見と修正を容易にします。

具体例

// 悪い例(長すぎる関数 - 200行以上)
func ProcessOrder(order Order) error {
    // バリデーション(30行)
    if order.ID == "" {
        return errors.New("order ID is required")
    }
    if order.CustomerID == "" {
        return errors.New("customer ID is required")
    }
    // ... さらに20項目のバリデーション

    // 在庫チェック(40行)
    for _, item := range order.Items {
        stock, err := db.GetStock(item.ProductID)
        if err != nil {
            return err
        }
        // ... 複雑な在庫ロジック
    }

    // 価格計算(40行)
    subtotal := 0.0
    for _, item := range order.Items {
        subtotal += item.Price * float64(item.Quantity)
    }
    // ... 割引、税金、送料の計算

    // 決済処理(40行)
    // ... 決済ゲートウェイとの通信

    // メール送信(30行)
    // ... メール作成と送信

    // データベース保存(20行)
    // ... 複数テーブルへの保存

    return nil
}

// 良い例(適切に分割された関数)
func ProcessOrder(order Order) error {
    if err := validateOrder(order); err != nil {
        return fmt.Errorf("validation failed: %w", err)
    }

    if err := checkInventory(order.Items); err != nil {
        return fmt.Errorf("inventory check failed: %w", err)
    }

    total, err := calculateOrderTotal(order)
    if err != nil {
        return fmt.Errorf("calculation failed: %w", err)
    }

    if err := processPayment(order.CustomerID, total); err != nil {
        return fmt.Errorf("payment failed: %w", err)
    }

    if err := saveOrder(order); err != nil {
        return fmt.Errorf("save failed: %w", err)
    }

    if err := sendConfirmationEmail(order); err != nil {
        log.Printf("email failed: %v", err)
        // メール失敗は注文処理を失敗させない
    }

    return nil
}

// 各関数は単一の責任を持ち、100行以内
func validateOrder(order Order) error {
    if order.ID == "" {
        return errors.New("order ID is required")
    }
    if order.CustomerID == "" {
        return errors.New("customer ID is required")
    }
    // ... その他のバリデーション
    return nil
}

func checkInventory(items []Item) error {
    for _, item := range items {
        if err := verifyStockAvailability(item); err != nil {
            return err
        }
    }
    return nil
}

func calculateOrderTotal(order Order) (float64, error) {
    subtotal := calculateSubtotal(order.Items)
    discount := calculateDiscount(order, subtotal)
    tax := calculateTax(subtotal - discount)
    shipping := calculateShipping(order)
    return subtotal - discount + tax + shipping, nil
}

参考リンク

Show Text to Share
各関数は100行以内に収める
https://www.tricrow.com/core/coding-standard/max-100-lines.html
この記事を書いた人
T.Nakamura
T.Nakamura
AIが大好きなクラウドエンジニア。IT業界歴10年以上。標準化と効率化を追求している。技術ネタを発信中。フォローお気軽にどうぞ!フォローはこちら

カテゴリ

タグ