バウンデッドコンテキストの定義
歴史的なコンテキスト
2024 年 5 月まで、GitLab のコードベースには明確なドメイン構造がありませんでした。 最初のステップとしていくつかのモジュールの作成を強制しましたが、一貫して実施するための明確に定義された戦略はありませんでした。
コードの大部分は適切に名前空間化・整理されていませんでした:
- 使用された Ruby 名前空間は常に SSoT を表しているわけではありませんでした。複数の名前空間に広がる重複した概念がありました。例えば:
Abuse::とSpam::、またはSecurity::Orchestration::とSecurity::SecurityOrchestration。 - 同じバウンデッドコンテキストに関連するドメインコードが複数のディレクトリに散在していました。
- ドメインコードが
lib/ディレクトリに存在し、app/の同じドメインとは異なる名前空間の下にありました。 - 一部の名前空間は非常に浅く、少数のクラスしか含んでいない一方、他の名前空間は非常に深く大きいものでした。
- 古いコードの多くは名前空間化されておらず、使用されているコンテキストを理解することが困難でした。
2024 年 5 月にバウンデッドコンテキストを定義・強制しました。
目標
- バウンデッドコンテキストが持つべき特性のリストを定義する。例えば: 少なくとも 1 つの製品カテゴリに関連していること。
- すべてのドメインコードが分解されるトップレベルのバウンデッドコンテキストのリストを持つ。
- エンジニアが利用可能なバウンデッドコンテキストのリストを明確に確認し、新しいクラスとモジュールをどこに追加するかを簡単に決定できる。
- アプリケーションに新しいバウンデッドコンテキストを追加するプロセスを定義する。これはあまり頻繁に発生すべきではなく、新しいバウンデッドコンテキストは以前に定義された特性に準拠する必要があります。
- 承認されたもの以外に新しいトップレベル名前空間を使用できないようにバウンデッドコンテキストのリストを強制する。
バウンデッドコンテキストを機能カテゴリにマッピングする
バウンデッドコンテキストは機能カテゴリを基点にします。機能カテゴリは、モジュールを deep に保つのに十分な大きさのプロダクト領域を表し、小さなトップレベルモジュールの乱立を防ぎます。機能カテゴリを基点にすることで、コードベースをプロダクトの ubiquitous language に合わせ続けることもでき、新しいコントリビューター(GitLab チームメンバーとより広いコミュニティ)がコードを辿りやすくなります。
1 つのチームが複数の機能カテゴリを担当できるため、複数のバウンデッドコンテキストのビジョンを所有できます。機能カテゴリのオーナーシップが変わった場合、そのバウンデッドコンテキストを新しいオーナーに再マッピングするコストは低く抑えられます。
機能カテゴリとバウンデッドコンテキストは、必ずしも 1 対 1 ではありません:
- 複数の機能カテゴリが強く関連している場合、それらは単一のバウンデッドコンテキストの下にグループ化されることがあります。
- ある機能カテゴリが親機能カテゴリの中でのみ関連する場合、それは親のバウンデッドコンテキストに折り込まれることがあります。例えば、build artifacts は Continuous Integration 機能カテゴリの中に存在し、単一のバウンデッドコンテキストの下に統合される可能性があります。
イテレーション
- このステップはモジュール化をブロックするものではありませんが、
lib/に存在する汎用コードが少ないほど、バウンデッドコンテキストを特定・分離しやすくなります。 - ドメインコードへの依存を防ぐために、別のプロジェクトに存在できるコードを分離する。
- このステップはモジュール化をブロックするものではありませんが、
ADR-001: アプリケーションドメインのモジュール化? モジュール化から始める
ADR-002: フィーチャーカテゴリを中心としたバウンデッドコンテキストの定義をコードの SSoT として。
- バウンデッドコンテキストの SSoT リストを定義する。
- RuboCop 静的解析ツールを使用してそれを強制する。
- 指定されたリストに基づいて非標準の Rails ディレクトリをオートロードする。
最終更新 July 30, 2026: Merge pull request #483 from kyama0/translation/batch-2026-07-29-1 (
c955a93f)