From 8fdca49e1d63db1075a23958ff23189818a49d6c Mon Sep 17 00:00:00 2001 From: muqiuhan Date: Thu, 13 Mar 2025 09:18:34 +0000 Subject: deploy: 11fd5b5345c11055a7c18e9b2c0baa4d2787fe15 --- .../index.html" | 2 +- "2023/05/04/C-\347\232\204-Trait/index.html" | 294 --------------------- .../index.html" | 279 ------------------- .../index.html" | 274 ------------------- .../index.html" | 2 +- .../index.html" | 10 +- .../index.html" | 2 +- .../index.html" | 2 +- .../index.html" | 287 ++++++++++++++++++++ .../index.html" | 277 +++++++++++++++++++ .../index.html" | 2 +- .../index.html" | 5 + .../index.html" | 282 ++++++++++++++++++++ archives/2023/05/index.html | 54 ---- archives/2023/page/4/index.html | 54 ++-- archives/2023/page/5/index.html | 60 ++--- archives/2023/page/6/index.html | 54 ---- archives/2025/02/index.html | 36 +++ archives/2025/03/index.html | 217 +++++++++++++++ archives/2025/index.html | 54 ++++ archives/index.html | 64 ++--- archives/page/2/index.html | 60 ++--- archives/page/3/index.html | 60 ++--- archives/page/4/index.html | 60 ++--- archives/page/5/index.html | 64 ++--- archives/page/6/index.html | 60 ++--- archives/page/7/index.html | 60 ++--- archives/page/8/index.html | 60 ++--- css/animation.css | 0 js/theme-switch.js | 31 +++ page/6/index.html | 114 +------- page/7/index.html | 114 +++++++- search.xml | 201 +++++++------- tag/index.html | 12 +- tags/C/index.html | 264 ------------------ tags/Software-Engineering/index.html | 10 +- tags/Technique/index.html | 64 ++--- tags/Technique/page/2/index.html | 60 ++--- tags/Technique/page/3/index.html | 64 ++--- tags/Technique/page/4/index.html | 12 +- tags/Web/index.html | 18 ++ 41 files changed, 1849 insertions(+), 1850 deletions(-) delete mode 100644 "2023/05/04/C-\347\232\204-Trait/index.html" delete mode 100644 "2023/05/11/C-vector-\347\232\204-push-back-\345\222\214-emplace-back/index.html" delete mode 100644 "2023/05/12/C-20-\345\256\236\347\216\260-string-split/index.html" create mode 100644 "2025/02/10/\345\256\236\346\227\266\346\220\234\347\264\242\344\270\255\347\232\204\351\230\262\346\212\226\345\207\275\346\225\260/index.html" create mode 100644 "2025/02/11/\344\273\216\344\272\213\344\273\266\351\243\216\346\232\264\347\234\213\351\242\206\345\237\237\351\251\261\345\212\250\350\256\276\350\256\241/index.html" create mode 100644 "2025/03/13/\351\242\206\345\237\237\351\251\261\345\212\250\350\256\276\350\256\241\344\270\255\347\232\204\342\200\234\350\201\232\345\220\210\346\240\271\342\200\235/index.html" create mode 100644 archives/2025/03/index.html create mode 100644 css/animation.css create mode 100644 js/theme-switch.js delete mode 100644 tags/C/index.html diff --git "a/2023/05/03/Rust-NewType-\346\250\241\345\274\217/index.html" "b/2023/05/03/Rust-NewType-\346\250\241\345\274\217/index.html" index 7ad16dd5..dcb2a4e8 100644 --- "a/2023/05/03/Rust-NewType-\346\250\241\345\274\217/index.html" +++ "b/2023/05/03/Rust-NewType-\346\250\241\345\274\217/index.html" @@ -198,7 +198,7 @@
- Prev + Prev
diff --git "a/2023/05/04/C-\347\232\204-Trait/index.html" "b/2023/05/04/C-\347\232\204-Trait/index.html" deleted file mode 100644 index e626505f..00000000 --- "a/2023/05/04/C-\347\232\204-Trait/index.html" +++ /dev/null @@ -1,294 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - -C++ 的 Trait | 暮秋小屋 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
- -
-
-
- - - -
-
-
- - -
-
-
- - -
- -
- -
- -
-
-
-
-

