メインコンテンツまでスキップ

依存関係

モジュール間の依存方向と、依存関係を管理する理由を説明します。

依存方向の原則

client-apps → server-apps → server-core

server-platform (実装注入)

基本ルール

  1. 一方向依存: 依存は一方向のみ。循環依存は禁止
  2. coreは独立: server-coreは他のモジュールに依存しない
  3. 実装注入: server-platformの実装はserver-appsから注入

各モジュールの依存関係

client-apps

  • 依存可能: packages/*(共有パッケージ)
  • 依存禁止: server-*(サーバーコードは直接参照しない)

理由: クライアントとサーバーは別リポジトリに分離する可能性があるため

server-apps

  • 依存可能:
    • server-core/*(ドメインサービス使用)
    • server-platform/*(実装取得して注入)
    • packages/proto-gen-go(gRPC型定義)
  • 依存禁止: client-apps/*

理由: アプリケーション層は依存注入のコンポジションルート

server-core

  • 依存可能: server-core内の他のパッケージ(例:shared)
  • 依存禁止:
    • server-platform/*(実装に依存しない)
    • server-apps/*(アプリケーション層に依存しない)
    • packages/proto-gen-*(Protobuf生成コードに依存しない)

理由: ドメイン層は技術的詳細から独立させる

server-platform

  • 依存可能: server-core/*(ポートを実装するため)
  • 依存禁止: server-apps/*(実行物に依存しない)

理由: 実装は差し替え可能にし、アプリケーション層に依存させない

依存方向の例

良い例:投稿作成フロー

// server-apps/gateway/handlers/post_handler.go
import (
"go.bazbii.app/core/post" // ✅ core使用
"go.bazbii.app/platform/datastore" // ✅ platform使用
)

// server-core/post/service.go
import (
. "go.bazbii.app/core/shared" // ✅ core内のみ
)

// server-platform/datastore/postgres/post_repository.go
import (
"go.bazbii.app/core/post" // ✅ coreのポート実装
)

悪い例:循環依存

// ❌ server-core/post/service.go
import "go.bazbii.app/platform/datastore" // 実装に依存してはいけない

// ❌ server-platform/datastore/postgres/post_repository.go
import "go.bazbii.app/platform/observability" // 他のplatformに依存してはいけない(必要ならcore経由)

Protocol Buffersの扱い

原則

  • proto定義: packages/proto/ に配置
  • 生成コード: packages/proto-gen-go/, packages/proto-gen-ts/
  • server-core: proto-gen-*を直接importしない

理由

  • ドメイン層はプロトコルの詳細から独立させる
  • コントラクト変更時の影響を最小化

実装例

// ❌ server-core/post/entity.go
import "go.bazbii.app/packages/proto-gen-go/bazbii/types/v1" // NG

// ✅ server-core/post/entity.go
type Post struct {
ID PostID
ActorID ActorID
H3Index H3Index // ドメイン型を使用
}

// ✅ server-apps/api/handlers/post_handler.go
// ここでproto型とドメイン型を変換
func (h *PostHandler) Create(ctx context.Context, req *pb.CreatePostRequest) (*pb.CreatePostResponse, error) {
// proto型 → ドメイン型
post, err := post.NewPostDraft(req.H3Index, req.Text, actorID)

// ドメイン型 → proto型
return &pb.CreatePostResponse{PostId: post.ID.String()}, nil
}

共有パッケージ (packages)

依存方向

全てのモジュール → packages/*
packages/* → packages/*(限定的)
packages/* → server-* or client-*(禁止)

配置すべきもの

  • 設計: Protocol Buffers定義、型定義
  • ユーティリティ: i18n, themes, ts-utils
  • ビジネスロジック: packagesには置かない

依存関係の管理

Go Workspace

  • 複数のGoモジュールを一つのワークスペースで管理
  • go.work で依存関係を管理

pnpm Workspace

  • TypeScript/JavaScriptパッケージをワークスペースで管理
  • pnpm-workspace.yaml で設定

依存関係の確認方法

# Goモジュールの依存関係確認
cd server-core
go mod graph

# 循環依存チェック
go list -m all

# pnpmワークスペースの依存確認
pnpm list --depth=0

関連ドキュメント