Aggregates Composition: A new view on Aggregates - Jérémie Chassaing - DDD Europe 2023

Domain-Driven Design Europe
6 Mar 202453:24

Summary

TLDRスクリプトは、ホスピタリティ業界で15年間働いた外国人の専門家が、ホテルの予約やプランニングを管理する会社で建築家として働いていることを紹介しています。講演では、集約、構成、そして「decider」という用語について説明し、集約の定義のあいまいさと力、またその弱点についても触れています。deciderパターンを紹介し、これは集約を明確な方法で書くことができ、インメモリやイベントソーシングなどの異なる方法で動作する集約を作成する方法を説明しています。また、deciderを組み合わせて複雑なシステムを構築する方法も示されています。

Takeaways

  • 🌟 集約化とコンポジションの概念が紹介され、集約化は境界内の一貫性を保つもの、コンポジションは複雑性を減らすために使用されることについて説明されています。
  • 🔍 集約化の定義は曖昧であり、強みと弱みの両方を持っていると指摘されています。集約化は内部の一貫性を保つが、どのようにそれを管理するかは明確にしていません。
  • 📈 集約化を設計する際には、小規模な集約化が独立して動作する多くの小さなピースになることがあり、これによりコンカレンシーやインフラストラクチャの複雑性が増大します。
  • 🛠️ 問題を解決するために提案された「Deciderパターン」。このパターンは、特定の形状を持つ集約化を定義し、興味深い性質を持つことを説明しています。
  • 🔧 Deciderパターンは、コマンドを受け取り、状態を変化させるだけでなく、イベントを出力する機能も持っています。これにより、永続化やイベントソーシングに使用できます。
  • 🔄 Deciderパターンは、不変データ構造を使用し、状態の変更を純粋な関数で管理します。これにより、テストや理解が容易になります。
  • 📚 シンプルなドメイン例(電球と猫)を使用して、Deciderパターンが実装され、テストされ、実行される方法が説明されています。
  • 🔗 複数のDeciderを組み合わせて、1つのDeciderとして扱うことができる。これにより、関連するドメインロジックをグループ化し、管理が容易になります。
  • 🔄 永続化とイベントソーシングの両方にDeciderパターンを使用することができ、インフラストラクチャに依存しないドメインロジックの実装が可能になります。
  • 🎯 Deciderパターンを使用することで、ドメインロジックのテストが容易になり、状態の変更に関連するテストも簡単に行えます。
  • 🛠️ Deciderパターンは、ドメインロジックをシンプルで再利用可能な形で構築し、様々な方法で実行可能にすることができる強力なツールです。

Q & A

  • どのような職業の人物が話している?

    -脚本の人物は15年間ホテルの予約やプランを管理する会社で働いている建築家です。

  • 集約(Aggregate)とは何ですか?

    -集約は、境界内の一貫性を保持するものであり、内部は一貫性がある必要がありますが、どのようにそれを管理するかについては言及されていません。

  • Deciderパターンは何を可能にしますか?

    -Deciderパターンは、集約を明確に定義された形で書くことを可能にし、特定の型を持つ異なるものを扱うことができます。

  • Deciderパターンの利点は何ですか?

    -Deciderパターンの利点は、永続化に関連するコードを変更することなく、ドメインコードをテストし、インメモリで実行することができます。

  • どのようなシンプルなドメイン例が挙げられましたか?

    -シンプルなドメイン例として、電球と猫が挙げられました。電球はソケットに取り付けられ、使用回数に応じて故障する可能性があります。猫は寝ていると觉醒しているという2つの状態があります。

  • どのようにしてDeciderをテストするのか?

    -Deciderをテストするためには、期待されるイベントと実際の出力が一致していることを確認するBDD(Behavior Driven Development)テストが使用されます。

  • インメモリでのDeciderの実行方法は何ですか?

    -インメモリでのDeciderの実行では、状態を変更するための命令を送ることができます。状態はミュータブルな変数として扱われ、各命令を処理することで新しい状態が生成されます。

  • 状態を永続化するために何が必要ですか?

    -状態を永続化するためには、シリアライザーとキーバリューストア(またはイベントストア)が必要です。シリアライザーは状態を文字列に変換し、キーバリューストアに保存します。

  • Deciderを複数のインスタンスで実行するにはどうすればいいですか?

    -Deciderを複数のインスタンスで実行するためには、各インスタンスに一意の識別子を割り当て、状態を辞書(またはマップ)として管理する必要があります。

  • プロセスとは何ですか?

    -プロセスは、イベントをリッスンしてコマンドを発行し、内部状態を持つステートマシンです。プロセスは、新しいイベントを生成するDeciderと組み合わせることができます。

  • Deciderとプロセスの組み合わせの利点は何ですか?

    -Deciderとプロセスの組み合わせにより、複数のドメインロジックを単一のユニットとして実行できます。これにより、インフラストラクチャの変更なしにインメモリ実行とイベントソーシングの間を簡単に切り替えることができます。

Outlines

00:00

🏢 多国籍ホスピタリティ企業の建築家としての経験と新しい作業の紹介

スピーカーは15年間 hotellity 企業で働いており、その企業は世界中のホテルの予約や計画を管理するものであると説明しました。彼はその企業の建築家であり、新しい作業について話すことができるが、その作業は最近のものであり、まだ完全に記録されていないと述べました。スピーカーは実演を通じて、コードを用いてそれらを紹介する予定であり、集約、構成、そして「decider」という用語について話すことになると述べました。

05:02

📊 集約とdeciderパターンについて

スピーカーは集約の定義について説明し、集約は境界内で一貫性を保つものであると述べました。境界内のものは一貫性を保つ必要がある一方、境界外のものは一貫性を保つ必要がないと指摘しました。また、スピーカーは集約の複雑性を減らすために、小規模な集約を独立した要素やサービスに分割し、必要に応じてグループ化することで管理しやすくなると説明しました。deciderパターンについても触れ、それは集約を明確に定義した形で、興味深い特性を持つ集約を記述する方法であると述べました。

10:03

🔧 Deciderパターンの具体的な例

スピーカーはF#言語を使用して、deciderパターンの具体的な例を示しました。decider型を作成し、その型はジェネリックであり、異なる型に対して動作することができると説明しました。deciderパターンはコマンドを受け取り、イベントを出力するものであり、状態を管理するために必要とされると述べました。deciderパターンの構成には、decide関数、evolve関数、初期状態、およびターミナル関数が含まれることが示されました。

15:05

💡 シンプルなドメインのdeciderパターンの例

スピーカーは、電球と猫のシンプルなドメインを使用して、deciderパターンの例を説明しました。電球はソケットに差し込むことができ、猫は目覚めてると寝ているの2つの状態を持つと説明しました。この例では、電球を操作するコマンド(電球を差し込む、開ける、閉める)とイベント(電球が差し込まれた、開けた、閉まった)が定義され、deciderパターンがどのように機能するかを説明しました。

20:08

📈 テストと実行可能なdeciderパターン

スピーカーはdeciderパターンをテストする方法と、インメモリで実行する方法について説明しました。テストは、特定のコマンドが期待されるイベントを生成することを確認するものであり、インメモリ実行は、状態をミュータブル変数として保持することで行われます。この方法により、テストが容易になり、状態の変更を自由に行えることが示されました。

