今天我们来分析另一个开源的CQRS+ES项目:Equinox。该项目可以在github上下载并直接本地运行,项目地址:https://github.com/EduardoPires/EquinoxProject,该项目是基于 .net core 2.2的,开发语言、编码方式比Diary.CQRS更加新潮(CQRS+ES项目解析-Diary.CQRS),也更符合我们现在的开发习惯。

项目概览

首先通过github获取到项目源代码,打开项目文件,你会看到如下分层:

  • Presentation:展示层,UI在该层实现
  • Services:WebApi在该层实现,同样隶属于UI
  • Application:应用程序服务层,提供了对Domain层接口的封装,注重数据交换,DTO对象在该层定义
  • Domain:领域层,项目的核心部分,领域对象、领域服务在该层实现
  • Infra:基础设施层,项目的公共部分(数据访问)、切片(身份认证、消息发布、依赖注入)部分在该层实现

通过项目分层,我们已经对该项目有了一个大致的轮廓,当从Presentation、Services层接收到来自客户端的请求后,将会调用Application层的应用程序服务,应用程序服务将数据进行封装和转换,然后交给Domain层进行处理,Domain层则调用Infra相关的方法完成持久化、消息发布等功能。

Domain层

Domain层是Equinox项目的核心部分,Entity/ValueObject、Repository、UoW、Command、Event、EventStore等均在该层进行定义,我们来看一下。

Entity对象

实体对象,定义如下:

public abstract class Entity
{
public Guid Id { get; protected set; } public override bool Equals(object obj)
{
//......
} public static bool operator ==(Entity a, Entity b)
{
//......
} public static bool operator !=(Entity a, Entity b)
{
//......
} public override int GetHashCode()
{
//......
} public override string ToString()
{
//......
}
}

每一个实体对象都要具备ID属性,用来标记唯一性;重写了Equals方法、定义了==、!=操作符,用于两个对象的比较;重写了ToString方法、GetHashCode方法。

ValueObject

值对象,与实体对象进行区分,值对象没有Id属性。定义如下:

public abstract class ValueObject<T> where T : ValueObject<T>
{
public override bool Equals(object obj)
{
//......
} protected abstract bool EqualsCore(T other); public override int GetHashCode()
{
//......
} protected abstract int GetHashCodeCore(); public static bool operator ==(ValueObject<T> a, ValueObject<T> b)
{
//......
} public static bool operator !=(ValueObject<T> a, ValueObject<T> b)
{
//......
}
}

与Entity相似,定义了一些基本的操作方法。

Repository

数据仓储,用来进行数据访问,定义如下:

public interface IRepository<TEntity> : IDisposable where TEntity : class
{
void Add(TEntity obj);
TEntity GetById(Guid id);
IQueryable<TEntity> GetAll();
void Update(TEntity obj);
void Remove(Guid id);
int SaveChanges();
}

定义了对数据的基本操作,添加、更新、删除、查询等方法

UoW

工作单元,定义如下:

public interface IUnitOfWork : IDisposable
{
bool Commit();
}

定义了Commit方法,当业务逻辑执行完成用,用于数据库事物

Command/CommandHandler 和 Event/EventHandler

CQRS和ES的核心部分,Command、Event被定义为消息,拥有共同的基类Message,分别定义如下:

Command:

public abstract class Command : Message
{
public DateTime Timestamp { get; private set; }
public ValidationResult ValidationResult { get; set; } protected Command()
{
Timestamp = DateTime.Now;
} public abstract bool IsValid();
}

Event:

public abstract class Event : Message, INotification
{
public DateTime Timestamp { get; private set; } protected Event()
{
Timestamp = DateTime.Now;
}
}

与Command、Event对应的处理程序用来处理相应的业务逻辑,此处不在介绍。感兴趣的朋友可以参照上篇文章进行了解。

EventStore

EventStore也是ES的核心内容,负责对事件的存储、提取工作。在Equinox项目中,EventStore的定义如下:

public interface IEventStore
{
void Save<T>(T theEvent) where T : Event;
}

额?只有一个Save方法,这不符合逻辑,只能进行事件的存储,而没有事件的查询。通过查阅项目的其它代码,我发现事件的查询则是通过EventStoreRepository来实现的,这一点不太符合我们的开放封闭原则和模块化思想。作者可能是想着对事件的操作也遵循CQRS模式吗?这就未可知了。

Bus

消息通信,Equinox项目中使用MediatR实现的基于内存的消息通信。定义如下:

public interface IMediatorHandler
{
Task SendCommand<T>(T command) where T : Command;
Task RaiseEvent<T>(T @event) where T : Event;
}

Infra层

基础设施层里面,定义了Domain层接口的实现,例如Data中实现了仓储、工作单元,Bus中实现了InMemoryBus等。由于都是非常简单的实现,不再展开介绍。

Application层

应用程序服务层有两个作用,封装底层(Infra、Domain)的操作,对UI层(Presentation、Services)数据进行转换,它是UI层与Domain层的桥梁。此处不再展开介绍。

UI层

Equinox项目中,UI层由两部分组成,分别是Presentation和Services,其中展示层提供了界面操作的功能,Services层提供了接口访问的功能,这两个项目采用MVC和WebApi技术,不再展开介绍。

Equinox项目总结

通过分析Equinox项目的结构和代码,我们可以发现,这个项目并不是很完善,作者所说的不要用在生产环境是实话。

在这个项目中,对于ES的实现并不是很优雅,首先EventStore的操作,未提供查询事件的接口,从而导致了需要通过Repository来获取Event,破坏了EventStore的完整性;其次该项目没有完成事件重放功能,我们只能通过事件查看到数据的变更,但是无法通过重放来获取项目的某个时段的状态的功能;最后,Equinox项目未实现读写分离,对于数据的查询和增加更新等操作都混合在一个Repository中,不利于我们进行读写分离。

