Status | Authors | Coach | DRIs | Owning Stage | Created |
---|---|---|---|---|---|
proposed |
@grzesiek
@fabiopitino
| 2023-07-05 |
モジュラー・モノリスPOC
モノリスのモジュール化は複雑なプロジェクトです。未知の部分がたくさんあるでしょう。リスクを軽減し、重要なインサイトを提供するのに役立つのが、早い段階で提供できる概念実証(Proof-of-Concepts)です。
モジュール間コミュニケーション
私たちが提供する予定のPoCは、モジュール間通信のPoCです。私たちはモジュールを分離する必要性を認識していますが、それでも、きちんと定義されたインターフェイスを使って、モジュールが一緒に通信できるようにしています。モジュールはファサード・クラス(通常のライブラリがそうであるように)を通して通信することもできますし、イベント・システムを通して通信することもできます。どちらの方法も重要です。
主な問題は、どのようにインターフェイスを定義し、どのように通信チャネルを設計するかということです。
私たちの目標の一つは、モジュールをプラグアウトできるようにし、その一部を別のサービスとしてオペレーションできるようにすることです。そうすることで、将来GitLab.comをデプロイしやすくなり、主要なドメインをスケールしやすくなります。この目標を達成する一つの可能な方法は、インターフェイスとしてprotobufを使い、通信チャネルとしてgRPCを使ってモジュール間の通信を設計することです。モジュールがプラグインされた場合、gRPCとシリアライゼーションをバイパスし、(インターフェースとしてprotobufを使用しながら)プロセス内通信プリミティブを使用します。モジュールがプラグアウトされると、gRPC はモジュール間のメッセージを伝達します。
モジュール境界を強制するためにPackwerkを使用
Packwerkは、Rubyのモジュール境界の定義と強制を支援する静的解析ツールです。
このPoCマージリクエストでは、モノリスを個別のモジュールに分割したディレクトリ構造の可能性を示します。
このPoCでは、EEエクステンション(およびJHも)の問題を解決することも目指しており、Coreコードベースのみをロードするか、エクステンションをロードするかによってRailsオートローダを調整できるようにしています。
PoCでは、Ci::
名前空間のごく一部のみをcomponents/ci
Packwerkパッケージに移動することも試みました。これは、これまでで最も反復的なアプローチです。
Packwerkを採用するには、さまざまなアプローチが考えられます。その他のPoCとしては、CIパッケージの大規模な抽出と2つの主要なCIクラスのパッケージへの移動が検討されています。
Packwerkのパッケージと設定の導入から、オートローダーがどのパッケージでも動作するためのパスの設定まで、3つのPoCには共通点が多くあります。様々なマージリクエストの間で変化しているのは、最初に移動するファイルを選択するアプローチです。
PoCの主な目標は以下の通りです:
- GitLabのコードベースでPackwerkが使えるかどうか。
- 開発者の学習曲線を理解します。
- EEとJHエクステンションのサポートを検証します。
- 段階的なモジュール化
ポジティブな結果
- Packwerkは主にRailsコードベースで動作するように設計されているので、GitLabで使うのはとても簡単です。
- ドメインコードの構成をMVCパターンに従うのではなく、モジュール指向に変更することができます。Railsのオートローディングが新しいディレクトリ構造をサポートするようにするための小さな初期変更が必要です。その後、新しいトップレベルのパッケージ/bounded-contextを登録すれば、1LOCの変更で済みます。
- PoCで示された正しいディレクトリ構造を使用することで、EEやJH拡張を含むすべてのコードをパッケージに含めることができます。
- 段階的なモジュール化が可能であり、最初は強制しないことから、インメモリ・マイクロサービス環境をシミュレートする完全な分離まで、どの程度のモジュール化も可能です。
- ファイルをPackwerkパッケージに移動することは、必ずしも定数の名前を変更することを意味しません。これは長期的にはお勧めできませんが、ツールが提供する特別な柔軟性です。
- 例えば
Ci::
モジュールを Packwerk パッケージに展開する場合、CommitStatus
のように CI ドメインに属しながら名前空間がない定数や、Gitlab::Ci::
のように名前空間が異なる定数が存在する可能性があります。Packwerkは、このような定数をci
パッケージ内部に移動することを許可し、境界違反に正しくフラグを立てます。 - RubyAtScaleツールによるPackwerkの機能強化により、パッケージ内のすべての定数が同じRuby名前空間を共有することを強制できます。いずれはこれを活用したいと思います。
- 例えば
- RubyAtScaleは、モジュール化とその採用に関するメトリクスを追跡するツールも提供しています。
- Packwerkには、IDEの拡張機能(VSCode用など)があり、(Rubocopのような)違反に関するリアルタイムフィードバックを提供します。また、単一のパッケージに対して開発ワークフロー中にCLI経由で実行することもできます。プッシュ前のGitフックや、コードレビュー中のDangerにインテグレーションすることもできます。
課題
これらの課題のいくつかは、ツール/アプローチとしてのPackwerkに特有のものではありません。これらはPoCの間に観察されたもので、モジュール化のプロセスにより一般的に関連するものです:
- Packwerkのパッケージを導入する際に、正しいアプローチや間違ったアプローチはありません。開発者が最適な判断を下すためのツールを提供するために、明確なガイドラインを定義する必要があります:
- 時には、空のパッケージを作成し、その中のファイルを少しずつ移動させることもできます。
- すでによく設計され、分離されたコードベースの一部をラップすることもあります。
- ゼロから新しいパッケージを作ることもあります。
- 異なるディレクトリ構造にコードを移動する場合、現在のディレクトリ構造に従って拡張機能を管理する JiHu を巻き込む必要があります。部分的にマイグレーションされたモジュールがあるかもしれません。
- プライバシー/依存性チェックを有効にすると、Railsコードベースの定数参照は非常に複雑に絡み合うため、Packwerkは(RubocopのTODOのように)多くの違反ログを記録します。
- パッケージを所有するチームは、パッケージのビジョンを定義する必要があります。すべての違反が修正された後のパッケージはどのようなものになるでしょうか。これは、パッケージがシステムのコンテキストマップのどこに位置するかを指定することを意味するかもしれません。現在のパッケージが別のパッケージ
A
によってどのように使われるべきか、他のパッケージをどのように使うべきか。 - 上記のビジョンは、開発者がこれらの違反を時間をかけてどのように修正すべきかを伝えるべきです。特定の定数を公開すべきでしょうか?パッケージは他のパッケージを依存パッケージとして列挙すべきでしょうか?シナリオによってはイベントを使うべきか?
- チームにはそのためのガイダンスが必要でしょう。このような取り組みにおいて、エンジニアリングチームをサポートする、ドメインについて非常に広く理解しているメンテナーのようなエンジニアのチームが必要かもしれません。
- パッケージを所有するチームは、パッケージのビジョンを定義する必要があります。すべての違反が修正された後のパッケージはどのようなものになるでしょうか。これは、パッケージがシステムのコンテキストマップのどこに位置するかを指定することを意味するかもしれません。現在のパッケージが別のパッケージ
- Knapsackのチューニングと選択的テストに関するCI設定の変更は、PoCでは無視されました。
フロントエンドのソートハット
Frontend sorting-hatは、複数のドメインを組み合わせてGitLabの全ページをレンダリングするためのPoCです(メニューや複数の別々のドメインから来たアイテムがあります)。
フロントエンドのアセット集約
フロントエンド資産の集約は、マイクロフロントエンドを分離するためのPoCです。