25:10

🔄 状態の永続化とイベントソーシング

スピーカーは、状態を永続化し、イベントソーシングを使用する方法について説明しました。永続化は、データベースに状態を保存することで行われ、イベントソーシングは、イベントを介して状態を更新する方法です。スピーカーは、簡単なキーバリューストアとイベントストアの玩具的な実装を使用して、このプロセスを説明しました。

30:12

🎵 複数のdeciderを組み合わせる

スピーカーは、複数のdeciderを組み合わせて一つのdeciderを作成する方法について説明しました。この方法により、異なるドメインモデルを一つに統合することができ、同じdeciderを繰り返し使用することができると述べました。また、中性要素のdeciderを作成し、それを使用して複数のインスタンスを一つのdeciderにまとめることもできました。

35:16

🤖 状態マシンとしてのプロセス

スピーカーは、プロセス作为一种状态机について説明しました。プロセスは、イベントをリッスンしてコマンドをエミットし、内部状態を持つものであり、異なる状態间的遷移を定義することができます。スピーカーは、プロセスとdeciderを組み合わせて、光がONになると猫を目覚めるという動作を実装する方法を示しました。

40:17

🚀 統合と柔軟性

スピーカーは、deciderパターンとプロセスを組み合わせて、柔軟性のあるシステムを構築する方法について最後に説明しました。この方法では、インメモリ実行、状態データベース、イベントソーシングなど、さまざまな実行環境を簡単に切り替えることができると強調しました。また、コードを変更することなく、さまざまな実行環境で動作するようにシステムを構築することができると述べました。

Mindmap

Keywords

💡aggregate

aggregateは、データベースの概念であり、関連するエンティティのグループをまとめるために使用されます。このビデオでは、aggregateは一貫性を維持する境界内に保持されるものであり、内部は一貫性があることが重要です。aggregateは、状態の遷移を管理し、外部との相互作用を通じて決定を下す役割を持っています。例えば、電球のon/offやキャットの起業/睡眠状態を管理するaggregateが登場しています。

💡composition

compositionは、複数のオブジェクトや関数を組み合わせて一つのシステムや機能を作成することを指します。このビデオでは、複数のaggregateを組み合わせて一つの大きめのaggregateを作成することができます。これにより、一つのシステム内で複数のエンティティを統合して管理することができます。例えば、キャットと電球の状態を一緒に管理するaggregateを作成することができました。

💡decider pattern

decider patternは、ソフトウェア開発において、特定のタスクや処理を実行するためのデザインパターンです。このビデオでは、decider patternを使用して、aggregateを定義し、状態の変化やイベントの発生を管理する方法が説明されています。decider patternは、アプリケーションのロジックを整理し、テストや保守を容易にするための役立つ構造を提供します。

💡event sourcing

event sourcingは、ソフトウェアのイベントドリブンアーキテクチャで、システムの状態の変更をイベントとして記録し、そのイベントを使ってシステムの過去の状態を再現できる方法です。このビデオでは、event sourcingを使用して、aggregateの状態の変更を追跡し、データベースに保存する方法が説明されています。これにより、システムの変更履歴を保持し、問題が発生した場合に状態をロールバックすることができます。

💡state

stateは、ある瞬間にシステムやオブジェクトの状態を表すデータのセットです。このビデオでは、aggregateのstateは、そのaggregateの現在の状態を示しており、decider patternを使用して状態の変化を管理する方法が説明されています。stateは、システムの動作やイベントの発生に必要な情報を含むため、重要な役割を果たしています。

💡command

commandは、システムに何かを実行するように指示するメッセージです。このビデオでは、commandはaggregateに対して状態変化を要求する役割を果たしています。commandは、システムに特定の操作を実行するように指示し、その結果としてイベントが発生する可能性があります。

💡event

eventは、システム内で発生した什么の事実を表すメッセージです。このビデオでは、eventは、aggregateの状態変化を記録し、イベントソーシングを使用してシステムの過去の状態を再現できるようにします。eventは、システムの変更を通知し、その変更を他のシステムやプロセスに伝播するために使用されます。

💡concurrency

concurrencyは、複数のタスクやプロセスが同時に進行することを指します。このビデオでは、concurrencyは、複数のaggregateやdeciderが同時に動作し、システム全体を管理する際に必要になるインフラストラクチャや管理の複雑性を示しています。同時に複数の操作を処理するためには、システムは適切な並列処理能力を備える必要があります。

💡immutable data structure

immutable data structureは、一度作成された後、変更できないデータ構造です。このビデオでは、immutable data structureを使用して、stateが変更される際に、新しいバージョンのデータ構造が作成されることを説明しています。これにより、データの整合性が維持され、変更履歴が追跡可能になります。

💡pure functions

pure functionsは、与えられた入力に対して常に同じ出力を返す関数で、副作用を持ちません。このビデオでは、pure functionsを使用して、decider patternのロジックを整理し、テストを容易にしています。pure functionsは、予測可能性が高いため、バグの発生を減らし、システムの信頼性を向上させます。

💡behavior driven test

behavior driven testは、ソフトウェアの動作を定義し、その動作が正しく実行されるかを検証するテスト手法です。このビデオでは、behavior driven testを使用して、decider patternのロジックが正しく動作することを確認しています。このテスト手法は、要件定義に基づいてテストケースを作成し、システムの実際の動作を確認することで、品質を確保します。

Highlights

The discussion introduces the concept of aggregates and their role in maintaining consistency within their boundaries while allowing for complex interactions outside of them.

The importance of managing small aggregates and the challenges that arise from the concurrency and infrastructure required to run them is emphasized.

The Decider pattern is introduced as a solution to write aggregates in a well-defined way, providing a specific shape for aggregates with interesting properties.

The Decider pattern enables the running of classic load state safely without touching the domain code, making it versatile for different types of persistence.

The concept of a boundary in aggregates is explored, highlighting how it defines the consistency required within the system and the complexity that arises from managing interactions across boundaries.

The idea of grouping and splitting aggregates is discussed, along with the potential friction and challenges that come with reorganizing the system's structure.

The implementation of the Decider pattern is explained through the use of F#, showcasing its simplicity and powerful type system.

The concept of a 'command' and 'event' within the Decider pattern is introduced, explaining how they represent changes and outcomes within the system.

The role of the 'evolve' function in the Decider pattern is discussed, detailing how it manages state changes based on events.

The importance of having an initial state and a terminal function in the Decider pattern is highlighted, providing the framework for the lifecycle of an aggregate.

The demonstration of a simple domain model using the Decider pattern, such as a light bulb with a specific number of uses, is provided to illustrate the practical application of the concept.

The concept of 'even sourcing' is introduced, explaining how it can be used in conjunction with the Decider pattern to manage state changes and events.

The use of a key-value store and event store for persisting the state of deciders is discussed, providing a solution for maintaining the system's history and current state.

The ability to combine multiple deciders into a single, more manageable unit is explored, showcasing the flexibility and scalability of the Decider pattern.

The concept of a 'process' is introduced, explaining how it can listen to events, emit commands, and maintain an internal state, further expanding the capabilities of the system.