C++ 的 traits 技术,是一种约定俗称的技术方案,用来为同一类数据(包括自定义数据类型和内置数据类型)提供统一的类型名(traits),这样可以统一的操作函数,例如 advance(), swap(), encode()/decode() 等。

-
-

例如,拥有义类型Foo, Bar,以及编译器自带类型 int, double, string,我们想要为这些不同的类型提供统一的编码函数 decode() 。

-

除了使用 trait 技术之外,函数重载和模板函数 + 内置字段也可以实现,前者每增加一种数据类型就需要重新实现一个函数,而同一类数据(int, unsinged int)可以使用同样的编码方法。我们想要的是针对同一种数据类型,只编写一个函数。后者对于系统自定义变量 int, double 而言,是无法在其内部定义 type 的。

-

traits 技术的关键在于,使用另外的模板类 type_traits 来保存不同数据类型的 type,这样就可以兼容自定义数据类型和内置数据类型:

-
1
2
3
4
5
6
// 定义数据 type 类
enum Type {
TYPE_1,
TYPE_2,
TYPE_3
}
- -

对于自定义类型,在类内部定义 type,然后在 traits 类中定义同样的 type:

-
1
2
3
4
5
6
7
8
9
10
11
12
13
// 自定义数据类型
class Foo {
public:
Type type = TYPE_1;
};
class Bar {
public:
Type type = TYPE_2;
};
template<typename T>
struct type_traits {
Type type = T::type;
}
- -

对于内置数据类型,使用模板类的特化为自定义类型生成独有的 type_traits:

-
1
2
3
4
5
6
7
8
9
// 内置数据类型
template<typename int>
struct type_traits {
Type type = Type::TYPE_1;
}
template<typename double>
struct type_traits {
Type type = Type::TYPE_3;
}
- -

这样就可以为不同数据类型生成统一的模板函数

-
1
2
3
4
5
6
7
8
9
10
// 统一的编码函数
template<typename T>
void decode<const T& data, char* buf) {
if(type_traits<T>::type == Type::TYPE_1) {
...
}
else if(type_traits<T>::type == Type::TYPE_2) {
...
}
}
- -

总结

-
    -
  • traits 技术的关键在于使用第三方模板类 traits,利用模板特化的功能, 实现对自定义数据和编译器内置数据的统一
  • -
  • 这个例子使用了枚举变量来表示数据类型,而实际操作中通常使用不同的类来表示不同的类型,这样可以在编写模板函数时更好的优化。
  • -
  • tratis 技术常见于标准库的实现中,但对日常开发中降低代码冗余也有很好的借鉴意义
  • -
  • C++20 提供了Concept 的特性,使用Concept 可以使得实现类似的功能更加方便
  • -
- -
- - - - - -
- - - - - - - -
- - -
-
-
- - - -
- - -
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
- - - - - - - - - diff --git "a/2023/05/11/C-vector-\347\232\204-push-back-\345\222\214-emplace-back/index.html" "b/2023/05/11/C-vector-\347\232\204-push-back-\345\222\214-emplace-back/index.html" deleted file mode 100644 index ef87129a..00000000 --- "a/2023/05/11/C-vector-\347\232\204-push-back-\345\222\214-emplace-back/index.html" +++ /dev/null @@ -1,279 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - -C++ vector 的 push_back 和 emplace_back | 暮秋小屋 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
- -
-
-
- - - -
-
-
- - -
-
-
- - -
- -
- -
- -
-
-
-
1
2
3
4
5
6
/// Inserts a new element at the end of the vector, right after its current last element. This new element is constructed in place using args as the arguments for its constructor.
/// This effectively increases the container size by one, which causes an automatic reallocation of the allocated storage space if -and only if- the new vector size surpasses the current vector capacity.
/// The element is constructed in-place by calling allocator_traits::construct with args forwarded.
///A similar member function exists, push_back, which either copies or moves an existing object into the container.
template <class... Args>
void emplace_back (Args&&... args);
- -

