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-10-29

クリーンアーキテクチャとは

概要

ビジネスルールを中心に置き、外の技術に依存しない設計

詳細

アーキテクチャの中心は「ドメイン(ビジネスルール)。
UI・DB・外部APIなどはすべて「外側の関心事」として扱われ、
依存の方向は常に内向き(=内側は外側を知らない)

層構造について

各層の役割

主な責務 外側or内側 外部との役割 具体例
Framwworks&Drivers 技術的な土台。外部ライブラリやフレームワーク層 最も外側 Webフレームワーク,DB,外部API,UI Gin,Gorm,Echo,MySQL,gRPCなど
Interface Adapters 内側と外側の橋渡し。データ形式変換・I/O制御。 外側寄り JSON,SQL,HTTP形式に合わせる HTTP Handler,DB RepositoryImpl
Use Cases(アプリケーション) ビジネスルールの組み立て。トランザクション単位の整理 内側 DBやUIを意識しない CreateUserUseCase,PlaceOrderUsecase
Entities(ドメイン) ビジネスルールの中核。純粋なロジック。 最も内側 技術的な依存ゼロ User,Order,CalculateTotal()

Goでのディレクトリ構成例

/internal
  /domain
    user.go              // Entity
    user_repository.go   // Repository interface
  /usecase
    create_user.go       // ユースケース
  /interface
    handler/http_user.go // HTTPハンドラ
  /infrastructure
    mysql/user_repo.go   // MySQL実装
/cmd/api/main.go         // DIで結線(wireやfxなど)

「内側」と「外側」とは具体的にどこな箇所の事か

内側

ビジネス(Entities)に近いものほど内側

外側

技術や実装に近いものほど外側

特徴・メリット

  • 1.依存方向が一方通行(内向き)
    • 内側(ドメイン)は外側(DB,Webフレームワークなど)を知らない。
    • 外側が「インターフェースを実装」して内側に提供する形。
  • 2.テストしやすい
    • ドメイン層やユースケースそうを「モック化されたリポジトリ」でテストできる。
    • DB接続なしでビジネスロジックの単体テストが可能。
  • 3.技術変更に強い
    • フレームワークやDBを差し替えてもドメインに影響しない。
      • 例:Gin-Fiberに変えてもユースケース層はそのまま。
  • 4.長期保守に向く
    • 「ビジネスルール」と「技術的実装」分離されているため、新機能追加やリファクタ時も影響範囲が明確。

Entities(ドメイン)とは

概要

システムの中で最も「本質的なビジネスルール」を表す層で、
外部技術(DB・UI・フレームワーク)に依存しない純粋なロジックを記述する場所。

詳細説明

ビジネス的に重要なルール・制約・状態遷移を保持する。
外部要因(DB,API,UI)に影響されないようにすることでどんな技術を使ってもルールが壊れないようにする。

具体例

間違った例

type User struct {
    ID int `json:"id" gorm:"primary_key"`
    Name string `json:"name"`
    Email string `json:"email"`
    Password string `json:"password"`
}

良い例

package domain

import "errors"

type User struct {
    id       int
    name     string
    email    string
    password string
}

// コンストラクタ: 不正な状態で生成されないように
func NewUser(name, email, password string) (*User, error) {
    if name == "" {
        return nil, errors.New("name is required")
    }
    if len(password) < 8 {
        return nil, errors.New("password must be at least 8 characters")
    }

    return &User{
        name:     name,
        email:    email,
        password: password,
    }, nil
}

// ドメインロジック(ビジネスルール)
func (u *User) ChangeEmail(newEmail string) error {
    if newEmail == "" {
        return errors.New("email cannot be empty")
    }
    u.email = newEmail
    return nil
}

func (u *User) Name() string { return u.name }
func (u *User) Email() string { return u.email }

このように書くと

  • gormやjsonタグがない→非技術依存
  • バリデーションや制約(ビジネスルール)を内包
  • 外部から直接フィールドを触れない(カプセル化)
    • goはフィールド名の先頭文字を大文字にしないと外部モジュールから接続できない
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?