The practical application of combining deciders, processes, and event sourcing to create a cohesive and interactive system is demonstrated.

Transcripts

play00:01

foreign

play00:18

working at the age Hospitality for 15

play00:22

years now so it's quite a lot of time

play00:25

and you can also it's a company that is

play00:30

managing bookings and planning for hotel

play00:32

all around the world

play00:35

I am an architect there and I'm applying

play00:39

some of the thing I will show you but

play00:41

this is quite recent work and it has not

play00:44

been fully documented yet so you will

play00:46

see here I will do everything

play00:50

mostly live so it's cool and I think

play00:54

after all you've heard this morning you

play00:56

want to see some code to learn actually

play00:58

the thing and this is what we will see

play01:00

and today we will talk about aggregate

play01:03

composition

play01:04

and they use the word aggregate here but

play01:06

we will talk about deciders who know

play01:07

what we decider is

play01:09

okay not many people so the problem with

play01:12

the aggregate with the aggregate

play01:14

definition is that it's quite fuzzy so

play01:15

that one of the power of aggregate uh

play01:18

but that's also one of its weakness uh

play01:21

an aggregate is something that keeps

play01:24

some consistency inside the boundary so

play01:27

it's yeah there are something inside

play01:28

there is a red outside and what it says

play01:31

is that what is inside need to be

play01:33

consistent okay so you need to move from

play01:36

one valid state to another valid state

play01:38

or not at all okay but it says nothing

play01:42

about how you do that and how you manage

play01:44

that but something interesting with this

play01:46

definition is that you have a bundary

play01:48

what is inside has to be consistent and

play01:51

what he says is that what is outside

play01:53

just doesn't have to doesn't mean that

play01:56

it should be not consistent okay just

play01:59

doesn't have to and this is something

play02:01

that uh leads in a lot with that

play02:04

regulate a lot of complexity when you

play02:06

start to design small aggregate is that

play02:08

you have a lot of small pieces Maybe

play02:10

independently and you usually you need

play02:14

some things like small actors or small

play02:16

services for each aggregate calling the

play02:17

the ones one other

play02:21

in a complicated way and then at some

play02:23

point you have too much moving Parts too

play02:26

many parts in parallel in concurrency

play02:29

there is no problem for that but it's a

play02:32

lot of infrastructure to run all these

play02:33

small things

play02:34

and something we that could be easier

play02:36

sometimes it's just to take several that

play02:39

work together and group them together as

play02:41

a more manageable all so what you can do

play02:45

is that you can write add a code that

play02:48

group them but then if at some point in

play02:50

time it's better to split them again you

play02:52

risk to have some friction because some

play02:55

decisions have been taken in this

play02:57

composition in this grouping and then

play02:59

when you start to remove it you don't

play03:00

know how to do and here uh I will show

play03:04

you first what the decider pattern is

play03:06

this is a pattern

play03:10

that enables you to write Aggregates in

play03:13

the

play03:14

well-defined way so this is a specific

play03:16

shape for aggregates

play03:18

that has very interesting properties so

play03:22

we are

play03:23

in an even sourcing track so we'll talk

play03:27

about even sourcing but not

play03:29

exclusively because you can also use the

play03:32

decider pattern to run classic loads

play03:35

load State safe State way and the super

play03:38

cool thing with that is that you never

play03:40

need to touch the domain code whatever

play03:43

the persistence you want to to use okay

play03:46

so let's start with this idea pattern

play03:49

the other side of pattern is quite uh

play03:53

simple it's here we will I will write it

play03:56

again

play03:57

so that you see how it it works okay

play04:00

so

play04:01

it's a decider because this is this is

play04:03

something that decide things okay so we

play04:06

will create a who is fluent in F sharp

play04:08

hey hey some some people yeah this is F

play04:12

sharp you will you will see it reads

play04:13

mostly like python but with more types

play04:16

things and I will explain on the Fly uh

play04:18

what's happening so we'll uh create

play04:21

decider type

play04:22

and this decider type is generic meaning

play04:25

that it can act on different things with

play04:28

specific types that we will find

play04:30

multiple times in the definition the

play04:32

first thing decider will do is that it

play04:35

will receive commands comments that will

play04:37

ask to make a change on the decider this

play04:40

is the commands we talk about with

play04:43

Aggregates it can also be seen as the

play04:45

method on your Aggregates that will

play04:47

change the thing in the aggregate but we

play04:49

will

play04:50

put this command in a type and we'll

play04:53

just use this cut C

play04:56

name inside the definition okay so these

play04:59

are the comments okay but what an

play05:02

aggregate this idea is doing also it's

play05:04

it's taking decisions and the output of

play05:07

this decision will be events saying this

play05:10

happened okay so we will have an event

play05:12

type

play05:13

and to manage all this inside

play05:16

it will need a state to know what is the

play05:19

current state and take the decision so

play05:21

an s okay so short end for command event

play05:26

and state and the first thing in the

play05:29

decider will be the decide function the

play05:30

decide function is here to say when you

play05:33

ask me to do this command and I'm in

play05:36

this state here is what happened so

play05:39

definition is quite straightforward this

play05:42

is a decide function

play05:43

and this function we'll take a command

play05:46

of type c it will also take a state of

play05:50

Type S and it will it will return events

play05:53

so e

play05:55

and this is a list

play05:57

okay because it can return 0 one or many

play06:01

events

play06:03

so this is where the domain logic will

play06:06

take place okay this is where we will

play06:08

say okay I'm in this state you asked me

play06:10

to do this this is the result this is

play06:12

what happens

play06:13

of course you can anticipate this is

play06:16

this event can finish in an even store

play06:19

of course okay

play06:20

second step

play06:23

once when we are in the state and

play06:25

something happens the state change and

play06:28

in the decider pattern we clearly split

play06:30

the decision

play06:33

from the state change and we will have

play06:35

for this state change an evolve function

play06:38

evolve and it says when I'm in this

play06:41

state of Type S and this event happened

play06:44

of Type e

play06:46

here is the new state

play06:48

of type S

play06:50

Okay so

play06:52

here

play06:53

I'm writing in F sharp I'm using

play06:56

immutable data structure so the state is

play06:59

not like some things that change you

play07:01

have a data structure that contains some

play07:03

values and the evil function will create

play07:05

a new version of this data structure

play07:06

with a new value and return it okay so

play07:09

this is pure functions will be really

play07:11

easy to reason with and all that you

play07:13

will see how we write it uh just after

play07:18

uh to be able the evil function texture

play07:21

state but the question is where do we

play07:23

start

play07:24

so we need an initial state

play07:27

so initial State like that and this is

play07:30

just a value of Type S that is the

play07:34

State before anything happens okay

play07:37

and the last thing is that at some point

play07:40

we will need to to to finish to know

play07:44

that this this idea has finished its job

play07:45

and that we can archive it or something

play07:47

so we have these terminal function that

play07:49

takes to State and return a Boolean

play07:51

value uh to say okay it's done

play07:54

right

play07:55

this is a decider

play07:57

and actually you can take any aggregates

play08:00

on writing with this form

play08:03

you if you have access to external

