Fineractのモジュール化:これまでの進捗と課題

FineractはApache Foundation傘下のオープンソースプロジェクトとして、金融サービスのためのオープンソースプラットフォームとして知られています。近年、コミュニティの成長と貢獻量の増加に伴い、単體アーキテクチャの限界が顕在化し、モジュール化の必要性が高まっています。本記事では、Fineractのモジュール化における現狀、技術的課題、および今後の方向性について解説します。

モジュール化の動機

Fineractのモジュール化は、以下の要因から必要とされています。

  • コミュニティの成長と貢獻量の増加:過去2年間で貢獻量が前年比で數倍に増加し、年間4つのバージョンのリリースが可能となっています。しかし、開発者の経験不足により、開発プロセスが不安定化しています。
  • 開発者體験の改善:単體アーキテクチャでは、機能間の依存関係が複雑になり、開発者が不必要なツールクラスを再利用しやすいため、機能間の結合度が高まっています。
  • 安定性の向上:コミュニティが安定したコードベースを求める中、モジュール化によりバージョン管理と機能の隔離が可能になります。
  • カスタマイズの柔軟性:単體アーキテクチャではカスタマイズが困難なため、標準化されたモジュール化フレームワークの構築が求められています。

アーキテクチャと技術的詳細

Fineractのモジュール化には以下のアーキテクチャと技術的選択が採用されています。

  • 分層構造
    • REST API層:初期はJAX-RSを使用していましたが、Spring BootのJSONシリアライズを採用。しかし、データ構造の複雑さにより手動処理が必要な狀況が生じています。
    • CQRSパターン:読み取り要求とデータ変更要求を分離し、獨立した拡張性を実現しています(書き込みインスタンス/読み取りインスタンス)。
    • データ層:初期はHibernateを使用していましたが、Apache Foundationのライセンス問題によりOpenJPAに切り替え、最終的にはEclipseLinkを採用。一部の機能ではPostgreSQLをサポートするため、原生SQLの使用が行われていました。
    • サービス層:Springの@Serviceアノテーションを使用し、ビジネスロジックとデータベースアクセス(Repository)を含んでいます。
  • モジュール化の実踐
    • レポートエンジンモジュール:GPLライセンスの問題により獨立モジュールとして分離され、獨立したJARファイルとして提供されています。Fineractのデータパラメータを修正し、外部モジュールのサポートを実現しています。
    • Fineractクライアントモジュール:標準化されたAPIクライアントを構築し、OpenAPIの記述子を用いて機械可読なドキュメントを生成。Code Generatorツールの開発も進められています。
    • コアモジュールの分割:コアモジュール(Core Module)とその他の機能モジュールの分割を試みましたが、モジュール間の依存関係の問題が殘っています。

技術的課題

モジュール化の進展に伴い、以下の課題が顕在化しています。

  • JSONシリアライズの問題
    • 手動でのJSONシリアライズ/デシリアライズにより、ビジネスロジック層と通信プロトコルが結合しています(今後gRPCへの移行が検討されています)。
    • データ層の複雑さ:JPAと手動SQLの混合により、データベースの獨立性とクエリ生成ツール(QueryDSL、JQ)の統合が課題となっています。
  • モジュール化構造の設計
    • モジュールパッケージ構造:
      • API:RESTリソースクラス(エントリポイント)。
      • Data:データ転送オブジェクト(DTOs)、サービスインターフェースと実裝(ビジネスロジック)。
      • Domain:データベースとJavaオブジェクトのマッピング。
      • Repository:データベースアクセス層。
    • 現在の問題:データ層とサービス層の結合が強く、真のモジュール化を実現するための再設計が求められています。

今後の展望

Fineractのモジュール化には以下の方向性が示されています。

  • Spring Modulithフレームワークの導入:単體アーキテクチャとモジュール化の特徴を融合させ、モジュール化設計の參考として活用されます。
  • モジュール化の標準化
    • コアモジュールと機能モジュールのさらに明確な分割を行い、モジュール間の依存関係を削減します。
    • OpenAPIを用いたクライアントツールの生成により、APIの利用効率を向上させます。
  • 技術的最適化の方向
    • QueryDSLやJQなどのツールを導入し、手動SQLとJPAの混合使用の問題を解決します。
    • データベースの獨立性を高め、PostgreSQLなどの多様なデータベースへのサポートを強化します。

