领域驱动设计系列(三):事件驱动上

前言

今天讲一下事件驱动,这个不是领域驱动设计里的事件源(Event Source), 这个以后再讲,今天主要讲一下如何用事件来解耦,主要的原因是我们有个项目有个功能我觉得用事件的方式比较好,正好写篇博客,就不用专门给他们讲了。

解耦

说到解耦,我们很熟悉分层设计,比如上层依赖于抽象,不依赖于具体的实现。比如一个类使用另一个类,我们使用接口而不直接使用实现类。

1
2
3
4
5
public EquipmentService(IEmailService emailService, IEquipmentRepository equipmentRepository)
{
_emailService = emailService;
_equipmentRepository = equipmentRepository;
}

为何用事件?

SRP (单一职责)

比如我们一个会议室预定系统,我们的一个设备坏了。我们需要通知预定这个会议室的所有人。于是我们需要发邮件。

伪代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class EquipmentService
{
private readonly IEmailService _emailService;
private readonly IEquipmentRepository _equipmentRepository;

public EquipmentService(IEmailService emailService, IEquipmentRepository equipmentRepository)
{
_emailService = emailService;
_equipmentRepository = equipmentRepository;
}

public void SetEquipmentBroken(string Id)
{
var equipment = _equipmentRepository.GetById(Id);
equipment.DeActive();

_emailService.SendEmail();
}
}

但是,问题来了,如果后来我们要说,如果设备坏了,我们要更改可用库存的数量,这时候我们是不是要在这里修改代码而引入IInventoryService? 后来如果经理说设备坏了你们尽然不告诉我,你们要闹哪样?这个时候我们是不是要修改代码引入ISMSService.Info(Manager)? 即使我们不考虑OCP原则,不考虑单一职责,我们程序员也会哭,我就DeActive一个设备,你要我做这么多事,我哪里清楚所有的功能?我就骂过程序员,你做这个功能呢为什么没考虑全!!!漏掉了这么重要的功能。

而问题,程序员从来没考虑全过,因此我就想办法如何解决这个程序员不仔细的问题。

事件驱动

因为我熟悉iOS的开发,我就想到了iOS的Notification Center. 那我我DeActive一个设备,我就只DeActive这个设备,很SRP是不是? 但是别的地方如何拿到通知? 于是事件就自然的付出水面了。如果设备被DeActive了,程序就只需要喊一声,老子把设备DeActive了,你们要闹哪样你们自己看着办,代码如下。

1
2
3
4
5
6
7
8
public void SetEquipmentBroken(string Id)
{
var equipment = _equipmentRepository.GetById(Id);
equipment.DeActive();

EventBus.Publish(new EquipmentDeActivedEvent {Id = equipment.Id});

}

这样,通知会议室预定者的模块去通知,给老板发短信的模块就通知老板就OK了。

总结

这里我们先将事件驱动,下一篇展示如何实现同步的事件,以后转换为异步那也很容易,让多个接受者处理这个事件,接受者可以是动态的哦,以后老板娘也想知道的话,代码也不用改的亲,好,我先去写实现代码去!

领域驱动设计系列(三):事件驱动上

http://deshui.wang/2015/02/11/technologies-DDD-2015-2-11-eventdriven1/

Author

王德水

Posted on

2015-02-11

Updated on

2021-01-05

Licensed under

版权:本文版权归作者所有,转载需经作者同意。

Comments