play08:06

service you move them

play08:07

up the stack and you put the values

play08:10

inside the commands as values and your

play08:14

desired function will take everything as

play08:15

the state

play08:16

all the reaction instead of Performing

play08:20

side effect you will have some events

play08:23

from the decide function you can use

play08:25

them to perform the side effect from the

play08:27

outside remove all the rest you keep the

play08:29

logic inside okay

play08:32

this is a shape of a decider and on for

play08:36

the last part I will need something that

play08:38

I will explain later but I will need to

play08:40

to make a dissociation between the state

play08:44

that is on the output on the input on

play08:46

the state on the output so everywhere

play08:48

the state is on the left

play08:50

I will call it s i on everywhere it's on

play08:54

the right I will call it

play08:56

so and we can just create another type

play08:59

for short end which is

play09:01

the same but with the same state on the

play09:06

input and the output uh yes like that

play09:09

it's a decider of c e S and S this is a

play09:15

short n when the state on the input on

play09:17

the output is the same okay

play09:18

so know that we have a decider let's

play09:22

write some domain code so we will take a

play09:24

very simple domain we have a light bulb

play09:26

okay and we have a cat

play09:29

right so the light bulb you can

play09:32

fit it in the in the blog in the socket

play09:35

and it will have a specific number of

play09:39

usage for blowing up right on the cat it

play09:43

just has two states it can be a weight

play09:45

awake or sleeping and you can wake it up

play09:49

or get it to sleep okay so

play09:52

our first example is here so document

play09:56

here is the type command

play09:59

and so this kind of type is called the

play10:03

Union

play10:04

uh so the command can be as three kgs

play10:08

which is either fit with the feed value

play10:12

which contains the max uses integer or

play10:15

it can be a switch on or switch off okay

play10:18

so

play10:19

the way to implement it in other

play10:21

languages usually you can create a base

play10:23

class and having three classes the

play10:25

deriving from from this base class and

play10:28

then you can match on the type and do

play10:30

the thing okay or you can use Dynamic

play10:32

dispatch or anything but in our case

play10:34

it's this is a single type with three

play10:37

cases okay

play10:39

the event

play10:41

are quite the same as the users but in

play10:45

the past tense right so we have a fit

play10:47

and we have a fitted event

play10:49

we have a switch on Switched on switch

play10:52

off switched off but we have an other

play10:53

event which is blue

play10:55

uh when the the

play10:58

verb just blue

play11:01

the status can be on on on on or off and

play11:04

the state is also a union

play11:08

it can be not fitted working with the

play11:11

statues

play11:12

and the remaining uses and it can be

play11:15

blown right okay so

play11:18

usually you don't start like that you go

play11:21

using a tdd to to Define what your state

play11:25

is but the comment on the event

play11:28

come from the specification the state is

play11:30

more like implementation details so the

play11:33

decide function here

play11:35

as we said must take a command on the

play11:37

state so what you ask the bulb to do on

play11:40

in what state it is so we just match the

play11:42

two values

play11:44

and return some event for each right so

play11:48

if it's not fitted then we send it a

play11:50

feed command it will return fitted with

play11:53

the max uses indicated if it's we ask we

play11:58

to fit but the state is not not fitted

play12:02

it will fail

play12:04

when you ask it to switch in on uh while

play12:08

it's working

play12:09

and the status is off it will be

play12:13

switched on okay but this is only the

play12:17

case when the remaining uses are larger

play12:19

than zero right because when it's zero

play12:21

we go to the other line and it's earned

play12:24

we ask it although the current state is

play12:27

off it's just blue and the last one is

play12:30

you switch it off while it's on and it

play12:33

will say it switch off in all other

play12:34

cases it does nothing right

play12:38

so this is this the decision

play12:41

for this thing right

play12:43

so this is a very simple decider uh in

play12:47

the case of a board game that I wrote I

play12:49

have a decider which is 2 000 lines long

play12:52

of F sharp which is quite test language

play12:54

so yeah and it has been converted to

play12:57

uh 11

play13:00

000 lines of PHP so yeah you can imagine

play13:02

the the thing

play13:05

um so uh after the decide function we

play13:08

need we need an evolve function

play13:10

and this function is just changing the

play13:14

state based on what happens so it takes

play13:16

the state on an event and will return

play13:17

the state

play13:19

if it's not fitted only just fitted no

play13:21

it's working with the status off and the

play13:25

remaining uses are Max uses

play13:27

if it's working on it that's been

play13:29

switched on we change the statues and

play13:31

remove one from the remaining uses if

play13:34

it's working

play13:35

and switch off it's off and if it's blue

play13:39

it's a transition to the blown state in

play13:41

other cases it's remaining the in the

play13:44

same state

play13:45

right the initial state is not fitted

play13:48

and the e-terminal state is statically

play13:52

equal to blown right and now I can just

play13:55

create the structure by taking the

play13:57

function and put it in put it put them

play13:59

in the data structure

play14:01

right so the cool thing is that this

play14:06

decider is very easy to test so I wrote

play14:09

here

play14:11

function

play14:13

given when which deck you decider

play14:15

right

play14:16

on what it does it takes its return a

play14:19

function that takes some event on the

play14:22

command

play14:23

okay

play14:24

it takes these events

play14:27

and pass it to the list.fold list.fold

play14:31

is taking your list

play14:33

initial value which is the decider

play14:35

initial State okay and it takes the

play14:37

first element in the list and called the

play14:40

function that is passed here is this

play14:42

idea that evolve detect the result takes

play14:45

the next the next item in the list and

play14:48

do the same so

play14:50

after the second line

play14:53

we get the initial state

play14:58

then the state after the first event

play15:01

after the second event and the last

play15:02

event so we get the current state right

play15:04

and so this is a pipe forward thing here

play15:09

this current state is passed to the

play15:12

decider the decide function with the

play15:14

command

play15:15

and the result is a list of events right

play15:17

so I just create a small operator which

play15:21

is a equal bank which says assert okay

play15:24

let's check that X actually is equal to

play15:27

expected on print something

play15:30

and no I can also create this small

play15:33

Arrow operator

play15:36

simple row

play15:38

that is given when with the bulk decider

play15:40

so my tests are here when nothing

play15:43

happened before and I fit the bulb with

play15:45

Max user to five the result is one event

play15:50

which is fitted with maxus 5. when the

play15:53

bulb has been fitted and you switch in a

play15:55

switch it on it's switched on

play15:58

etc etc so the tests are here and very

play16:01

easy to to read so the last one is

play16:04

checking that if you oops

play16:07

if you start it with maxus one and

play16:10

switch it on off and then you try to

play16:12

switch it on again the resulting event

play16:14

is blue okay cool thing here with this

play16:17

with this this test is that the state

play16:20

never appears in the state so I can

play16:22

refactor the state as much as I want I

play16:25

never have to change the test this is

play16:27

pure Behavior driven test

play16:30

and you have seen all the framework I'm

play16:32

using like the

play16:34

SE lines okay this is my test framework

play16:37

to write this okay

play16:39

uh

play16:41

so this build thing I can there will be

play16:44

the cat after this thing the first thing

play16:46

I can do with this you will say okay you

play16:48

