Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 长时间运行的、有状态的&x27;服务';适合DDD吗?_C#_Design Patterns_Domain Driven Design_Cqrs_Onion Architecture - Fatal编程技术网

C# 长时间运行的、有状态的&x27;服务';适合DDD吗?

C# 长时间运行的、有状态的&x27;服务';适合DDD吗?,c#,design-patterns,domain-driven-design,cqrs,onion-architecture,C#,Design Patterns,Domain Driven Design,Cqrs,Onion Architecture,在更多与工业或自动化相关的应用程序中(这些应用程序主要依赖于它们必须管理的外部组件),您通常会遇到这样的情况:域包含的模型不仅仅是从实际问题中抽象出来的,但也包括对物理上存在于域之外的事物的表示和指针 例如,以表示网络设备的域实体为例: public class NetworkDevice { public IPAddress IpAddress { get; set; } } 应用程序可能需要基于域内的表示来管理外部组件,而不仅仅是存储或验证这些实体或在实体更改时采取操作。现在,DDD

在更多与工业或自动化相关的应用程序中(这些应用程序主要依赖于它们必须管理的外部组件),您通常会遇到这样的情况:域包含的模型不仅仅是从实际问题中抽象出来的,但也包括对物理上存在于域之外的事物的表示和指针

例如,以表示网络设备的域实体为例:

public class NetworkDevice {
   public IPAddress IpAddress { get; set; }
}
应用程序可能需要基于域内的表示来管理外部组件,而不仅仅是存储或验证这些实体或在实体更改时采取操作。现在,DDD是否适用于此类情况?那些是管理者域服务吗

Eric Evans在其著名的蓝皮书中描述,域服务需要是一个无状态的模型,实现从泛素语言获取的方法,以完成实体或存储库本身无法处理的请求。但是如果一个服务需要有状态呢

一个简单的例子:应用程序需要监视网络中已配置的IP设备,以便将状态事件通知域中的其他应用程序。如果IP设备在应用程序中注册(例如存储在数据库中),则“ping服务”会收到通知并开始监视该设备

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));
        }
    }

}
公共类PingMonitor:IDisposable,
我处理,
我处理
{
公共列表_设备=新列表();
公共无效句柄(DeviceRegisteredEvent@event){
_添加(@event.Device);
}
公共无效句柄(DeviceMoveDevent@event){
_删除(@event.Device);
}
公职人员(){
foreach(var设备在_设备中){
var状态=Ping(设备.IpAddress);
如果(状态!=状态之前)
DomainEvents.Raise(新设备状态事件(设备、状态));
}
}
}
然后,其他组件可以处理这些状态事件,例如,如果设备脱机,则停止通过其他协议与设备通话

现在,这些组件是什么?起初我认为它们是域服务,因为它们服务于域的特定需求。但是,它们是有状态的,并且不具体代表泛素语言(ping服务的任务是对域实体进行ping,并报告其状态,但是ping服务没有实现客户端允许对设备进行ping的方法)


它们是应用服务吗?这些组件在DDD模式中的位置如何?

我曾经实现过类似的功能,希望它能有所帮助:)

我们的组织拥有一个在线支付处理应用程序。一旦客户完成支付,在线支付提供商将向use发送一条通知,指示成功或失败。有时发生网络故障时,通知可能永远不会到达我们的应用程序。因此,不满的顾客来了。因此,需要一种自动检查机制

应用程序运行者负责保持检查运行:

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());
    }
}
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();
}
公共接口事务检查器{
/**
* 
*|在线支付提供商与我们之间的数据| txn状态|结果|
*|一致|关闭|有效|
*|不一致|关闭|无效|
*其他遗漏 */ 检查结果检查(交易); /** *将txn规范返回到要检查的过滤器。 */ TobecheckedSpec()的规范; }
如您所见,应用程序服务和域服务现在都是无状态的


总之,Ping是一种域服务(与TxnChecker相关),但监视器是一种应用程序服务(与CheckingBatch相关)。

在DDD中,长时间运行的过程称为Saga。它通常使用域事件来实现

以下是对该主题的一些介绍:

我不明白为什么PingMonitor是有状态的。它保持什么状态?@Hippoom PingMonitor存储并监视在整个应用程序生命周期内在应用程序内注册的所有网络设备,因此在单实例生命周期范围内运行。这是一个很好的答案,实际上解决了我在应用程序中遇到的一些其他问题(域/服务层混合)。非常感谢@马可:谢谢,我同意你的看法。但此应用程序是在我了解CQR之前构建的:-(.我认为它对没有CQRS块支持的应用程序仍然有用。@Hippoom,sagas与CQRS没有直接关系,它们更多的是在事件SOA领域。sagas有一个特定的用途,所以从防御性角度来说,您的代码可以完成这项工作,我只想指出sagas应该是与ddd/event SOA一起使用的正确模式。
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();
}