Role Object パターンと古き良き集約を使用することもできます。
すべてのビジネス ロジックを含むスマート エンティティを用意する代わりに、それらをダムにし、すべてのビジネス ロジックを役割に移動して、ダム エンティティを集約します。あなたの行動は、役割の中に住む一流の市民です。
例:
interface BannableUser
{
public function ban();
}
1 つの特定の動作を持つインターフェイスを持つことは、インターフェイス分離の原則に従います。また、アプリケーション固有の動作のコレクションを持つエンティティよりも個々の動作を再利用する可能性が高いため、再利用の可能性が大幅に増加します。
これを実装するには、適切なロール クラスを作成します。
class BannableUserRole implements BannableUser
{
private $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function ban()
{
$this->user->isBanned = true;
}
}
User エンティティはまだありますが、すべての動作が完全に取り除かれています。基本的には、Getter と Setter、またはパブリック プロパティの単なるバッグです。それはあなたのシステムが何であるかを表しています。インタラクション部分ではなく、データ部分です。インタラクションは現在、ロール内にあります。
class User
{
public $isBanned;
// … more properties
}
ある種の Web UI があると仮定すると、コントローラーで次のことができます。
class BanUserController implements RequestHandler
{
// …
public function handleRequest(Request $request)
{
$userId = $request->getVar('user_id');
$user = $this->userRepository->findById($userId);
$bannableUser = new BannableUserRole($user);
$bannableUser->ban();
}
}
ユーザーの実際の検索と役割の割り当てを UseCase クラスに移動することで、これをさらに分離できます。それをコンテキストと呼びましょう:
class BanUserContext implements Context
{
public function run($userId)
{
$user = $this->userRepository->findById($userId);
$bannableUser = new BannableUserRole($user);
$bannableUser->ban();
}
}
これで、すべてのビジネス ロジックがモデル レイヤー内にあり、ユーザー インターフェイスから完全に分離されました。コンテキストは、システムが行うことです。コントローラーは、適切なコンテキストにのみ委任します。
class BanUserController implements RequestHandler
{
// …
public function handleRequest(Request $request)
{
$this->banUserContext->run($request->getVar('user_id'));
}
}
以上です。Runkit や同様のハッカーは必要ありません。上記は、さらに調査したい場合に備えて、 Data Context Interactionアーキテクチャ パターンの簡略化されたバージョンです。