can test it but can I run it right so we

play16:52

can run it like this

play16:54

uh we'll create a smaller module in

play16:56

memory

play16:58

and create an instance of it with in

play17:03

memory

play17:06

in memory with my bulb decider

play17:10

and now I can send it some commands like

play17:13

for instance fit

play17:16

.fit

play17:19

and with the value

play17:21

dot Max uses is five okay

play17:26

and after that we can call it with

play17:29

another command which is a switch on

play17:35

and same but we switch off

play17:38

like that so I take my decider

play17:42

I didn't run the code before so it's not

play17:45

working of course

play17:46

here

play17:51

perfect

play17:52

and so just to show you that it's

play17:56

working I can run all the tests

play17:59

and

play18:02

we should get green

play18:04

freeware okay

play18:06

so I take my decider here okay I create

play18:10

an instant of it uh an instance to run

play18:14

it and you see that what I get is a

play18:16

function that takes a command and

play18:17

returns and evenly so I will pass some

play18:22

to some commands to this function here

play18:24

and it says okay the result is it was

play18:27

fitted with a Max use of five if I try

play18:29

it again I get an exception because you

play18:31

cannot fit it twice right but now I can

play18:34

switch it on okay switch on I can try to

play18:37

switch it on again nothing happens this

play18:39

is what we expect I switch it switch it

play18:43

off it switched off on off on Earth

play18:47

on earth once again and Bloom okay I

play18:53

know I can try anything nothing happens

play18:55

anymore okay so

play18:57

when you have a decider you can just run

play18:59

it like that I don't need an even store

play19:01

or anything I can just turn it I will

play19:04

show the cut just after the cool thing

play19:05

with that

play19:06

I can take the code I'll show you and I

play19:09

can for instance we have a new service

play19:12

that we that we want to to to to

play19:16

implement and first thing I do is I

play19:19

write my my domain code as a decider and

play19:25

I use this

play19:26

in memory function to run it I just put

play19:30

it behind your service and I put it into

play19:32

staging and people can start to play

play19:34

with it there is no persistence no event

play19:36

store no database but you can already

play19:38

test the domain logic from here okay and

play19:43

what is the magic for this in memory

play19:45

function

play19:46

it's very simple what it does it says

play19:48

give me your decider

play19:50

okay and I create a mutable variable

play19:53

called state which is equal to the

play19:56

decider initial state

play19:58

right and then I return a function that

play20:01

takes as a command

play20:02

and it will call the decide function

play20:04

with the command on the state I get some

play20:07

events

play20:09

with this event I use the level function

play20:11

on the current state to fold them and

play20:14

get a new current state that I store in

play20:16

the state again and just return the list

play20:18

of events that I computed

play20:21

right

play20:23

this idea running in Murray the cool

play20:26

thing with that is that you can take any

play20:28

domain logic written as a decider pass

play20:30

it to this function and it will run like

play20:32

that

play20:33

I don't need to rewrite the same blah

play20:36

blah blah running instantiate the thing

play20:39

because all deciders have the same shape

play20:41

I can write this code once and use it

play20:43

for any domain logic

play20:45

okay so next step

play20:48

no at some point I will so to test that

play20:52

it also work with something different I

play20:54

can test it with the cat so

play20:58

so I will not show the code for the cat

play21:01

because it says even simpler decider

play21:03

which can be awakened and it's just

play21:05

doing the thing okay so I take Creator

play21:07

in memory with the cat decider

play21:11

and I can

play21:14

cat dot wake up

play21:18

no we see here

play21:22

or I can get to sleep right so and

play21:28

instantiate it when I tried it was

play21:31

already woke up awake so if I try to

play21:35

wake him up and nothing happens but I

play21:37

get it to sleep wake up go to sleep I

play21:39

try to go to sleep again nothing happens

play21:41

and all that okay

play21:43

it's working and I'm just running the

play21:46

decider in memory no the thing we want

play21:48

to do

play21:49

is that we want to persist

play21:52

uh

play21:54

the state this way if we stop everything

play21:57

and we will start we will be in the same

play22:00

in the same position

play22:03

um the thing usually is that if you

play22:04

start with thing in memory and then you

play22:06

want to implement it with the database

play22:10

you get a bit in trouble because you

play22:13

will have to change your code

play22:16

here we will

play22:18

just do something like that

play22:21

module state

play22:24

and we will create so it states that run

play22:29

and for this I need to give a decider a

play22:34

bird decider and what I will do is that

play22:37

I also will give a serializer

play22:43

state serializer and the two last things

play22:47

I need to give is the container name

play22:49

this is a bulb and this is instance one

play22:52

okay

play22:53

like that

play22:55

I know I can just

play22:57

do the same thing as before sending

play22:59

command to this function

play23:01

and Magic here this is the ESC KV this

play23:06

is my toy implementation of key value

play23:09

store and even store

play23:12

only for educational purpose okay this

play23:15

is stated in the lessons you can use it

play23:17

if you want for your own demonstration

play23:18

right

play23:20

but only if you don't make money with it

play23:23

or you contact me and you see and never

play23:26

use it in production because it's not

play23:28

done for that it's really something to

play23:31

show how it works

play23:33

there is a client library to use eskv uh

play23:38

which has all the Primitives you find in

play23:41

any client for the events to her and for

play23:46

key value stores right but I try to

play23:49

reduce it to reduce at the maximum the

play23:52

complexity of demos okay so you do the

play23:55

same for your own infrastructure uh you

play23:58

you try to create the same kind of

play24:01

client API that I created for eskv and

play24:04

you will be able to do everything but in

play24:06

your production right but don't use a

play24:09

eskv for production

play24:10

uh the cool thing is that you it's very

play24:13

easy to install and all that you will

play24:15

look at my um and my GitHub and you will

play24:17

find it so now I have an instance and I

play24:20

fit the bulb and as you can see just

play24:22

appeared here in the key Value Store in

play24:24

the container bulb key one the value is

play24:28

of 5.

play24:29

cool you know if I try to build do fit

play24:33

it again it fails I can switch it on off

play24:36

and off

play24:38

on if I try on again nothing happens off

play24:41

on off on off on on the next call the

play24:45

state is blowing right so you see

play24:48

uh

play24:50

and as you can see I just took the same

play24:53

decider and run it and I saved the state

play24:56

so it will tell me yeah but we are here

play24:58

for even sourcing it's not even sourcing

play24:59

we are saving the state but the cool

play25:01

thing is that we will switch to even

play25:02

sourcing without changing the domain

play25:04

code either right so follow with me

play25:07

what's happening inside the state run

play25:09

function

play25:12

so it needs a decider on the serializer

play25:15

a serializer is just a pair of

play25:17

cellulitis and deserialized function

play25:19

right

play25:20

uh the serialized on this ILS function

play25:23

take your state and return the string or

play25:25

take a string and return the state and

play25:28

the container is key is just to to know

play25:30

where to store it in eskv so starting

play25:34

the skv is is really easy

play25:37

you create a client

play25:39

right

play25:41

and then what we have is these two

play25:45

functions this first one is a try load

play25:47

it takes a decile this iulized function

play25:50

the default value and the container in

play25:52

