问题
First, as I know, Entity in DDD is almost same with Value Object except Entity has identity. Every article I have read say same thing that entity id has ORM mapping with any ORM tool. But I don’t want to use ORM mapping in Entity. Instead, I would like to do database operation with Repository Interfaces without mapping. And, in this case, I am stuck on how I should do this.
I will explain in my mind with an example below
Let’s assume I have a TODO application and there are some questions in the TODO and some answers in each those questions.
We have 3 value object (or entity): Todo TodoQuestion TodoQuestionValue
Now, I thought that I have a value object (or entity) for TODO. This value object has a method to get questions that gets array of TodoQuestion value object. And inside of TodoQuestion value object we have a method to get values of questions that gets array of TodoQuestionValue.
<?php
class Todo{
private int $id;
/**
* @param array<TodoQuestion> $questions
*/
private array $questions;
private TodoRepositoryInterface $repository;
public function __constructor(TodoRepositoryInterface $repository){
$this->repository = $repository;
}
public function getQuestions(){
$this->questions = $this->repository->listQuestionsByTodoId($this->id);
}
}
<?php
class TodoQuestion{
private int $id;
private string $question;
/**
* @param array<TodoQuestionValue> $values
*/
private array $values;
private TodoRepositoryInterface $repository;
public function __constructor(TodoRepositoryInterface $repository){
$this->repository = $repository;
}
public function getValues(){
$this->values = $this->repository->listValuesByQuestionId($this->id);
}
}
Now, I would like to get your opinions about how I could shape this structure by following the DDD rules.
Thank you.
回答1:
Let’s assume I have a TODO application and there are some questions in the TODO and some answers in each those questions.
You just need to translate this into code. The only entity here is the Todo. Make it the aggregate root and create a repository for it.
<?php
class Todo
{
private int $id;
/**
* @param array<TodoQuestion> $questions
*/
private array $questions;
public function getQuestions()
{
return $this->questions;
}
}
The question has answers. You can model that with 2 value objects: Question and Answer.
<?php
class TodoQuestion
{
private string $question;
private array $values;
/**
* @var TodoAnswer[]
*/
private array $answers;
public function getValues()
{
return $this->values;
}
public function getAnswers(): array
{
return $this->answers;
}
}
Your model should never depend on the repository. The repository task is to save the state of your aggregate and rebuild the same state when you query your aggregate.
interface TodoRepository {
public function save(Todo $todo): void;
public function todoOfId(TodoId $id): Todo;
}
You don't need more than this 2 methods. If you want to have the list of questions for one Todo you just get the Todo aggregate root and then call ->getQuestions()
. In your repository implementation you can decide to use the orm, write raw queries, serialize the aggregate and then save it... The possibilities are endless just make sure you keep your model decoupled from these infrastructure concerns.
来源:https://stackoverflow.com/questions/60541818/ddd-value-objects-and-entity-without-orm-mapping-in-php