在更多行业或自动化相关的应用程序(主要依赖于他们必须管理的外部组件)中,您经常会遇到这样的情况:域包含的模型不仅仅是真实问题的抽象,但也是在域外实际存在的东西的表示和指针。
例如,使用代表网络设备的此域实体:
public class NetworkDevice {
public IPAddress IpAddress { get; set; }
}
应用程序可能需要根据域内的表示来管理外部组件,而不仅仅是存储或验证此类实体或对实体更改采取措施。现在,DDD甚至适合这种情况吗?那些经理域名服务?
埃里克·埃文斯在其着名的蓝皮书中描述,域名服务需要是一个无状态模型,实现从 ubiquitos language 中获取的方法,以满足对该实体的请求,或者存储库本身无法处理。但是,如果服务需要有状态,该怎么办?一个简单示例:应用程序需要监视网络中已配置的 IP设备,以便通知域内其他应用程序有关状态事件的信息。如果IP设备在应用程序内部注册(例如存储在数据库中),则会通知“ping-service”并开始监视设备。
public class PingMonitor : IDisposable,
IHandle<DeviceRegisteredEvent>,
IHandle<DeviceRemovedEvent>
{
public List<NetworkDevice> _devices = new List<NetworkDevice>();
public void Handle(DeviceRegisteredEvent @event) {
_devices.Add(@event.Device);
}
public void Handle(DeviceRemovedEvent @event) {
_devices.Remove(@event.Device);
}
public void PingWorker() {
foreach(var device in _devices) {
var status = Ping(device.IpAddress);
if(status != statusBefore)
DomainEvents.Raise<DeviceStateEvent>(new DeviceStateEvent(device, status));
}
}
}
然后,其他组件可以处理这些状态事件,例如如果设备离线,请停止通过其他协议与设备通话。
现在,那些组件是什么?起初我认为它们是域服务,因为它们满足域的某些要求。但是,它们有状态以及不具体代表 ubiquitos language ( ping-service 的任务是 ping 域实体和报告它的状态,但 ping-service 未实现客户端允许ping设备的方法。
他们是应用服务吗?这些组件在DDD模式中的适用范围是什么?
答案 0 :(得分:2)
在DDD中,长时间运行的过程称为 Saga 。它通常使用域事件实现。
以下是该主题的一些介绍: http://abdullin.com/journal/2010/9/26/theory-of-cqrs-command-handlers-sagas-ars-and-event-subscrip.html/
答案 1 :(得分:1)
我曾经实现了类似的功能,希望它有所帮助:)
我们的组织拥有在线支付处理应用程序。一旦客户完成付款,在线支付提供商就会发送指示成功或失败的通知。发生网络故障时,通知可能永远不会到达我们的应用程序。因此,这里有不满的客户。因此需要一种自动检查机制。
应用程序运行器负责保持检查运行:
public class CheckingBatch {
private TransactionChecker transactionChecker;
public void run() {
List<Transaction> transactions = transactionsToBeChecked();
for (Transaction transaction : transactions) {
//publish events if the transaction needs check
doCheck(transaction, now); }
}
}
private List<Transaction> transactionsToBeChecked() {
return transactionRepository.findBy(transactionChecker
.aToBeCheckedSpec());
}
}
Annother应用程序服务侦听事件并进行实际检查:
public class CheckTransactionServiceImpl implements CheckTransactionService {
private TransactionChecker transactionChecker;
@Transactional
public void check(final TransactionNo transactionNo) {
Transaction transaction = transactionRepository.find(transactionNo);
CheckResult result = transactionChecker.check(transaction);
//handle check result
}
}
TransactionCheck是一种在线支付解决方案不可知的域名服务:
public interface TransactionChecker {
/**
*
* | data between online-payment provider and ours | txn STATUS | RESULT |<br>
* | consistent | CLOSED | VALID |<br>
* | inconsistent | CLOSED | INVALID |<br>
* others omitted
*/
CheckResult check(Transaction transaction);
/**
* returns txn specification to filter to be checked ones.
*/
ToBeCheckedSpecification aToBeCheckedSpec();
}
正如您所看到的,应用程序服务和域服务现在都是无状态的。
恕我直言,Ping是域服务(与TxnChecker相关),但监视器是一种应用程序服务(与CheckingBatch相关)。