従業員と部門のデータベースがあるとしましょう。これを処理するための単純なオブジェクトモデルを作成しました:
class Employee
{
decimal Salary;
Department Department;
}
class Department
{
decimal TotalSalaries; //calculated as the sum of all employees salaries
//stored in database, not just a C# property
}
と..
class Employees
{
void Create(Employee e);
void Update(Employee e);
void Delete(Employee e);
...
}
class Departments
{
...
}
従業員を更新したい場合は、単に次のようにします。
Employee emp = Employees.GetById(1);
emp.Salary += 100; //salary increase
Employees.Update(emp);
従業員の1人を更新するたびTotalSalaries
にDepartment
自動的に再計算したいのですがSalary
私は次のことができます:
void Update(Employee e)
{
... //
... // sql stuff to update employee fields.
Departments.ReCalculateTotalSalaries(e.Department.Id);
}
しかし、そうすると、単一責任の原則に違反すると思います。なぜ従業員の更新方法を気にする必要があるのDepartments
ですか?これは非常に単純な例ですが、エンティティ間に多くの依存関係がある場合、コードが非常に乱雑になる可能性があります。
私はそれを行う他の方法について考えました:
1)従業員のサービスクラスを作成します:EmployeeService
。次に、このクラスでUpdate()
、従業員を更新するメソッドを定義します。このメソッドは、従業員を更新し、部門の合計を再計算します(もちろん、リポジトリメソッドを呼び出します)。
void Update(Employee e)
{
Employees.Update(e);
Departments.ReCalculateTotalSalaries(e.Department.Id);
}
問題:データモデルに多くの依存関係がある場合、モデルレイヤーをほぼ「2倍」にする必要があります(クラスの数x2)。また、コントローラー(またはビュー)がリポジトリを直接呼び出すのではなく、常にサービスメソッドを呼び出すようにするにはどうすればよいですか?
2)Employees
リポジトリには、メソッドOnSalaryChange()
から呼び出されるイベントがあります。Update()
リポジトリDepartments
はそれをサブスクライブし、必要に応じて必要な処理を実行します(つまり、call ReCalculateTotalSalaries()
)。そうすれば、リポジトリにDepartments
とどまるものは他のエンティティを気にする必要がありません。Departments
Employees
問題:給与が変更されたときに何が起こったのかを(コードを読んだりデバッグモードで)追跡するのが非常に難しくなる可能性があります(複数のサブスクライバーがいる場合)。また、サブスクライバーを特定の順序で呼び出す必要がある場合は、問題になる可能性があります。