the key and it will call try load

play25:54

with the container on the key to get the

play25:56

string

play25:57

that is contained for this key okay I

play26:00

get a result if the key exists I take

play26:02

the value and this I realize it if it

play26:04

doesn't exist I take the default value

play26:06

now I have a value and I will result the

play26:08

value and the e-tag

play26:10

for this key so the e-tag is useful

play26:14

because the attack will change on each

play26:16

version of the document right and when I

play26:19

will

play26:20

save the document again I will check

play26:23

that the document has not changed

play26:25

between the moment I loaded it and the

play26:27

moment I save it right so the save is

play26:31

equally easy

play26:32

Texas cellular laser the container the

play26:35

key the state and the tag and it called

play26:39

try save

play26:40

uh with the key and it's a realize the

play26:44

state to a string it pathway tag if the

play26:48

state has changed I will get null and I

play26:50

can fail if the e-tag is not null I get

play26:55

a new tag but I will not use it so I

play26:57

just drop it so

play27:00

um

play27:01

know that I have these two very easy

play27:03

function I can use just use them

play27:06

so I

play27:08

use the tryload function to get the

play27:10

current state and the attack from the

play27:12

database

play27:13

now I can call the D type function with

play27:15

the command that has been provided to

play27:17

the function on the state I just loaded

play27:20

I get some events I use list fold with

play27:22

the evil function to get the new state

play27:25

right and I just save it

play27:27

okay I return the events and this is

play27:31

working and this is working for any

play27:33

designer right and this version as

play27:36

controlled optimistic concurrency

play27:38

checking because of the attack so if

play27:41

some other instance

play27:43

uh is messing with the state I will

play27:46

detect it between the load and the Save

play27:47

which should be super short anyway

play27:50

the other thing is that it's very easy

play27:52

to change this to keep state in memory I

play27:55

can create also a mutable variable load

play27:57

the state up front and then for each

play28:00

command

play28:01

I keep the e-tag for each command I will

play28:05

compute a new state try to save it if

play28:08

the tag has changed I will just reload

play28:10

the state from the database and each

play28:12

time I will update so I reload only if I

play28:15

have a conflict with the current state

play28:18

of the database so

play28:20

and once again I don't need to know

play28:22

anything about what's inside this

play28:24

designer just to know that it's a

play28:26

decider it can run for all your domain

play28:30

logic exactly the same way so I just

play28:32

need several versions of this run to

play28:35

implement the different loading saving

play28:38

keeping in memory patterns but the

play28:40

decided I don't care

play28:43

uh

play28:45

it's also working for cats of course

play28:48

let's see stat dot run

play28:52

cat dot decider I will just take the uh

play28:57

the cat

play28:59

state serializer

play29:03

and I will

play29:05

call it cat one and I have my two

play29:08

functions my two commands here

play29:11

yeah

play29:12

I wake it up it's awake I get it to

play29:15

sleep it's asleep if it's already asleep

play29:17

nothing happened and extra extra okay

play29:20

so super cool I have a cat on the light

play29:23

bulbs that are working now the question

play29:24

is but how do you use these deciders for

play29:28

even sourcing

play29:30

oh it's actually very easy module even

play29:34

sourcing

play29:38

so let B and I will say even sourcing

play29:42

dot run

play29:44

with my bulb decider

play29:48

bulb event serializer

play29:52

[Music]

play29:54

I don't have container on the streams

play29:56

yet but it will come Monday

play30:00

up

play30:02

up like that so I get it

play30:06

oh in my streams here I see this build

play30:09

one stream the first event is fitted if

play30:12

I try to run it again bam no I cannot I

play30:15

can switch it on off on off so you can

play30:19

see also the event uh

play30:22

I can switch on if I do it again nothing

play30:24

happened on off on

play30:28

under that time it's just blue and

play30:30

nothing happened anymore right so once

play30:33

again no I'm using even sourcing

play30:37

uh but totally without uh totally

play30:40

without a

play30:42

changing the code so for the

play30:45

infrastructure for this is just

play30:48

I load the events with my data laser

play30:51

from the stream so there is an easy API

play30:54

in eskave that just returns all the

play30:57

events from a stream

play30:58

I get the event on an expected version

play31:01

this is the current version of the

play31:02

Stream

play31:03

I fold all my events using the evil

play31:06

function I get the current state I pass

play31:09

the student state to the decide function

play31:11

with the command I get the new events

play31:13

you follow it's okay so I get the new

play31:15

events and then I open this event to the

play31:18

Stream

play31:19

passing the expected version if someone

play31:21

added new events to the stream in

play31:24

between it will be detected and I can do

play31:28

something more specific right

play31:31

so this is even sourcing now

play31:33

cool it's also working for the cat of

play31:36

course as you can guess

play31:37

but no the thing is that

play31:40

uh

play31:42

I have this small decider and I

play31:46

maybe I want to just run one thing and

play31:50

not two things like not two apis or

play31:52

something an API that will have things

play31:54

for the cat thing for the

play31:56

for the bulb and I want to put them

play32:00

together because uh in some ways this is

play32:03

so small they go together

play32:05

uh what what the first to to create all

play32:09

this infrastructure to run both okay

play32:11

so I have two decider

play32:14

is it possible to create a single

play32:16

decider

play32:18

and actually yes

play32:20

and this is where it gets interesting

play32:22

the thing here

play32:24

so I will go a bit

play32:27

here and we will create a compost

play32:29

function

play32:30

so this will be a bit harder to follow

play32:34

this is the code but I will not show you

play32:36

we will write it

play32:37

Okay so

play32:41

the only thing I will copy is the first

play32:43

line because it's a bit long to type

play32:45

the first two lines

play32:49

up

play32:52

like that

play32:54

so uh I need I want to write a compose

play32:59

function that will take an X decider

play33:01

okay that text comment of type CX

play33:05

that will return events of types e x and

play33:08

have a state of type SX okay and I have

play33:11

a second d y decider with the Cy ey Sy

play33:16

and what I want

play33:18

is a decideration can do both so it can

play33:22

take

play33:23

commands either

play33:25

from the first one the one on the left

play33:28

or for the second one the one on the

play33:30

right right and

play33:32

the decision taken from there for for

play33:35

from this decider can either be uh an

play33:39

event for the one on the left or an

play33:41

event from the white run one on the

play33:44

right okay

play33:45

and what is the state the state is just

play33:48

a pair of both States

play33:50

okay

play33:52

this is George repair the state of the

play33:54

bulb on the state of the cat

play33:56

okay so this is what the signature of

play33:58

this function is saying the either type

play34:01

is not a standard type in F sharp but I

play34:03

just wrote it here so it's either

play34:08

uh with two two type parameters and when

play34:11

the left side is of Type L on the right

play34:14

side is of type error

play34:17

so

play34:19

returning here the first thing we need

play34:21

in our decider is a decide function

play34:25

okay and as you decide function it will

play34:28

take a command

play34:31

I will say CMD for short and it will

play34:35

take a state and we know that the

play34:36

decider we want to provide

play34:39

its state is a pair of State okay so we

play34:42

will directly call the left part SX

play34:47

and the right part is why okay so it

play34:51

will get one pair and I call the left

