CQRS (Command Query Responsibility Segregation) の概念に従って、MVC アプリケーションで DAL を直接参照し、ViewModel を介してすべての読み取りを行っています。しかし、私の同僚は、読み取りを行うときにビジネス ロジックを適用する必要がある場合、何をするかを尋ねてきました。たとえば、以下のようなシナリオでパーセンテージ値を計算する必要がある場合:
//Employee domain object
class Employee
{
string EmpName;
Single Wages;
}
//Constant declared in some utility class. This could be stored in DB also.
const Single Tax = 15;
//View Model for the Employee Screen
class EmployeeViewModel
{
string EmpName;
Single GrossWages;
Single NetWages;
}
// Read Facade defined in the DAL
class ReadModel
{
List<EmployeeViewModel> GetEmployeeList()
{
List<EmployeeViewModel> empList = new List<EmployeeViewModel>;
string query = "SELECT EMP_NAME, WAGES FROM EMPLOYEE";
...
..
while(reader.Read())
{
empList.Add(
new EmployeeViewModel
{
EmpName = reader["EMP_NAME"],
GrossWages = reader["WAGES"],
NetWages = reader["WAGES"] - (reader["WAGES"]*Tax)/100 /*We could call a function here but since we are not using the business layer, the function will be defined in the DAL layer*/
}
);
}
}
}
上記の例では、DAL レイヤーで行われている読み取り中に計算が行われています。計算を行う関数を作成することもできますが、読み取りのためにビジネス層をバイパスしたため、関数は DAL に配置されます。さらに悪いことに、Tax の値が DB に格納されている場合、誰かがストアド プロシージャの DB で直接実行する可能性があります。そのため、ここで他のレイヤーにビジネス ロジックが漏えいする可能性があります。
コマンドを実行しているときに、計算された値を列に保存しないのはなぜだと言うかもしれません。では、シナリオを少し変えてみましょう。現在の税率を含むレポートで従業員の潜在的な正味賃金を表示していて、賃金がまだ支払われていないとします。
これを CQRS でどのように処理しますか?