Tôi có một kịch bản chung là tôi đang tìm kiếm một số hướng dẫn từ những người có kinh nghiệm về DDD và Mô hình miền nói chung.Cách tránh các mô hình miền thiếu máu hoặc khi di chuyển các phương thức từ các thực thể sang các dịch vụ
Giả sử tôi bắt đầu xây dựng một công cụ blog và yêu cầu đầu tiên là sau khi Bài viết được đăng, người dùng có thể bắt đầu đăng Nhận xét lên đó. Điều này bắt đầu tốt, và dẫn đến việc thiết kế sau:
public class Article
{
public int Id { get; set; }
public void AddComment(Comment comment)
{
// Add Comment
}
}
My MVC điều khiển được thiết kế như thế này:
public class ArticleController
{
private readonly IRepository _repository;
public ArticleController(IRepository repository)
{
_repository = repository;
}
public void AddComment(int articleId, Comment comment)
{
var article = _repository.Get<Article>(articleId);
article.AddComment(comment);
_repository.Save(article);
return RedirectToAction("Index");
}
}
Bây giờ tất cả mọi thứ hoạt động tốt, và nó đáp ứng các yêu cầu. Lặp lại tiếp theo, chúng tôi nhận được yêu cầu rằng mỗi khi nhận xét được đăng, tác giả blog sẽ nhận được email thông báo cho anh ấy.
Tại thời điểm này, tôi có 2 lựa chọn mà tôi có thể nghĩ đến. 1) Sửa đổi Điều để yêu cầu một IEmailService (trong ctor?) Hoặc nhận một EmailService từ tham chiếu tĩnh đến vùng chứa DI của tôi
1a) Dường như khá xấu xí. Tôi tin rằng nó phá vỡ một số quy tắc mô hình tên miền mà các thực thể của tôi nhận thức được các dịch vụ?
public class Article
{
private readonly IEmailService _emailService;
public Article(IEmailService emailService)
{
_emailService = emailService;
}
public void AddComment(Comment comment)
{
// Add Comment
// Email admin
_emailService.SendEmail(App.Config.AdminEmail, "New comment posted!");
}
}
1b) Cũng có vẻ xấu xí, bây giờ tôi yêu cầu vùng chứa DI được định cấu hình được truy cập tĩnh.
public class Article
{
public void AddComment(Comment comment)
{
// Add Comment
// Email admin
var emailService = App.DIContainer.Resolve<IEmailService>();
emailService.SendEmail(App.Config.AdminEmail, "New comment posted!");
}
}
2) Tạo IArticleService và di chuyển phương thức AddComment() vào dịch vụ này thay vì trên chính Đối tượng bài viết.
Giải pháp này sạch hơn Tôi tin, nhưng việc thêm nhận xét giờ đây ít bị phát hiện hơn và yêu cầu ArticleService thực hiện công việc. Có vẻ như AddComment nên thuộc về chính class Article.
public class ArticleService
{
private readonly IEmailService _emailService;
public ArticleService(IEmailService emailService)
{
_emailService = emailService;
}
public void AddComment(Article article, Comment comment)
{
// Add comment
// Email admin
_emailService.SendEmail(App.Config.AdminEmail, "New comment posted!");
}
}
public class ArticleController
{
private readonly IRepository _repository;
private readonly IArticleService _articleService;
public ArticleController(IRepository repository, IArticleService articleService)
{
_repository = repository;
_articleService = articleService;
}
public void AddComment(int articleId, Comment comment)
{
var article = _repository.Get<Article>(articleId);
_articleService.AddComment(article, comment);
_repository.Save(article);
return RedirectToAction("Index");
}
}
Vì vậy, về cơ bản tôi tìm kiếm lời khuyên từ những người có nhiều kinh nghiệm trong mô hình miền. Nếu tôi thiếu một giải pháp rõ ràng hơn, vui lòng cho tôi biết :)
Tôi thường không thích cả hai giải pháp một cách trung thực, vì tùy chọn Dịch vụ ít phát hiện hơn. Tôi không còn có thể thêm một bình luận vào một thể hiện của một bài báo mà không có một ArticleService có sẵn. Nó cũng cảm thấy ít tự nhiên hơn, vì AddComment có vẻ như là một phương pháp rõ ràng như vậy trên loại bài viết.
Dù sao thì tôi cũng mong được đọc đầu vào. Cảm ơn trước.
1 cho giải pháp # 2 – JuanZe
1 cho một câu hỏi rõ ràng – Rippo