play34:53

part of the pair SX on the right by part

play34:56

of the state Sy

play34:58

the command can be either a common for x

play35:01

or a command for a y so I will test it

play35:05

with a match

play35:07

on the command

play35:08

and if it's for the left

play35:11

we will call it CX recommend for X okay

play35:15

and no we know that we have a command

play35:17

for the left part so we will take the

play35:19

left decider and call the D side

play35:23

function from the last decider so the

play35:25

left decider is the X

play35:27

and I will call this side this digital

play35:30

except CX as a parameter on SX as a

play35:34

parameter okay and this will return

play35:36

events

play35:39

for the it will return events of the

play35:44

left decider so to be able to

play35:49

make it compatible with the others I

play35:52

will say they are on the left so I will

play35:54

just use

play35:57

I will just say there are on the left on

play35:59

all the events okay

play36:01

like that four

play36:03

if it's the right it will be equally

play36:06

easy

play36:07

so if it's the right I will call it Cy I

play36:12

will take the right decider the Y pass

play36:15

it

play36:16

the command with the state for the right

play36:20

and just say

play36:22

okay it's an event on the right

play36:25

and this is my decide function now what

play36:28

I can do is eval function

play36:30

so the function as you remember is

play36:32

taking a state that our state is still

play36:34

in two parts SX and s y and we have an

play36:37

event here

play36:39

so the thing is that we need to return a

play36:42

new state that will be computed with the

play36:44

2D slider we have so we will again match

play36:48

but this time we haven't uh to see if

play36:52

it's an event for the left or the right

play36:54

if it's for the left we call it e x

play36:58

and what we can call is the

play37:00

evil function from the DX decider

play37:04

with the state for x

play37:07

though even for x and what we get is

play37:10

just the new state for the left part so

play37:12

I will just put the same value for the

play37:15

right part like that

play37:17

okay

play37:19

but if it's for the right

play37:23

it will be an event for y I will use the

play37:26

Y evolve function

play37:28

uh with the state for right for y and

play37:33

the event and

play37:34

I will keep the same value on the left

play37:38

okay

play37:43

uh yes uh where yes why like that uh

play37:49

uh

play37:50

the next thing is the initial state

play37:54

initial state

play37:57

the initial state is easy because it

play37:58

will be the initial state from the DX

play38:01

decider on the left

play38:04

and the initial state of the d y decider

play38:06

on the right

play38:08

and

play38:09

lastly the is terminal function

play38:13

this is a function that will take a

play38:15

state so we will call SX the left

play38:18

pattern as why the right part and we'll

play38:20

just say test that SX is this terminal

play38:22

state

play38:24

on the

play38:26

X on the left decider and that Sy is the

play38:31

terminal State on the right decider

play38:35

like that and as you see yeah it it

play38:37

works right so this is awesome I know we

play38:41

can create a bulb

play38:43

and cat a cat and bulb uh decider let's

play38:48

try it

play38:49

you'll

play38:53

chat

play38:55

and bulb

play38:57

so let CNB it will be shorter c and b

play39:03

and to create so to create the decider

play39:07

uh I will

play39:10

just created it here let's get and verb

play39:15

equal and I will use a decider dot

play39:18

compose function to take the cat decider

play39:22

and the bulb decider

play39:25

I know I get a cation belt decider

play39:28

so the thing is that you can apply this

play39:30

compose function to any decider you will

play39:32

write with your on-demand logic of

play39:33

course not just with the cotton bulb it

play39:36

will work okay and we can run it in

play39:38

memory

play39:39

CNB

play39:41

in memory

play39:45

and I will need the cat and bulb decider

play39:49

here right and then I can give it some

play39:55

some function so I already wrote this to

play40:00

gain some time so here I can so to to

play40:05

pass

play40:06

a comment to the cat I have to say that

play40:10

it's on the left okay because this

play40:11

slider is only accepting cat command on

play40:14

the left and bulb command on the right

play40:17

so I wake up look at nothing happens

play40:20

because it's already awake you go to

play40:22

sleep awake left go to sleep and then I

play40:25

can fit the bulb switch on switch off

play40:28

on off right and the cool thing is that

play40:31

I can also run it not in memory but uh

play40:36

as in

play40:38

with the state so I will just go here

play40:42

uh

play40:45

this one

play40:47

yes no this is not the one I wanted in

play40:50

memory card on

play40:52

I have a lot of things

play41:00

so the thing is that here I also compose

play41:02

a serializer together to be able to take

play41:05

two serializer and make a single one

play41:07

and then I can do this and as you can

play41:11

see on the left of the pipe on the right

play41:13

you have the state of the skirt and on

play41:15

the right state of the of the bulb

play41:18

so I can switch on off and go to sleep

play41:22

awake

play41:24

switch on switch off

play41:26

on off

play41:28

on off and it just blown right

play41:33

so uh I can take two aggregate two

play41:38

deciders on the other single decider but

play41:40

what I can do now is that I can take

play41:42

another decided and combine it with this

play41:44

one right

play41:46

and the fun thing is that we can also

play41:48

create a neutral decider

play41:50

like this which is a decider that you

play41:53

cannot use and that does nothing why

play41:56

because the command is void which is a

play41:59

type which has no value so you cannot

play42:01

create a value of it so you cannot

play42:02

create a command of type void and it has

play42:05

no event because it's of type void until

play42:08

that it has a single state which is the

play42:10

value of unit which has a single value

play42:12

which is a parenthesis parenthesis right

play42:15

and the decide function just says

play42:18

whatever you ask me I return nothing

play42:20

when you ask me to evolve I keep the

play42:24

same state my initial state is the only

play42:26

value I have which is boundary is bound

play42:28

to this and it's always terminal right

play42:31

no I if I take a decider and I composite

play42:35

with this I get another decider but

play42:38

which can do exactly the same thing as

play42:40

the this later I composed with it right

play42:42

so actually this is a neutral element

play42:45

for the operation which says that the

play42:47

operation is monoidal

play42:53

because we have different shape but that

play42:55

those exactly just do the same thing

play42:57

something that is interesting also is

play43:00

that we we when you have a cat uh you

play43:03

can run a cat but if you want to run

play43:05

many cats it can be cumbersome to

play43:07

combine them all together as a single

play43:09

decider so there is a mini operator

play43:11

which take a decider and will return a

play43:14

decider for many instances of the same

play43:16

thing right so the thing is that in this

play43:19

decider

play43:20

uh each of the instance will have a

play43:23

string identifier okay you can choose a

play43:25

different type of a string but it was

play43:28

easier for the demo uh and each time the

play43:31

command will be

play43:32

the name of the thing and the command

play43:34

the event will be the name of the thing

play43:37

on the event and the state will be a map

play43:39

a dictionary of string and the state of

play43:42

this thing right and so the decide

play43:46

function it will receive a command which

play43:48

is actually an identifier and the

play43:51

command for the inside decider on all

play43:55

the states so we try to find the state

play43:56

in the map and if we cannot find it we

play43:58

return the initial state

play44:00

we have a state we call the decide

play44:02

function we get some event and we just

play44:04

add the ID on each event and no we can

play44:08

decide for many things

play44:10

