В вашем вопросе отсутствует какой-то контекст, например, какой пользовательский сценарий приводит к этому событию и из какого состояния вы начинаете? Если бы вы писали тесты BDD для этого случая, как бы они выглядели? Знание этого очень поможет ответить на ваш вопрос.
То, как вы решаете проблему соотнесения книги с автором, зависит от предметной области. Сначала мы предполагаем, что для вашего домена имеет смысл иметь агрегат для автора и агрегат для книги, например, если бы я писал библиотечную систему, я сомневаюсь, что у меня был бы агрегат для авторов, поскольку меня не волнует автор без своей книги, меня волнуют книги.
Что касается отсутствия геттеров, стоит упомянуть, что у агрегированных корней нет геттеров из-за предпочтения скажи-не-спрашивай стиль ООП. Однако вы можете сказать одному AR сделать что-то, а затем, если вам нужно, что-то скажет другому AR. Отчасти важно то, что AR сообщает другим о себе, а не пишет код, в котором вы его спрашиваете, а затем передаете.
Наконец, я должен спросить, почему у вас нет идентификатора автора, когда вы добавляете книгу? Как тогда вообще узнать, кто автор? Я предполагаю, что вы могли бы просто сделать следующее (мой код предполагает, что вы используете свободный интерфейс для создания AR, но вы можете заменять фабрики, конструкторы, все, что вы используете):
CreateNew.Book()
.ForAuthor(command.AuthorId)
.WithContent(command.Content);
Теперь, возможно, сценарий таков, что вы добавляете книгу вместе с новым автором. Я бы обработал это как две отдельные команды (что может иметь больше смысла для вашего домена) или обработал бы команду следующим образом:
var author = CreateNew.Author()
.WithName(command.AuthorName);
var book = CreateNew.Book()
.ForAuthor(author.Id)
.WithContent(command.Content);
Возможно, проблема в том, что у вас нет получателя для совокупного корневого идентификатора, который я не считаю необходимым или обычным. Однако, если для вас важна инкапсуляция идентификатора или ваше событие BookAdded требует больше информации об авторе, чем может предоставить идентификатор, тогда вы можете сделать что-то вроде этого:
var author = CreateNew.Author()
.WithName(command.AuthorName);
var book = author.AddBook(command.Content);
// Adds a new book belonging to this Author
public Book AddBook(BookContent content) {
var book = CreateNew.Book()
.ForAuthor(this.Id)
.WithContent(command.Content);
}
Здесь мы говорим автору добавить книгу, после чего он создает совокупный корень для книги и передает его идентификатор книге. Затем у нас может быть событие BookAddedForAuthor, которое будет иметь идентификатор автора.
Однако у последнего есть недостатки: он создает команду, которая должна действовать через несколько агрегированных корней. Насколько это возможно, я бы попытался выяснить, почему первый пример вам не подходит.
Кроме того, я не могу не подчеркнуть, как реализация, которую вы ищете, продиктована контекстом вашей конкретной предметной области.
person
Chris Nicola
schedule
27.02.2011