push_back 会构造一个临时对象,这个临时对象会被拷贝或者移入到容器中,然而 emplace_back 会直接根据传入的参数在容器的适当位置进行构造而避免拷贝或者移动。

-

传统观点认为 push_back 会构造一个临时对象,这个临时对象会被移入到 v 中,然而 emplace_back 会直接根据传入的参数在适当位置进行构造而避免拷贝或者移动。从标准库代码的实现角度来说这是对的,但是对于提供了优化的编译器来讲,上面示例中最后两行表达式生成的代码其实没有区别。

-

真正的区别在于,emplace_back 更加强大,它可以调用任何类型的(只要存在)构造函数。而 push_back 会更加严谨,它只调用隐式构造函数。隐式构造函数被认为是安全的。如果能够通过对象 T 隐式构造对象 U,就认为 U 能够完整包含 T 的所有内容,这样将 T 传递给 U 通常是安全的。正确使用隐式构造的例子是用 std::uint32_t 对象构造 std::uint64_t 对象,错误使用隐式构造的例子是用 double 构造 std::uint8_t。

-

如果想要调用显示构造函数,那么就调用 emplace_back。如果只希望调用隐式构造函数,那么请使用更加安全的 push_back:

-
1
2
3
4
std::vector<std::unique_ptr<T>> v;
T a;
v.emplace_back(std::addressof(a)); // compiles
v.push_back(std::addressof(a)); // fails to compile
- -

std::unique_ptr<T> 包含了显示构造函数通过 T* 进行构造。因为 emplace_back 能够调用显示构造函数,所以传递一个裸指针并不会产生编译错误。然而,当 v 超出了作用域,std::unique_ptr<T> 的析构函数会尝试 delete 类型 T* 的指针,而类型 T* 的指针并不是通过 new 来分配的,因为它保存的是栈对象的地址,因此 delete 行为是未定义的。

- -
- - - - - -
- - - - - - - -
- - -
-
-
- - - -
- - -
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
- - - - - - - - - diff --git "a/2023/05/12/C-20-\345\256\236\347\216\260-string-split/index.html" "b/2023/05/12/C-20-\345\256\236\347\216\260-string-split/index.html" deleted file mode 100644 index a2db0de9..00000000 --- "a/2023/05/12/C-20-\345\256\236\347\216\260-string-split/index.html" +++ /dev/null @@ -1,274 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - -C++ 20 实现 string split | 暮秋小屋 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
- -
-
-
- - - -
-
-
- - -
-
-
- - -
- -
- -
- -
-
-
-

C++20引入了范围库ranges,其中提供的两个范围适配器std::split、std::lazy_split可以使我们以一种更为优雅的形式实现split:

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <concept>
#include <ranges>
#include <algorithm>
#include <format>
#include <iostream>

#define stdr std::ranges
#define stdrv std::ranges::views

template<template<typename> typename Container = std::vector, typename Arg = std::string_view>
auto Split(std::string_view str, std::string_view delimiter)
{
Container<Arg> myCont;
auto temp = str
| stdrv::split(delimiter)
| stdrv::transform([](auto&& r)
{
return Arg(std::addressof(*r.begin()), stdr::distance(r));
});
auto iter = std::inserter(myCont, myCont.end());
stdr::for_each(temp, [&](auto&& x) { iter = {x.begin(), x.end()}; });
return myCont;
}
int main()
{
std::string str = "Hello233C++20233and233New233Spilt";
std::string delimiter = "233";
auto&& strCont = Split<std::list, std::string>(str, delimiter);
stdr::for_each(strCont, [](auto&& x) { std::cout << std::format("{} ", x); });
}
//output: Hello C++20 and New Spilt
- -