現在の狀況

  • モジュール化の進捗:レポートエンジンとクライアントモジュールの実裝が完了していますが、コアアーキテクチャはまだ単體アプリケーションのままです。
  • コミュニティとバージョン管理
    • 最大3つのマイナーバージョンをサポートし、安定性を確保しています。
    • バージョンリリースの頻度が向上していますが、開発者のボトルネックの改善が課題です。
  • アーキテクチャの改善
    • Gradleモジュールを段階的に分割し、単體コードの結合度を低下させています。
    • 技術的なディスカッションを通じて、JPAの完全な除去を検討し、より柔軟なデータベース操作方式への移行を模索しています。

モジュール構造と設計

  • モジュールの分割
    • モジュールはJavaパッケージ(package)に似ており、サブパッケージ(sub-packages)を含みます。
    • 現在の構造には以下が含まれます:
      • APIパッケージ:RESTリソースクラス(エントリポイント)。
      • データパッケージ:データ転送オブジェクト(DTOs)、サービスインターフェースと実裝(ビジネスロジック)、ドメインクラス(データベースとJavaのマッピング)、リポジトリ(データベース操作)。
    • デザイン図と実際の実裝の間にはギャップがあります。
  • データ層の問題
    • JSONデータとJavaの対応処理は手動で行われ(Gsonを使用)、冗長で複雑な処理が発生しています。
    • プロセスを簡略化するために、一部の層はデータ層をスキップし、サービス層に直接データを渡すことで、ビジネスロジックと通信プロトコルの結合が生じています。
    • 現在の技術的負債:ローンエンティティクラス(Loan Entity)には7,000行ものコードが含まれており、屬性とGetter/Setterのみを含めるべきであるにもかかわらず、実際にはビジネスロジックやユーティリティ関數が混在しています。

技術的負債と依存関係の問題

  • ドメイン境界の曖昧さ
    • ローン、ユーザーなどのエンティティデータには、モジュール間の依存関係(例:ローンとユーザー表の関連性)が存在しています。
    • ユーザー情報はセキュリティモジュールに屬するべきですが、ローンモジュールが直接參照しているため、データの隔離性が損なわれています。
    • ユーザーインターフェースの要件(例:ユーザー名をIDではなく表示)がデータ構造設計を駆動し、結合度を高めています。
  • テストとビルドの課題
    • テストケースの數は約900以上ありますが、ビルドプロセスはシリアル実行され、フィードバックループが1時間以上かかることがあります。
    • 開発者はGitHub Actionsを使用してテストを実行する傾向があり、問題の発見が遅延しています。
  • データベース層の問題
    • 手動でSQLを書く際、データの隔離性を考慮せず、モジュール間のJOIN操作が行われています。
    • コンパイラがこのような問題を検出できないため、靜的チェックメカニズムの不足が問題となっています。

カスタムモジュールと解決策

  • カスタムモジュールの設計
    • 新しい機能は獨立したディレクトリに分離し、上流プロジェクトと混在しないようにする必要があります。
    • 自動化ツールの提供:
      • 依存関係の自動処理(例:Gradleの構成)。
      • カスタムJavaコードとLiquibaseスクリプトのサポート。
      • カスタムモジュールを含むDockerイメージの自動パッケージング。
  • モジュール置換メカニズム
    • 原サービスインターフェースの@Serviceアノテーションを削除し、Javaの構成で條件付きロードを実裝。
    • 原機能の完全置換または拡張(特定のメソッドの上書き)が可能になります。

セキュリティモジュール化と今後の方向

  • セキュリティモジュールの進捗
    • 現在はSpring Securityを使用していますが、権限やロールなどの情報はデータベースに保存されています。
    • Spring Authorization Serverとの統合を計畫しており、Fineractが獨立したIDサービスとして機能するようになります。
    • 外部サービス(例:Keycloak)をIDサービスとしてサポートし、今後は置き換え可能な設計に移行します。
  • 他の改善方向
    • 必要のないモジュール(例:インフラストラクチャ構成モジュール)を削除し、Kubernetesなどの構成管理ツールを使用。
    • ArcUnitなどのツールを導入し、アーキテクチャのチェックを自動化し、アーキテクチャルルールのテストを実施。

現在の課題と提案

  • モジュール化の進捗
    • 現在は単體アプリケーションですが、內部ではモジュール化された機能を管理しています。
    • 今後の目標は、モジュールを段階的に分割し、ドメイン境界とデータの隔離性を強化することです。
  • カスタムモジュールのルール
    • 新しい機能を追加する際には、ドメイン境界を明確にし、非関連のデータを混入させないことが求められます。
    • カスタムモジュールは命名空間ルール(例:會社名)に従い、ネストレベルを最大3層に制限する必要があります。