#aggregate #event-sourcing #cqrs #ddd #pattern #architecture

eventmill_derive

eventmill crate 的一些特质提供 derive 宏的方便实现

3 个版本 (重大更新)

0.3.0 2020年5月17日
0.2.0 2020年5月16日
0.1.0 2020年5月10日

#36 in #ddd


用于 eventmill

MIT/Apache

20KB
253

eventmill-derive  

Latest Release Documentation License

为方便使用 eventmill crate 提供derive宏

您可以通过两种方式引入宏。推荐的方式是使用主crate的 derive 功能

[dependencies]
eventmill = { version = "0.3", features = ["derive"] }

或替代方式

[dependencies]
eventmill = "0.3"
eventmill_derive = "0.3"

以下示例假设您使用 eventmill crate 的 derive 功能推荐方式引入宏。

#[derive(EventType)]

#[derive(EventType)] 宏为您的事件实现 EventType 特质。事件可以是 structenum。我们可以通过使用可选属性 event_typeevent_type_versionevent_source 来配置生成的实现。

以下是一些示例

使用 struct 实现事件并指定所有可用属性。

use eventmill::EventType;

#[derive(EventType, Debug)]
#[event_type_version("V2")]
#[event_source("https://github.com/innoave/eventmill/examples/turtle")]
#[event_type("turtle-turned")]
pub struct TurtleTurned {
    angle: f32,
}

fn main() {
    let turtle = TurtleTurned { angle: 0.42 };

    assert_eq!(turtle.event_type_version(), "V2");
    assert_eq!(
        turtle.event_source(),
        "https://github.com/innoave/eventmill/examples/turtle"
    );
    assert_eq!(turtle.event_type(), "turtle-turned");
}

使用 enum 实现事件并指定所有可用属性。

use eventmill::EventType;

#[derive(EventType, Debug)]
#[event_type_version("V2")]
#[event_source("https://github.com/innoave/eventmill/examples/turtle")]
pub enum Turtle {
    #[event_type("turtle-turned")]
    Turned(f32),
    #[event_type("turtle-moved")]
    Moved { x: i32, y: i32 },
    #[event_type("turtle-stopped")]
    Stopped,
}

fn main() {
    let turtle = Turtle::Stopped;

    assert_eq!(turtle.event_type_version(), "V2");
    assert_eq!(
        turtle.event_source(),
        "https://github.com/innoave/eventmill/examples/turtle"
    );
    assert_eq!(turtle.event_type(), "turtle-stopped");

    let turtle = Turtle::Turned(0.42);
    assert_eq!(turtle.event_type(), "turtle-turned");

    let turtle = Turtle::Moved { x: 4, y: 2 };
    assert_eq!(turtle.event_type(), "turtle-moved");
}

如果我们省略了任何或所有属性,宏将使用默认值。注意 event_type() 函数返回的默认名称。

use eventmill::EventType;

#[derive(EventType, Debug)]
pub enum Turtle {
    Turned(f32),
    Moved { x: i32, y: i32 },
    Stopped,
}

fn main() { 
    let turtle = Turtle::Turned(0.42);
    assert_eq!(turtle.event_type(), "Turtle::Turned");
    
    let turtle = Turtle::Moved { x: 4, y: 2 };
    assert_eq!(turtle.event_type(), "Turtle::Moved");
    
    let turtle = Turtle::Stopped;
    assert_eq!(turtle.event_type(), "Turtle::Stopped");
}

我们可以使用任何评估为 &str 的表达式作为属性的值。例如,使用 const 定义 event_source 属性。

use eventmill::EventType;

const EVENT_NAMESPACE: &str = "https://github.com/innoave/eventmill/examples/turtle";

#[derive(EventType, Debug)]
#[event_source(EVENT_NAMESPACE)]
pub struct TurtleTurned {
    angle: f32,
}

fn main() {
    let turtle = TurtleTurned { angle: 0.42 };

    assert_eq!(turtle.event_type_version(), "V0");
    assert_eq!(turtle.event_source(), EVENT_NAMESPACE);
    assert_eq!(turtle.event_type(), "TurtleTurned");
}

#[derive(AggregateType)]

#[derive(AggregateType)] 实现了为您的聚合类型提供 AggregateType 特性。目前,此宏只能用于 struct 类型。我们可以使用两个可选属性 #[id_field]#[initialize_with_defaults] 来配置宏。

当指定了 #[id_field] 属性时,宏将额外实现 WithAggregateId 特性。此属性有一个参数,即结构体中 id 字段的标识符。

#[initialize_with_defaults] 属性告诉宏使用结构体中每个字段的默认值来实现 InitializeAggregate 特性。这假设结构体字段中使用的类型实现了 Default 特性。#[initialize_with_defaults] 属性要求结构体也指定了 #[id_field] 属性。

以下是一些示例

使用带有所有可选属性的 AggregateType 宏为特性 AggregateTypeWithAggregateIdInitializeAggregate 实现派生

use eventmill::{AggregateType, InitializeAggregate, WithAggregateId};

#[derive(AggregateType, Debug, PartialEq)]
#[id_field(id)]
#[initialize_with_defaults]
pub struct Turtle {
    id: String,
    x: f32,
    y: f32,
    direction: f32,
    speed: f32,
    pen: bool,
}

#[test]
fn main() {
    let expected_turtle = Turtle {
        id: "4711".to_string(),
        x: Default::default(),
        y: Default::default(),
        direction: Default::default(),
        speed: Default::default(),
        pen: Default::default(),
    };

    let new_turtle = Turtle::initialize("4711".to_string());

    assert_eq!(new_turtle, expected_turtle);
    assert_eq!(new_turtle.aggregate_id(), "4711");
    assert_eq!(Turtle::aggregate_type(), "Turtle");
}

仅派生 AggregateType 的实现。不要指定任何其他属性

use eventmill::AggregateType;


#[derive(AggregateType, Debug)]
pub struct Turtle {
    id: String,
    x: f32,
    y: f32,
    direction: f32,
    speed: f32,
    pen: bool,
}

#[test]
fn main() {
    assert_eq!(Turtle::aggregate_type(), "Turtle");
}

派生特性 AggregateTypeWithAggregateId 的实现

use eventmill::{AggregateType, WithAggregateId};

#[derive(AggregateType, Debug)]
#[id_field(id)]
pub struct Turtle {
    id: String,
    x: f32,
    y: f32,
    direction: f32,
    speed: f32,
    pen: bool,
}

#[test]
fn main() {
    let turtle = Turtle {
        id: "0815".to_string(),
        x: -0.5,
        y: 0.3,
        direction: 0.42,
        speed: 1.0,
        pen: true,
    };

    assert_eq!(turtle.aggregate_id(), "0815");
    assert_eq!(Turtle::aggregate_type(), "Turtle");
}

依赖项

~1.5MB
~35K SLoC