C++20没有提供关键的 ranges::to<container>函数,导致demo中还需要额外封装并手写for_each来写入数据,等到C++23实装了该函数,split的实现会比现在简洁优雅的多,真正做到方便泛用、无需封装:

-
1
2
3
auto&& strCont = str
| stdrv::lazy_split(delimiter)
| stdr ::to<std::vector<std::string>>;
-
- - - - - -
- - - - - - - -
- - -
-
-
- - - -
- - -
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
- - - - - - - - - diff --git "a/2023/05/24/Rust-\351\227\255\345\214\205-lifetime-may-not-live-long-enough-\351\227\256\351\242\230/index.html" "b/2023/05/24/Rust-\351\227\255\345\214\205-lifetime-may-not-live-long-enough-\351\227\256\351\242\230/index.html" index 3e34ba99..ff0dfa44 100644 --- "a/2023/05/24/Rust-\351\227\255\345\214\205-lifetime-may-not-live-long-enough-\351\227\256\351\242\230/index.html" +++ "b/2023/05/24/Rust-\351\227\255\345\214\205-lifetime-may-not-live-long-enough-\351\227\256\351\242\230/index.html" @@ -202,7 +202,7 @@
- Next + Next
diff --git "a/2023/06/10/\344\272\214\351\233\266\344\272\214\344\270\211\345\271\264\345\205\255\346\234\210\345\215\201\346\227\245/index.html" "b/2023/06/10/\344\272\214\351\233\266\344\272\214\344\270\211\345\271\264\345\205\255\346\234\210\345\215\201\346\227\245/index.html" index 4ebbe5eb..8cc6e28e 100644 --- "a/2023/06/10/\344\272\214\351\233\266\344\272\214\344\270\211\345\271\264\345\205\255\346\234\210\345\215\201\346\227\245/index.html" +++ "b/2023/06/10/\344\272\214\351\233\266\344\272\214\344\270\211\345\271\264\345\205\255\346\234\210\345\215\201\346\227\245/index.html" @@ -158,11 +158,11 @@
-

我希望与我一样独自生活多年的宝宝们,能绝对理性的面对所有事情,这是一个人工作学习生活的基础,但同时要感同身受的去阅读文学类作品,这是让我们保留一丝感性的方式,感性是不可或缺的,理性可以让人控制感性,但也可以消灭它。

-

一个人的世界很容易出现信息茧房,要不断的和人交流,把很多想法说出来,接收一切评论,不然会在长期的不分正确错误的信息堆叠中出现一团巨大的闭塞性的知识,这很不利于我们快乐的活下去。

-

接收到的评论不必急于改变,先存起来,让它们陪着你跟着时间走,路上会慢慢的和其他的事情连结起来,这样就能择其善者而从之,其不善者而改之了。

-

和我一样处在青少年阶段的宝宝们应当早日从这喧扰的世界冷静下来,让脑子里满是憧憬和情爱的灵魂得到一丝陈酿,理性点抬头看看世界上方的二氧化碳,自己晃晃头打破能回到最初的样子再重来的梦。

-

爱你们噢。

+

请绝对理性的面对所有事情,这是一个人工作学习生活的基础,但同时要感同身受的去阅读文学类作品,这是保留一丝感性的方式,感性是不可或缺的,理性可以让人控制感性,但也可以消灭它。

+

独处的世界很容易出现信息茧房,要不断的和人交流,把很多想法说出来,接收一切评论,不然会在长期的不分正确错误的信息堆叠中出现一团巨大的闭塞性的知识,这很不利于快乐的活下去。

+

接收到的评论不必急于改变,先存起来,让它们陪着自己,跟着时间走,路上会慢慢的和其他的事情连结起来,这样就能择其善者而从之,其不善者而改之了。

