はじめに
業務アプリを作る上では、業務ロジックが正しく実装されていることが必須ですね。
業務ロジック、英語でいうと、ビジネスロジックw
業務ロジック(=ビジネスロジック)とはなんぞや? な話をここで深追いするつもりはありませんが、いわゆる3層構造のWebアプリケーションにおいては、以下のように定義され、業務ロジックは中間層にあたります。
いや、今は3層構造じゃなくて、4層なんじゃない?ドメイン層とアプリケーション層に分けるんじゃ?と言う方もあるかもしれませんが、
ここでは一旦3つにしましょう。層としては3つで別によいと思いますし。
3つにさえ分けられていないのが現状だったりします。
それぞれの層が「疎結合」とはならず、かなり密に結合しあっているのが現状ではないでしょうか。
疎結合かどうかのチェックポイント
- 各層の内部での変更が他の層に影響を及ぼさない作りになっている
- ある層だけ作り変えることが容易に可能
- 層ごとに別アプリケーションとしてデプロイが可能
- ある層だけ、スケールアウトすることが可能
プレゼンテーション層に、入力値の相関チェックなどの業務ロジックが含まれていたり、
複雑なデータアクセスを必要とするロジック部分が、ストアドプロシージャとしてDB側に実装されていたり、という例がよくあります。
また、多くの場合、一連の業務ロジックを実現するのに、データアクセスを繰り返しながら、判断ロジックを順に繰り返すという形式で実装されているため、
データアクセスと判断ロジックを切り離せないという例がほとんどなのではないかと思います。
この課題のソリューションとして、「ルールエンジン」を適用することは、実はとても理にかなっています。
今からその話をします。
ルールエンジンとは
ルールエンジンの「ルール」とはビジネスルールのことを指します。
ビジネスルールとは、ビジネスを実行するために必要な規則・規約・判断基準等のことです。
言い換えると、業務アプリケーションにおける、業務ロジックで表現される部分にあたります。
ルールエンジンを使ってロジック部分を実装することによるメリットはいくつもありますが、今日はその中でも以下のメリットについて解説します。
ロジック部分を"ルール"と"データアクセス"とに分離し、ルール部分をアプリケーションから切り離し疎結合にすることでメンテナンス性を高めることが出来る
業務ロジックを"ルール"と"データアクセス"に分離する
図1:従来のロジック図
この図は、1か月の勤怠データを元に、残業代を計算するロジックの例です。
この図のように、DBに登録されているいろいろな「マスター」を参照しながらロジックが走り、画面に結果を返す、もしくは他のDBに格納するというケースがよく見られます。
ここで問題となるのが、
「DBを参照しながら、判定や計算を行っている」
ということです。
新たなチェックが必要となった場合、ここに新たな分岐を追加し、またそのチェック内容のしきい値を格納用に新たなマスターを追加して・・・
というように、ロジックがますます複雑化し、スパゲティコード化していきます。
では、これをロジック部分とデータ参照部分に分離してみましょう。
図2:ロジックとデータ参照を分離した例
判定や計算処理部分は、ルールエンジン側に持っていきます。
そして、そのために必要となるデータは、あらかじめ取得し、ルールエンジンを呼び出す際に、渡すという形式にします。
このとき最も重要なことは、
「ルールエンジン内から、DBアクセスを行わない」
ということです。データ参照とロジック処理とを完全に分離することが大切です。
ルールエンジンでは、渡されたデータを元に各種処理を行い、その結果を返すだけにします。
もともとの残業代計算ロジックで参照していた、各種マスターの内容に注目してみましょう。
これらをマスターで管理していた理由が、ロジックの値を外に出して変更しやすくするため、だけであれば、これらマスターは廃止して、「ルール」として管理することが出来ます。
この例では、「シフトマスター」や「休日マスター」がその対象となります。
マスターではなく、ルールとして管理することで、ロジック内容がひと目で把握できますし、また、DBのテーブル構造にしばられないため、柔軟な変更が可能になります。
マスターメンテの代わりに、ルールを変更するという運用になります。
このように、判定や計算処理と、データ参照とを分離することで、アプリケーションアーキテクチャがシンプルになります。
また、DB構造が大きく変わることがあっても、ルールに渡すデータに変更がなければ、ルール側は影響を受けずにすみます。
ルールエンジンの呼び出しは、REST APIを使って呼び出し、INPUT/OUTPUTデータは、JSON形式等でやりとりするのが一般的です。
これにより、データアクセスとビジネスロジックとが、切り離され、疎結合になりました。
アプリケーションの改修時の影響分析調査は、短時間で済むようになります。
最も頻繁に起こる改修は、ビジネスロジック部分の改修です。
その際、ルール部分の呼び出しインターフェースに変更がなければ、ルール部分のみのテストをすれば、他に影響がないことがはっきりします。
DB側に何らかの変更を入れる際も、ルールエンジン呼び出し部分のインターフェースに変更が入るか入らないかを気にすればよいことになります。
また、ルールエンジン部分は別プロセス、別アプリケーションとして動かすことが可能になり、アプリケーションの柔軟性を高めます。
マイクロサービス分割の指針にするのもよし
モノリシックなアプリケーションを、マイクロサービス化していく上で、どのような単位で分割すべきか、はなかなか悩ましいテーマですが、
このように、ビジネスロジック部分を切り出し、業務ルール単位で、マイクロサービス化するという分割指針は非常におすすめです。
おわりに
3層構造については、Webアプリの開発をし始めたころから、何度も耳にしていますが、本当の意味で3層にキレイに分かれているアプリケーションを見たことがありませんでした。
(ある意味、COBOLのプログラムのほうが、明示的に分かれていたとも言える・・・密結合ではあったが)
でも、ルールエンジンを適用したアプリケーション開発をした時、はじめて、「こ、これは!ビジネスロジック層がきちんと分離出来ているぞ!!!」と感動しました。ルールエンジンがなくても実現は論理上可能かもしれませんが、使ったほうが良いです。ルールエンジンの特性を活かすことができます。
ここではルールエンジンの詳細は書いていませんが、別ポストをぜひ参照ください。