以上请大家参考。

CQRS+ES项目解析-Equinox的更多相关文章

  1. CQRS+ES项目解析-Diary.CQRS

    在<当我们在讨论CQRS时,我们在讨论些神马>中,我们讨论了当使用CQRS的过程中,需要关心的一些问题.其中与CQRS关联最为紧密的模式莫过于Event Sourcing了,CQRS与ES ...

  2. CQRS\ES架构介绍

    大家好,我叫汤雪华.我平时工作使用Java,业余时间喜欢用C#做点开源项目,如ENode, EQueue.我个人对DDD领域驱动设计.CQRS架构.事件溯源(Event Sourcing,简称ES). ...

  3. Android开发周报:Flyme OS开源、经典开源项目解析

    Android开发周报:Flyme OS开源.经典开源项目解析 新闻 <魅族Flyme OS源码上线Github> :近日魅族正式发布了MX5,并且在发布会上,魅族还宣布Flyme OS开 ...

  4. 用CQRS+ES实现DDD

    用CQRS+ES实现DDD 这篇文章应该算是对前三篇的一个补充,在写之前说个题外话,有园友评论这是在用三层架构在写DDD,我的个人理解DDD是一种设计思想,跟具体用什么架构应该没有什么关系,DDD也需 ...

  5. renren-fast开源项目解析日志—1、项目的部署

    renren_fast项目解析日志 一.环境搭建 1.后端部署 (1)下载源码 按照步骤,从码云上down了fast,zip的(引maven项目)项目包. (2)安装lombok插件 安装lombok ...

  6. CQRS/ES框架调研

    1.Enode一个C#写的CQRS/ES框架,由汤雪华设计及实现,github上有相关源码,其个人博客上有详细的孵化.设计思路.版本迭代及最新的完善: 2.axon framwork,java编写,网 ...

  7. 分享一个CQRS/ES架构中基于写文件的EventStore的设计思路

    最近打算用C#实现一个基于文件的EventStore. 什么是EventStore 关于什么是EventStore,如果还不清楚的朋友可以去了解下CQRS/Event Sourcing这种架构,我博客 ...

  8. 一款不错的 Go Server/API boilerplate,使用 K8S+DDD+CQRS+ES+gRPC 最佳实践构建

    Golang API Starter Kit 该项目的主要目的是使用最佳实践.DDD.CQRS.ES.gRPC 提供样板项目设置. 为开发和生产环境提供 kubernetes 配置.允许与反映生产的 ...

  9. Cocos2dx.3x入门三部曲-Hello Game项目解析(三)

    一.前提: 完成Hello Game项目的创建编译. 具体参考:Cocos2dx.3x_Hello Game项目创建篇 二.本篇目标: l  分析proj.win32工程的主要构成 l  分析proj ...

随机推荐

  1. 详解 PHP 中的三大经典模式

    单例模式 单例模式的含义: 作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例.它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用. 单例模式 ...

  2. 扛把子组2018092609-2 选题 Scrum立会报告+燃尽图 04

    此作业的要求参见[https://edu.cnblogs.com/campus/nenu/2019fall/homework/8682] 一.小组情况组长:迟俊文组员:宋晓丽 梁梦瑶 韩昊 刘信鹏队名 ...

  3. 几行代码轻松搞定python的sqlite3的存取

    很简单: 存数据: 1.加载sqlite3驱动(只需一行代码) 2.用驱动执行查询语句(只需一行代码) 取数据: 1.加载sqlite3驱动(只需一行代码) 2.用驱动执行查询语句(只需一行代码) 乍 ...

  4. tensorflow多层CNN代码分析

    tf,reshape(tensor,shape,name=None) #其中shape为一个列表形式,特殊的一点是列表中可以存在-1.-1代表的含义是不用我们自己#指定这一维的大小,函数会自动计算,但 ...

  5. IIS部署.net core网站

    1 安装   Windows8.1-KB2999226-x64 2 安装 DotNetCore.1.0.4_1.1.1-WindowsHosting http://download.microsoft ...

  6. Linux下用Docker部署接口安全的运行环境

    背景:MySQL数据库运行在宿主机上(Linux) 需求:Redis.服务.页面分别运行在独立的docker中,并处于同一网络,容器内部重要目录要挂载在物理目录,保证数据安全 方法: 一.设置网络环境 ...

  7. SpringMVC参数绑定学习总结【前后端数据参数传递】

    目录 1. 绑定机制 2. 支持的数据类型 3. 参数请求中文乱码解决 4.自定义类型转换器 5.最后参数绑定学习小结 SpringMVC作为Controller层(等价servlet和struts中 ...

  8. Linux基础命令小技巧

    总结 CentOS(Community Enterprise Operating System,中文意思是:社区企业操作系统)是Linux发行版之一,它是来自于Red Hat Enterprise L ...

  9. 一图读懂基于鲲鹏处理器的全栈混合云华为云Stack6.5

    [摘要] 够料的全栈混合云干货信息,速戳! 近日,在2019华为云城市峰会广州站上,华为云发布基于鲲鹏处理器的全栈混合云解决方案HCS 6.5.x86+鲲鹏,双驱动开启云上新架构;云上+本地,双平台无 ...

  10. 华为eNSP路由交换-静态路由

    静态路由 一. 静态路由及默认路由基本配置 1.1实验内容 在由三台路由器所组成的简单网络中,R1和R3各连着一台PC,现在要求能够实现PC-1和PC-2之间的通信.本实验将通过配置基本的静态路由和默 ...