0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【概念理解】ファクトリ:ソフトウェア開発における「工場」

Last updated at Posted at 2025-03-27

1. ファクトリ関数=ソフトウェアの工場

ファクトリ関数はまさにプログラミング世界の「工場」です。その特徴を現実の工場と比較しながら解説します。

工場の特徴と対応関係

現実の工場 ファクトリ関数
原材料を受け取る パラメータを受け取る
製造工程がある オブジェクト生成ロジック
品質検査を行う バリデーション処理
完成品を出荷 オブジェクトを返却
生産ラインを隠蔽 実装詳細をカプセル化

2. ファクトリ関数の3大機能

① 生産機能(オブジェクト生成)

// 自動車工場
func CreateCar(maker string, model string) *Car {
    return &Car{
        Maker: maker,
        Model: model,
    }
}
  • 原材料(パラメータ)から製品(オブジェクト)を生産

② 加工機能(データ変換)

// 車体ナンバー加工付き工場
func CreateCarWithSerial(maker string) (*Car, error) {
    serial, err := generateSerial() // 加工工程
    if err != nil {
        return nil, err
    }
    
    return &Car{
        Maker:  maker,
        Serial: serial, // 加工済みデータ
    }, nil
}

③ 品質管理(バリデーション)

// 品質検査付き工場
func CreateValidCar(maker string, year int) (*Car, error) {
    if year < 1900 {
        return nil, errors.New("製造年が古すぎます")
    }
    if len(maker) == 0 {
        return nil, errors.New("メーカー名必須")
    }
    
    return &Car{
        Maker: maker,
        Year:  year,
    }, nil
}

3. 優れた工場(ファクトリ)の設計ポイント

ポイント1:統一されたインターフェース

// 良い例:常に*Carとerrorを返す
func CreateCar(...) (*Car, error)

// 悪い例:場合によって返り値が異なる
func CreateCar(...) (*Car, error, string)

ポイント2:生産工程の隠蔽

// 内部実装は隠す(例:シリアル番号生成)
func generateSerial() string {
    return fmt.Sprintf("CAR-%d", time.Now().UnixNano())
}

ポイント3:拡張可能な設計

// 車種ごとの工場
func CreateSedan() *Car { ... }
func CreateSUV() *Car { ... }

4. 実際の工場(ファクトリ)運用例

ケース1:DB接続工場

func CreateDBConnection(config Config) (*sql.DB, error) {
    connStr := fmt.Sprintf(
        "host=%s port=%d user=%s password=%s",
        config.Host, config.Port, config.User, config.Pass,
    )
    
    db, err := sql.Open("postgres", connStr)
    if err != nil {
        return nil, fmt.Errorf("接続失敗: %w", err)
    }
    
    if err := db.Ping(); err != nil {
        return nil, fmt.Errorf("接続確認失敗: %w", err)
    }
    
    return db, nil
}

ケース2:設定ファイル工場

func LoadConfig(path string) (*Config, error) {
    raw, err := os.ReadFile(path)
    if err != nil {
        return nil, fmt.Errorf("設定ファイル読み込み失敗: %w", err)
    }
    
    var config Config
    if err := yaml.Unmarshal(raw, &config); err != nil {
        return nil, fmt.Errorf("設定解析失敗: %w", err)
    }
    
    if err := config.Validate(); err != nil {
        return nil, fmt.Errorf("設定検証失敗: %w", err)
    }
    
    return &config, nil
}

5. 工場長(開発者)へのアドバイス

  1. 単一責任原則
    「1つの工場では1種類の製品だけを作る」

  2. 不良品対策
    「必ずバリデーション工程を設ける」

  3. 生産ラインの最適化
    「複雑な生成処理はサブ関数に分割」

  4. 工場の安全性
    「非公開フィールドで内部状態を保護」

  5. 工場の拡張性
    「インターフェースを活用して差し替え可能に」

🎯 究極の目標
「クライアントコードが『どう作られるか』を気にせず、
 ただ『何が欲しいか』だけを伝えられる工場を作る」

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?