「7つの設計原則とオブジェクト指向プログラミング」から関心の分離を読み解く
「実装の詳細を記述したモジュール群」とは何か?をサンプルコードをベースに該当するモジュールを確認しよう
https://scrapbox.io/files/66d41afb5aa422001c254ae3.png
「入出力と計算・判断の分離」とは、レイヤードアーキテクチャにおける外縁部分と中心部分を分けて記述しようの意味で違和感なし。
ただし、入出力の中でも「業務の関心」となる下記の機能(application層)と、
- 利用者画面への出力
- 帳簿への記録(永続化)
- 他業務への通知・参照
業務の関心ではない入出力(=実装の詳細=具体的なデバイスや外部システムとのI/O)(UI層/Infra層)とに分けられる。
https://scrapbox.io/files/66d41afb5aa422001c254aec.png
では計算・判断における「業務の関心と実装の詳細の分離」とは
業務の関心である計算・判断はビジネスルール=domain層に他ならない。
そしてビジネスルールが用いられるビジネスロジックがapplication層であり、さらにロジックを組み上げてビジネスプロセスが構成され、利用者に有意なビジネス機能が提供される。
【ここから余談】
ここでは、ビジネス機能はマクロ的なビジネスプロセスとして捉え、 基本となる事業展開上で必要となる職務/職能の視点から分類整理したものである。ビジネス機能は、マクロなビジネスプロセスの静的な側面からや、マクロな業務処理機能として分類整理したものと見ることが出来る。 ここでは、プロセスを一般的にビジネス遂行上の業務処理機能 (意思決定機能) を指すものとし、ファンクション、アクション、アクティビティ、プロセス等の詳細な分類学の不毛な議論を避け、単純にインプットをアウトプットに変換するプロセスとして見ている。このビジネスプロセスは大分類 中分類、 少分類、 細分類と階層的に分類され、 具体的な業務処理自体になるものであり、このビジネスプロセスの連携を動的に捉えて業務処理フローを定義するものとする。 ここでは、ビジネスプロセス内での処理上の権限/規約/判断基準等をビジネスルールまたは業務ルールとして整理し、 処理ロジック (方法) と分離し、 多くのビジネス環境の変化をビジネスルールとして捉え、 共通的な業務処理方法の整理 統合を進めることに役立てるアプローチをとる。加えて、 日本の商習慣では、各社独自の商流/物流/金流の処理を認めており、これらを全ての例外的な処理を含めてシステム化を進めてきたが、 例外処理でなく一つの業務ルールとして整理し、 共通化し、ひいては標準化することを目指すためにも、ビジネスルール/業務ルールの整理/分類/分析/標準化が必要となる。尚、 ビジネスルールは基本的な規程/標準/ 要領が中心となるが、 業務ルールは、 詳細な個別の業務処理上のルールである。 では残る「実装の詳細x計算・判断」とは何者だろうか
これは下でOpusが述べている通り、言語やライブラリなどが提供する関数や演算機能やプリミティブな型と見てよいだろう。
「算術演算、比較演算、条件分岐、コレクション操作」などによりビジネスルールがプログラム上で表現されることを想定されていると思われるが、このときにビジネスルールをプログラム的にピュアに表現するために(特定のライブラリやフレームワークに過度に依存しないために)、ライブラリやフレームワークによる機能への依存も分けられるものは分けておくということ。 四象限とオニオンアーキクチャに対比してみよう
- 「業務の関心 x 計算・判断」は domain パッケージ
- 「業務の関心 x 入出力」は application パッケージ
- 「実装の詳細 x 入出力」は presentation および infrastructure パッケージ
- 「実装の詳細 x 計算・判断」はパッケージ上に該当するモジュールはない。ライブラリやフレームワークが提供する組み込み関数や型が該当
Opusによる解説
関心の分離では、関心事を以下の4象限に分類します。
1. 業務の関心 x 入出力
2. 業務の関心 x 計算・判断
3. 実装の詳細 x 入出力
4. 実装の詳細 x 計算・判断
そして、これらの関心事を別のモジュールに分離することで、複雑なソフトウェアをわかりやすく整理できると説明しています。
特に、業務のビジネスルールに基づく計算・判断のロジック(ドメインロジック)は最も複雑になりがちな関心事であり、他の関心事から分離することが重要だと主張しています。
- 業務の関心事を表現するクラス群。ビジネスルールに基づく計算・判断のロジックを記述。
- ユースケースを実現するアプリケーション層。業務の入出力に関する関心事。
- UIの入出力を扱うクラス群。実装の詳細に関わる入出力の関心事。
- データベースなどの技術的な詳細を扱うクラス群。実装の詳細に関わる入出力の関心事。
このように、関心事に応じてきれいに分離されたパッケージ構成になっており、関心の4象限に対応したモジュール構造の実例と言えます。
業務のビジネスルールを表現するdomainモジュールを中心に、他の関心事を表現するモジュール群がそれを使う構成になっています。
これにより、業務の関心事とプログラムの記述内容が直接的に対応し、変更への対応もしやすくなっています。
実装の詳細 x 計算・判断について
関心の4象限のうち「実装の詳細 x 計算・判断」に該当する処理は、GitHubのサンプルコードからは明示的には見つけられませんでした。
「実装の詳細 x 計算・判断」の例としては、以下のようなものが考えられます。
- フレームワークやライブラリ固有の計算処理
- 例えば、Spring FrameworkのAOPで実装するロギングやトランザクション制御のロジックなど
- 技術的な制約や環境に特化した判断処理
- 例えば、並列処理の制御、外部システムとの通信方式の選択、エラーハンドリングの方法などの判断ロジック
これらは業務というよりは技術的な関心事であり、その実装の詳細は業務ロジックからは切り離されるべきものです。
ただし、サンプルコードが単純なCRUD操作のみを例示しているため、「実装の詳細 x 計算・判断」に該当する処理が明示的には含まれていないのかもしれません。
実際のシステム開発では、インフラストラクチャ層の中で、フレームワークやライブラリに依存した計算・判断処理を技術的な詳細として記述することになると想像します。その際も、業務ロジックから独立した関心事として別のモジュールで扱うことで、疎結合な設計が実現できるでしょう。
以上のように、「実装の詳細 x 計算・判断」の処理は、サンプルコードからは読み取りづらい部分ではありますが、システム全体のアーキテクチャを考える上では重要な関心の分離の観点の1つだと言えます。