我正在构建一个图书馆应用程序。假设我们有一个要求,让图书馆中的注册人员在某个默认时间段(4 周)内借书。
我开始使用以下代码调用 AggregateRoot 对我的域进行建模Loan
:
public class Loan : AggregateRoot<long>
{
public static int DefaultLoanPeriodInDays = 30;
private readonly long _bookId;
private readonly long _userId;
private readonly DateTime _endDate;
private bool _active;
private Book _book;
private RegisteredLibraryUser _user;
public Book Book => _book;
public RegisteredLibraryUser User => _user;
public DateTime EndDate => _endDate;
public bool Active => _active;
private Loan(long bookId, long userId, DateTime endDate)
{
_bookId = bookId;
_userId = userId;
_endDate = endDate;
_active = true;
}
public static Loan Create(long bookId, long userId)
{
var endDate = DateTime.UtcNow.AddDays(DefaultLoanPeriodInDays);
var loan = new Loan(bookId, userId, endDate);
loan.Book.Borrow();
loan.AddDomainEvent(new LoanCreatedEvent(bookId, userId, endDate));
return loan;
}
public void EndLoan()
{
if (!Active)
throw new LoanNotActiveException(Id);
_active = false;
_book.Return();
AddDomainEvent(new LoanFinishedEvent(Id));
}
}
我的Book
实体看起来像这样:
public class Book : Entity<long>
{
private BookInformation _bookInformation;
private bool _inStock;
public BookInformation BookInformation => _bookInformation;
public bool InStock => _inStock;
private Book(BookInformation bookInformation)
{
_bookInformation = bookInformation;
_inStock = true;
}
public static Book Create(string title, string author, string subject, string isbn)
{
var bookInformation = new BookInformation(title, author, subject, isbn);
var book = new Book(bookInformation);
book.AddDomainEvent(new BookCreatedEvent(bookInformation));
return book;
}
public void Borrow()
{
if (!InStock)
throw new BookAlreadyBorrowedException();
_inStock = false;
AddDomainEvent(new BookBorrowedEvent(Id));
}
public void Return()
{
if (InStock)
throw new BookNotBorrowedException(Id);
_inStock = true;
AddDomainEvent(new BookReturnedBackEvent(Id, DateTime.UtcNow));
}
}
如您所见,我正在使用静态工厂方法来创建我的 Loan 聚合根,其中我传递了借书的身份和将要借书的用户身份。我应该在这里传递对这些对象(书籍和用户)的引用而不是 id 吗?哪种方法更好?如您所见,我的 Book 实体也有一个属性,它指示一本书的可用性(InStock
属性)。我是否应该在下一个用例中更新此属性,例如在 的处理程序中LoadCreatedEvent
?还是应该在我的 AggregateRoot 中更新它?如果它应该在我的聚合中更新,我应该传递整个书籍参考,而不仅仅是一个 ID 以便能够调用它的方法_book.Borrow()
。
我被困在这一点上,因为我想用 DDD 方法做得非常正确。还是我从错误的角度开始做,我错过了一些东西或以错误的方式思考?