问题
Say I'm creating a repository to store digital E-Books as shown in the interface below. This repository will store the actual text of the book, as well as the metadata that identifies the book (title, author, publisher, ISBN etc..).
public interface IBookRepository
{
void AddBook(Book newBook);
void DeleteBook(int bookId);
void UpdateBook(Book updatedBook);
Book GetBook(int bookID)
}
public class Book
{
public int BookId {get; set;}
public string Title {get; set;}
public string Author {get; set;}
public IList<Page> Contents {get; set}
}
public class Page
{
public int PageNumber {get; set;}
public string PageContent {get; set;}
}
In most cases I would not want to retrieve the entire text for the book, as that would be rather expensive. In most cases all I care about is the metadata, for example I may simply want to create a list of books. So would it be acceptable in regards to DDD to also allow an IBookRepository
to have methods that return BookSummary
objects? Book summary objects would include the metadata but not the actual contents of the book.
What about having an UpdateBook(BookSummary book)
method? Say I want to update the Book.Rating
property, but don't need/want to read the entire contents of the book from the repository to do this.
public interface IBookRepository
{
//Full Book Methods
void AddBook(Book newBook);
void DeleteBook(int bookId);
void UpdateBook(Book updatedBook);
Book GetBook(int bookID)
//BookSummary Methods
BookSummary GetBookSummary(int bookID)
IEnumerable<BookSummary> GetBooksByAuthor(string authorName);
IEnumerable<BookSummary> GetBooksByGenre(int genreId);
void UpdateBook(BookSummary bookSummary);
}
public class BookSummary
{
public int BookId {get; set;}
public string Title {get; set;}
public string Author {get; set;}
public int PageCount {get; set;}
}
Note: I know using an ORM with Lazy Loading would also be a solution to this, but I'd like to design my repositories with out the assuming that lazy loading will be used
回答1:
If there is a use case in your Domain that would support it why don't just create additional entity BookSummary with its own Repository that will do the job? It does not really matter where BookSummary is persisted - that it not relevant for the Domain.
It is important to derive Entities from the Domain using Ubiquitous language and not to look at the database structure.
public interface IBookRepository
{
//Full Book Methods
void Add(Book Book);
void Delete(Book Book);
Book findById(int bookID)
}
public interface IBookSummaryRepository
{
//Full Book Summary Methods
void Add(BookSummary BookSum);
void Delete(BookSummary BookSum);
Book findById(int bookSummaryID)
}
If you Repository has methods update() or store() it is more likely DAO than repository by DDD: http://codebetter.com/iancooper/2011/04/12/repository-saveupdate-is-a-smell/
回答2:
In DDD repository should work only with aggregate root. In your case, I suppose, BookSummary is just an entity inside of Book aggregate (of course, more accurate analysis is needed here), so should get Book via BookRepository and then traverse to BookSummary from aggregate root using lazy loading. Otherwise, you are not applying Domain Driven Design here
回答3:
This is an old question, however there is no accepted answer so I will answer for the benefit of people landing here from Google. I run into the issue all the time as we have many summary screens that show partial information and /or information compiled from multiple entities. What I do is use separate read models as suggested by @xelibrion in the comments of his answer. I do not employ full CQRS, just simple read models with query methods only. So your BookRepository remains like so:
public interface IBookRepository
{
void AddBook(Book newBook);
void DeleteBook(int bookId);
void UpdateBook(Book updatedBook);
Book GetBook(int bookID)
}
And your BookSummary read model and its methods look like this:
public class BookSummary
{
public int BookId {get; set;}
public string Title {get; set;}
public string Author {get; set;}
public int PageCount {get; set;}
}
public interface IBookSummaryQueries
{
BookSummary GetBookSummary(int bookID)
IEnumerable<BookSummary> GetBooksByAuthor(string authorName);
IEnumerable<BookSummary> GetBooksByGenre(int genreId);
}
Note, there are no methods to update Book here, just querying
来源:https://stackoverflow.com/questions/6299655/is-it-ok-for-a-ddd-repository-work-with-summary-objects-in-addtion-to-real-obj