+

应当早日从这喧扰的世界冷静下来,让脑子里满是憧憬和情爱的灵魂得到一丝陈酿,理性点抬头看看世界上方的二氧化碳,自己晃晃头打破能回到最初的样子再重来的梦。

+

爱你们。

diff --git "a/2024/11/17/\344\272\214\343\200\207\344\272\214\345\233\233\345\271\264\345\215\201\344\270\200\346\234\210\345\215\201\344\270\203\346\227\245/index.html" "b/2024/11/17/\344\272\214\343\200\207\344\272\214\345\233\233\345\271\264\345\215\201\344\270\200\346\234\210\345\215\201\344\270\203\346\227\245/index.html" index fe4cd80d..6163defd 100644 --- "a/2024/11/17/\344\272\214\343\200\207\344\272\214\345\233\233\345\271\264\345\215\201\344\270\200\346\234\210\345\215\201\344\270\203\346\227\245/index.html" +++ "b/2024/11/17/\344\272\214\343\200\207\344\272\214\345\233\233\345\271\264\345\215\201\344\270\200\346\234\210\345\215\201\344\270\203\346\227\245/index.html" @@ -158,7 +158,7 @@
-

快乐是正面情绪的原型,许多思想家都说过,人类的所作所为,最终都是为了追求快乐。我们之所以想追求财富、健康或名声,都是为了借此得到快乐。然而,追求快乐也不是因为它可以带给我们其他好处,因为快乐本身就是目的。

+

快乐是正面情绪的原型,人类的所作所为,最终都是为了追求快乐。我们之所以想追求财富、健康或名声,都是为了借此得到快乐。然而,追求快乐也不是因为它可以带给我们其他好处,因为快乐本身就是目的。

“世人皆以痛楚、孤独、悲伤为大境界,以为这就是深邃的人生,殊不知快乐才是人生的真谛。一个人获取快乐的能力才是真正有用的能力。伤春悲秋、离愁别绪太容易了,读几首诗词即可,但获取欢乐太难了非大丈夫不可为之。”

diff --git "a/2025/01/19/\350\272\253\344\275\223\345\276\200\345\211\215\345\200\276\357\274\214\347\201\265\351\255\202\345\220\221\345\220\216\346\221\207/index.html" "b/2025/01/19/\350\272\253\344\275\223\345\276\200\345\211\215\345\200\276\357\274\214\347\201\265\351\255\202\345\220\221\345\220\216\346\221\207/index.html" index 6abbd905..53f1ff70 100644 --- "a/2025/01/19/\350\272\253\344\275\223\345\276\200\345\211\215\345\200\276\357\274\214\347\201\265\351\255\202\345\220\221\345\220\216\346\221\207/index.html" +++ "b/2025/01/19/\350\272\253\344\275\223\345\276\200\345\211\215\345\200\276\357\274\214\347\201\265\351\255\202\345\220\221\345\220\216\346\221\207/index.html" @@ -190,7 +190,7 @@
- Prev + Prev
diff --git "a/2025/02/10/\345\256\236\346\227\266\346\220\234\347\264\242\344\270\255\347\232\204\351\230\262\346\212\226\345\207\275\346\225\260/index.html" "b/2025/02/10/\345\256\236\346\227\266\346\220\234\347\264\242\344\270\255\347\232\204\351\230\262\346\212\226\345\207\275\346\225\260/index.html" new file mode 100644 index 00000000..614e7b9c --- /dev/null +++ "b/2025/02/10/\345\256\236\346\227\266\346\220\234\347\264\242\344\270\255\347\232\204\351\230\262\346\212\226\345\207\275\346\225\260/index.html" @@ -0,0 +1,287 @@ + + + + + + + + + + + + + + + + + + + + + +实时搜索中的防抖函数 | 暮秋小屋 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+
+
+ + + +
+
+
+ + +
+
+
+ + +
+ +
+ +
+ +
+
+
+

