我有一个场景正在尝试重构为 DDD。我有一个 Batch,它是 BatchEntries 的聚合和列表。创建 Batch 并添加 BatchEntries 后,将向该批次中的个人发送一条 SMS,并且该批次的状态从运行变为已发布。
关于如何使设计更好的任何想法?该域有两个聚合 Batch 和 BatchEntry,其中 Batch 是聚合根。
代码看起来像这样
public class Batch : EntityBase, IValidatableObject
{
public int BatchNumber { get; set; }
public string Description { get; set; }
public decimal TotalValue { get; set; }
public bool SMSAlert { get; set; }
public int Status { get; set; }
private HashSet<BatchEntry> _batchEntries;
public virtual ICollection<BatchEntry> BatchEntries
{
get{
if (_batchEntries == null){
_batchEntries = new HashSet<BatchEntry>();
}
return _batchEntries;
}
private set {
_batchEntries = new HashSet<BatchEntry>(value);
}
}
public static Batch Create(string description, decimal totalValue, bool smsAlert)
{
var batch = new Batch();
batch.GenerateNewIdentity();
batch.Description = description;
batch.TotalValue = totalValue;
batch.SMSAlert = smsAlert;
return batch;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
//
}
}
public interface IBatchRepository : IRepository<Batch>
{
int NextBatchNumber();
}
public class BatchEntry : EntityBase, IValidatableObject
{
public Guid BatchId { get; set; }
public virtual Batch Batch { get; private set; }
public decimal Amount { get; set; }
public Guid CustomerAccountId { get; set; }
public virtual CustomerAccount CustomerAccount { get; private set; }
public static BatchEntry Create(Guid batchId, Guid customerAccountId, decimal amount)
{
var batchEntry = new BatchEntry();
batchEntry.GenerateNewIdentity();
batchEntry.BatchId = batchId;
batchEntry.CustomerAccountId = customerAccountId;
batchEntry.Amount = amount;
return batchEntry;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
//
}
}
public interface IBatchEntryRepository : IRepository<BatchEntry>{}
域和域服务通过应用程序服务公开。应用服务中的代码如下:
//Application Services Code
public class BatchApplicationService : IBatchApplicationService
{
private readonly IBatchRepository _batchRepository;
private readonly IBatchEntryRepository _batchEntryRepository;
public BatchAppService(IBatchRepository batchRepository, IBatchEntryRepository batchEntryRepository)
{
if (batchRepository == null) throw new ArgumentNullException("batchRepository");
if (batchEntryRepository == null) throw new ArgumentNullException("batchEntryRepository");
_batchRepository = batchRepository;
_batchEntryRepository = batchEntryRepository;
}
public BatchDTO AddNewBatch(BatchDto batchDto)
{
if (batchDto != null)
{
var batch = Batch.Create(batchDto.Description, batchDto.TotalValue, batchDto.SMSAlert);
batch.BatchNumber = _batchRepository.NextBatchNumber();
batch.Status = (int)BatchStatus.Running;
SaveBatch(batch);
return batch.Map<BatchDto>();
}
else
{
//
}
}
public bool UpdateBatch(BatchDto batchDto)
{
if (batchDto == null || batchDto.Id == Guid.Empty)
{
//
}
var persisted = _batchRepository.Get(batchDto.Id);
if (persisted != null)
{
var result = false;
var current = Batch.Create(batchDto.Description, batchDto.TotalValue, batchDto.SMSAlert);
current.ChangeCurrentIdentity(persisted.Id);
current.BatchNumber = persisted.BatchNumber;
current.Status = persisted.Status;
_batchRepository.Merge(persisted, current);
_batchRepository.UnitOfWork.Commit();
if (persisted.BatchEntries.Count != 0){
persisted.BatchEntries.ToList().ForEach(x => _batchEntryRepository.Remove(x));
_batchEntryRepository.UnitOfWork.Commit();
}
if (batchDto.BatchEntries != null && batchDto.BatchEntries.Any())
{
List<BatchEntry> batchEntries = new List<BatchEntry>();
int counter = default(int);
batchDTO.BatchEntries.ToList().ForEach(x =>
{
var batchEntry = BatchEntry.Create(persisted.Id, x.CustomerAccountId, x.Amount);
batchEntries.Add(batchEntry);
});
}
else result = true;
return result;
}
else
{
//
}
}
public bool MarkBatchAsPosted(BatchDto batchDto, int authStatus)
{
var result = false;
if (batchDto == null || batchDto.Id == Guid.Empty)
{
//
}
var persisted = _batchRepository.Get(batchDto.Id);
if (persisted != null)
{
var current = Batch.Create(batchDto.Description, batchDto.TotalValue, batchDto.SMSAlert);
current.ChangeCurrentIdentity(persisted.Id);
current.BatchNumber = persisted.BatchNumber;
current.Status = authStatus;
_batchRepository.Merge(persisted, current);
_batchRepository.UnitOfWork.Commit();
result = true;
}
else
{
//
}
return result;
}
private void SaveBatch(Batch batch)
{
var validator = EntityValidatorFactory.CreateValidator();
if (validator.IsValid<Batch>(batch))
{
_batchRepository.Add(batch);
_batchRepository.UnitOfWork.Commit();
}
else throw new ApplicationValidationErrorsException(validator.GetInvalidMessages(batch));
}
}
问题:
- BatchStatus 即 Running、Posted 应该分配在哪里?
- MarkBatchAsPosted 方法是否应该定义为批处理实体中的方法?
- 对于领域驱动设计,如何最好地重新设计?