okay the evil function is quite similar

play44:13

we have an idea with the event so we try

play44:16

to find the state or we use the initial

play44:18

State and we use the evil function to

play44:20

compute the new state and we replace the

play44:22

replace the state for this identifier in

play44:25

the in the dictionary

play44:27

the initial status is an empty map

play44:30

and there isn't this terminal function

play44:32

check that all the values in the map are

play44:36

terminal for the decider and with this I

play44:40

can run many cats so I will run many

play44:43

cats

play44:44

uh kids a bit further so many cats uh I

play44:50

will run it with uh with the state

play44:53

so the first cat is called bullet

play44:55

because this is the the name of of my

play44:58

cat Okay uh

play45:00

uh and when I put it to sleep you can

play45:02

see that the state is a bullet is asleep

play45:05

and I can wake it up and awake either

play45:09

cat I know and I can wake it and with a

play45:12

single decider I can run many cats

play45:15

next interesting things also is that I

play45:17

have a process

play45:19

so a process is a state machine and the

play45:21

process will I have four minutes left

play45:24

process will evolve so a process listen

play45:27

to mostly events will emit commands and

play45:31

have a inner states so we have an evil

play45:34

function that is similar to the other

play45:36

one

play45:37

the react function says when I'm in in

play45:40

this new state and this event just

play45:42

offshore is this here is the list of

play45:44

commands that we must send

play45:47

resume is when you just resume the

play45:50

process after a crash it just Returns

play45:53

the thing it has an initial date also

play45:56

it's terminal also

play45:58

I have every process that when a light

play46:02

is switched on

play46:03

it will wake up the cat and we will know

play46:06

that the cat is like awake because we

play46:10

will see the woke up

play46:12

event so my state is either idle the

play46:18

process is just waiting for the light to

play46:20

switch on or waking up it's sending the

play46:22

command but it does not the confirmation

play46:24

yet that it has been done so it will

play46:27

stay in this stage and when we

play46:30

receive the workout event we will go in

play46:32

idle State again so it looks a bit like

play46:35

the decider but with different function

play46:37

so we switched on a waking up

play46:40

when it's woke up it will go to idle

play46:42

state

play46:44

when it's waking up in because we

play46:47

switched on it will return backup and

play46:51

the initial state is idle

play46:53

and the cool thing with that is that we

play46:55

can combine

play46:57

this process with the decider so I'll do

play47:00

with that we do that the thing is that

play47:02

we take a process

play47:06

on the decider and this decider will be

play47:09

already the combination of the cat on

play47:12

the bulb okay and I will take this this

play47:15

uh this side there on my

play47:18

process that will wake up the cat when

play47:21

the light switch on okay so it doesn't

play47:24

get the cat to sleep when it switch off

play47:26

of course because the cat never go to

play47:28

sleep when you want

play47:31

um so uh it has a decide function so the

play47:34

thing is I get a function and I get the

play47:36

state for the decider on the process

play47:39

and what I will do is that I will take

play47:42

this command

play47:43

right and pass it to this Loop so this

play47:47

Loop will

play47:49

accumulate events over several commands

play47:52

because the thing is that we have an

play47:54

input command but the process May

play47:57

trigger other comments that will produce

play48:00

a new state so the first thing is that

play48:02

if I still have common to process I call

play48:05

it command this is a year document

play48:07

highlighting and I compute the event for

play48:10

this command in my decider

play48:13

and this event I will use my process to

play48:17

collect new commands for each event so

play48:20

this is the collect folder function

play48:22

what it does it says okay so I'm in a

play48:26

state I have some events and I have

play48:28

nothing to return

play48:29

uh uh and when I have an event I will

play48:32

evolve the process first okay with my

play48:36

current state on the the list of events

play48:39

I get a new state

play48:41

I call react on the process that can

play48:45

return me one or multiple comments and I

play48:47

put them in my result

play48:49

and then I take the next event on my new

play48:52

state and do it again until I have no

play48:55

event to process and in the end I have

play48:57

the the list of all the comments I need

play49:00

to to to to to process after

play49:04

and what I do is that once I have all

play49:07

this new command I will just put it in

play49:09

the list

play49:10

and do it again it will go through the

play49:12

deciders that will produce new events

play49:15

that may produce new events that go to

play49:18

the process that could produce new

play49:20

commands but eventually there will be no

play49:25

more common to send because everything

play49:26

in the right State and at that time I

play49:29

have collected all the events generated

play49:31

by the decider okay so now I can use

play49:36

this combine

play49:37

with decider and go quickly to show you

play49:42

how it works

play49:44

so here I will combine the

play49:48

uh

play49:49

uh yes I know yeah adapted process is

play49:52

here so this is just a small helper to

play49:55

to convert the event from the decider to

play49:57

the

play49:58

process of the rest

play50:01

yes I need to run both at the same time

play50:03

yes almost

play50:06

this is my

play50:09

new version of this of course it will

play50:12

not work

play50:13

demo effect

play50:15

ah

play50:17

[Music]

play50:19

why okay

play50:23

[Laughter]

play50:25

yes I will just run everything because

play50:29

yeah I made some change on the way

play50:33

uh

play50:36

[Music]

play50:40

with process yes

play50:45

and here

play50:50

like that no okay

play50:53

no it's not working okay so I explained

play50:55

what is happening so when I do this

play50:59

uh I take my combined decider with a cat

play51:03

on the bulb I take my process and I get

play51:06

a new decider right

play51:09

so this decider I can run it with any of

play51:12

the other function I wrote before but no

play51:15

when I get the cat to sleep and then I

play51:19

switch the light on I get both the light

play51:22

is switched on and look at woke up right

play51:27

so

play51:30

I had two deciders

play51:34

that I could I can still run

play51:37

independently using two different run

play51:40

functions I have a process that can also

play51:44

run independently using a process run

play51:45

function I can Bridge everything with an

play51:48

event store and all that but again also

play51:50

using just this few line of code put

play51:52

them together on every single thing okay

play51:55

but I don't need to change the code

play51:59

either for the cat for the bulb or for

play52:02

the process to move from one setting to

play52:06

another I can just

play52:08

glue them with standard operators

play52:11

and get all the things running as a

play52:13

single unit okay so the interesting idea

play52:16

is that you instead of thinking what

play52:18

should be the side of my uh aggregate

play52:21

you can think I will Design the small

play52:24

thing I will Design the processor glue

play52:26

that from them together and then I will

play52:28

think how I run this right use the

play52:31

operator I've shown

play52:33

compose uh on the combined with the

play52:37

decider and all that and you get two

play52:39

single thing that is still a decider and

play52:41

that you can run in memory with the

play52:44

state database or with an even store the

play52:48

same way

play52:49

you're free to choose and you can always

play52:52

choose letter and you can move from one

play52:55

version to the other like starting in

play52:58

memory State and then even sourcing and

play53:01

that's just the same code so

play53:03

I think my time is over so thank you

play53:06

very much I hope that you like it

play53:10

[Music]

Rate This

5.0 / 5 (0 votes)

Related Tags
集約構成デシダーアーキテクトホテル予約外国企業技術発展状態管理イベントソーシングコードサンプル
Do you need a summary in English?