在实现实时搜索功能时,通常会使用输入框的事件监听器来捕获用户的输入变化,并在输入变化时发送搜索请求。为了避免过多的请求导致服务器负担过重,通常会使用“防抖”(debounce)技术来控制请求的频率。

+

实现步骤

    +
  1. 监听输入框的变化:使用input事件监听器来捕获用户的输入变化。
  2. +
  3. 防抖处理:使用防抖函数来限制请求的频率。防抖函数会在用户停止输入一段时间后才发送请求。
  4. +
  5. 发送请求:在防抖函数中调用搜索请求。
  6. +
+

防抖函数示例

以下是一个简单的防抖函数示例:

+
1
2
3
4
5
6
7
8
function debounce(func, wait) {
let timeout;
return function(...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
}
+ +

实现实时搜索

假设你有一个输入框用于搜索患者:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<script>
import { onMount } from 'svelte';
import { patientsStore } from '$lib/stores/patients.svelte';

let searchTerm = '';

// 防抖函数
function debounce(func, wait) {
let timeout;
return function(...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
}

// 搜索函数
const searchPatients = debounce(async (term) => {
if (term) {
// 发送搜索请求
const response = await fetch(`/api/search-patients?query=${term}`);
const data = await response.json();
patientsStore.mbglPatients = data;
} else {
// 清空搜索结果或恢复默认数据
patientsStore.mbglPatients = [];
}
}, 300); // 300ms 的防抖时间

// 监听输入框变化
function handleInput(event) {
searchTerm = event.target.value;
searchPatients(searchTerm);
}
</script>

<input type="text" placeholder="搜索患者..." on:input={handleInput} bind:value={searchTerm} />
+ +

请求发送间隔

    +
  • 防抖时间:通常设置为 300ms 到 500ms 之间。这个时间足够让用户完成输入并减少不必要的请求。
  • +
  • 考虑用户体验:防抖时间过短可能导致过多请求,过长则可能让用户感到延迟。300ms 是一个常用的折中值。
  • +
+

通过这种方式,你可以实现一个高效的实时搜索功能,既能保证用户体验,又能减少服务器的负担。

+ +
+ + + + + +
+ + + + + + + +
+ + +
+
+
+ + + +
+ + +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ + + + + + + + + diff --git "a/2025/02/11/\344\273\216\344\272\213\344\273\266\351\243\216\346\232\264\347\234\213\351\242\206\345\237\237\351\251\261\345\212\250\350\256\276\350\256\241/index.html" "b/2025/02/11/\344\273\216\344\272\213\344\273\266\351\243\216\346\232\264\347\234\213\351\242\206\345\237\237\351\251\261\345\212\250\350\256\276\350\256\241/index.html" new file mode 100644 index 00000000..d7d6ef41 --- /dev/null +++ "b/2025/02/11/\344\273\216\344\272\213\344\273\266\351\243\216\346\232\264\347\234\213\351\242\206\345\237\237\351\251\261\345\212\250\350\256\276\350\256\241/index.html" @@ -0,0 +1,277 @@ + + + + + + + + + + + + + + + + + + + + + +从事件风暴看领域驱动设计 | 暮秋小屋 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+
+
+ + + +
+
+
+ + +
+
+
+ + +
+ +
+ +
+ +
+
+
+

事件风暴(Event Storming)是一种领域驱动设计(DDD)的实践方法,由 Alberto Brandolini 提出,旨在通过团队协作的方式快速理解和建模业务领域。

+

以下是事件风暴及相关领域驱动设计中的一些核心概念和知识点:

+

1. 领域(Domain):指的是业务相关知识的集合,可以进一步划分为子域。
2. 子域(Subdomain):是领域的一部分,可以是核心域、支撑域或通用域。
3. 核心域(Core Domain):指领域中最核心的部分,通常对应企业的核心业务。
4. 通用语言(Ubiquitous Language):团队所有成员使用的一种语言,用于确保业务和软件之间的沟通一致性。
5. 限界上下文(Bounded Context):定义了一组规则和协议,用于明确领域模型的适用范围。
6. 实体(Entity):具有唯一标识和生命周期的领域对象。
7. 值对象(Value Object):描述了某种特性或属性的对象,没有概念标识。
8. 聚合(Aggregate):一组相关对象的集合,由一个聚合根(Aggregate Root)统一管理。
9. 领域事件(Domain Event):领域中发生的重要事件,可以用于通知其他领域对象或跨限界上下文进行解耦和协作。
10. 命令(Command):表示要执行的操作,通常与事件一一对应。
11. 读模型(Read Model):为了优化读取操作而设计的模型,可能与写模型不同。
12. 决策命令(Decision Command):在事件风暴中,直接导致事件发生的命令。
13. 战略设计(Strategic Design):高层次的抽象和归类,包括理清上下文和子域的划分。
14. 战术设计(Tactical Design):对特定上下文下的模型进行详细设计,包括聚合、实体和值对象。
15. 贫血模型(Anemic Domain Model):领域对象只有属性及其getter/setter方法的纯数据类,业务逻辑通过服务实现。
16. 充血模型(Rich Domain Model):领域对象包含业务逻辑,每个对象都是活跃的。
17. 资源库(Repository):用于检索和持久化领域对象的机制。
18. 服务(Service):在模型中独立的操作,可以是领域服务或应用服务。
19. 固定规则(Invariant):为设计元素做出的断言,必须一直保持为真。

+

事件风暴通常包括以下步骤:

+
    +
  • 识别领域事件
  • +
  • 确定事件顺序
  • +
  • 识别命令和触发器
  • +
  • 识别聚合和实体
  • +
  • 划分限界上下文
  • +
  • 识别领域服务和资源库
  • +
  • 通过这些步骤,团队可以共同创建出反映业务领域的领域模型,为软件设计和开发提供指导。
  • +
+ +
+ + + + + +
+ + + + + + + +
+ + +
+
+
+ + + +
+ + +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ + + + + + + + + diff --git "a/2025/02/18/Prisma-\345\205\263\347\263\273\345\236\213\346\225\260\346\215\256\345\272\223\347\232\204-Self-relations/index.html" "b/2025/02/18/Prisma-\345\205\263\347\263\273\345\236\213\346\225\260\346\215\256\345\272\223\347\232\204-Self-relations/index.html" index c4c33004..d5523d01 100644 --- "a/2025/02/18/Prisma-\345\205\263\347\263\273\345\236\213\346\225\260\346\215\256\345\272\223\347\232\204-Self-relations/index.html" +++ "b/2025/02/18/Prisma-\345\205\263\347\263\273\345\236\213\346\225\260\346\215\256\345\272\223\347\232\204-Self-relations/index.html" @@ -267,7 +267,7 @@
- Next + Next
diff --git "a/2025/02/24/\344\272\214\343\200\207\344\272\214\344\272\224\345\271\264\344\272\214\346\234\210\344\272\214\345\215\201\345\233\233\346\227\245/index.html" "b/2025/02/24/\344\272\214\343\200\207\344\272\214\344\272\224\345\271\264\344\272\214\346\234\210\344\272\214\345\215\201\345\233\233\346\227\245/index.html" index 04392f68..ec7102ef 100644 --- "a/2025/02/24/\344\272\214\343\200\207\344\272\214\344\272\224\345\271\264\344\272\214\346\234\210\344\272\214\345\215\201\345\233\233\346\227\245/index.html" +++ "b/2025/02/24/\344\272\214\343\200\207\344\272\214\344\272\224\345\271\264\344\272\214\346\234\210\344\272\214\345\215\201\345\233\233\346\227\245/index.html" @@ -173,6 +173,11 @@