我想我可能对域名/服务层分离感到困惑。
在我的应用程序中,域代码需要生成具有业务含义的系统范围的唯一标识符。这意味着它必须以独占访问权限访问存储。我可以直接在域代码中执行此操作,但我认为这有两个原因:
例如,请考虑以下事项:
class UnitOfWork
{
public OrderRepository TheOrderRepository { get; private set; }
public void Commit() { /* ... */ }
}
class UnitOfWorkFactory
{
UnitOfWork CreateNewUnitOfWork()
{
var sess = CreateNewSession();
var trans = CreateNewTransaction(session);
return new UnitOfWork
{
TheOrderRepository = new OrderRepository(sess, trans);
}
}
}
class OrderService // application service layer
{
public void ProcessOrder(ID id, Details details)
{
using (uow = UnitOfWorkFactory.CreateNewUnitOfWork())
{
Order order = TheOrderRepository.Load(id);
order.Process(details);
uow.TheOrderRepository.Update(order);
uow.Commit();
}
}
}
class Order // domain layer
{
public void Process(Details details)
{
// need to get a unique, business-related identifier here.
// Where do I get it from?
}
}
我能想到两个选择:
// Option 1 - get BusinessIdRepository from Service layer
class Order // domain layer
{
public void Process(Details details)
{
// bad, because other Orders will block in Process() until my Process()
// is done.
// also, I access the storage in my domain layer, which is a no-no (?)
var id = m_businessIdRepository.GetUniqueId(details);
}
}
和
// Option 2 - introduce a service. For this example, suppose the business ID is
// just an increasing counter
class BusinessIdBrokerService
{
int GetBusinessId(Details details)
{
int latestId;
using (uow = UnitOfWorkFactory.CreateNewUnitOfWork())
{
latestId = TheIdRepository.GetLatest(); // takes lock
latestId ++;
TheIdRepository.SetLatestId(latestId);
uow.Commit(); // lock is released
}
return latestId;
}
}
class Order // domain layer
{
public void Process(Details details)
{
// domain layer accessing the service layer. Is this bad?
var id = m_businessIdBroker.GetBusinessId(details);
}
}
现在,选项(1)有明显的缺点,但选项(2)有域层访问服务层。在我看到的所有图表中,这是一个很大的禁忌。
遵循Jimmy Bogard的术语(http://lostechies.com/jimmybogard/2008/08/21/services-in-domain-driven-design/),看起来我想要一个域服务(而不是应用服务) )此处,但此域服务将访问存储(不仅通过存储库:它将创建一个独立的会话+事务。)
我应该注意,选项(2)的缺点是,如果Order.Process中存在问题,则无法回滚ID生成,因为它已经被提交。在我的场景中我没有问题。我很浪费ID。
如果它有所不同,我正在使用NHibernate作为我的ORM。
你会推荐什么方法?
答案 0 :(得分:1)
要从订单中删除依赖关系到IdBroker,您可以注入OrderService中注入的IdBrokerService,并将新Id作为参数传递给Order.Process方法。
如果您对浪费id很好,那么生成新id的独立服务可能是您案例中的最佳解决方案。然后,您将此服务作为依赖项添加到获取ID的其他服务,并将它们传递给域对象。这样,您的域对象就可以避免任何外部交互。