Slide 1

Slide 1 text

{The Enemy oF] [the State] Joy Clark

Slide 2

Slide 2 text

Joy Clark Consultant @ innoQ joy.clark@innoq.com @iamjoyclark

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

state noun the particular condition that someone or something is in at a specific time. @iamjoyclark

Slide 5

Slide 5 text

So what is the problem with state? @iamjoyclark

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

@iamjoyclark

Slide 8

Slide 8 text

@iamjoyclark

Slide 9

Slide 9 text

@iamjoyclark

Slide 10

Slide 10 text

some state is.. @iamjoyclark

Slide 11

Slide 11 text

How can I identify essential state? @iamjoyclark

Slide 12

Slide 12 text

One Tool: Domain Driven Design! @iamjoyclark

Slide 13

Slide 13 text

DDD Building Blocks > immutable > no lifecycle > constant identity > value can change over time ValueObject Entities Aggregates > extra grouping > transactional boundary @iamjoyclark

Slide 14

Slide 14 text

Entities and Aggregates represent the essential state of the system @iamjoyclark

Slide 15

Slide 15 text

Other state in an application is @iamjoyclark

Slide 16

Slide 16 text

state handling can be a source of @iamjoyclark

Slide 17

Slide 17 text

is Technical Debt @iamjoyclark

Slide 18

Slide 18 text

Why does state increase complexity? @iamjoyclark

Slide 19

Slide 19 text

State intertwines the value of an entity with time @iamjoyclark

Slide 20

Slide 20 text

And if there are dependencies between stateful components… @iamjoyclark

Slide 21

Slide 21 text

What can we do about it? @iamjoyclark

Slide 22

Slide 22 text

@iamjoyclark

Slide 23

Slide 23 text

How do different paradigms deal with state? @iamjoyclark

Slide 24

Slide 24 text

An example entity… @iamjoyclark

Slide 25

Slide 25 text

Character #1 @iamjoyclark

Slide 26

Slide 26 text

Character #2 @iamjoyclark

Slide 27

Slide 27 text

Character #3 @iamjoyclark

Slide 28

Slide 28 text

The value changes over time! @iamjoyclark

Slide 29

Slide 29 text

Commodore 64 Basic Jens Bendisposto https://twitter.com/jbendisposto/status/904662544245297152 1 LET JAR = 0 10 DATA "GRANNY", "MONSTER", "GRANNY", "CAT", "END" 20 READ A$ 100 IF A$="GRANNY" THEN GOSUB 1010 200 IF A$="MONSTER" THEN GOSUB 2010 300 IF A$="CAT" THEN GOSUB 3020 400 IF A$="END" THEN GOTO 10000 500 GOTO 20 1010 LET JAR = JAR + 4 1015 PRINT "YOU LOOK SKINNY, GET SOME COOKIES" 1020 RETURN 2010 IF JAR = 0 THEN PRINT "NO COOOKIE, ME SAD" 2020 IF JAR > 0 THEN PRINT "OM NOM NOM" 2030 LET JAR = 0 2040 RETURN 3020 PRINT "MEOW" 3030 LET JAR = JAR - 1 3040 RETURN 10000 END READY.

Slide 30

Slide 30 text

Object-Oriented class CookieJar def initialize(initial_count) @count = initial_count end def remove_cookies(amount) if amount > @count @count = 0 else @count -= amount end end def add_cookies(amount) @count += amount end end Lucas Dohmen https://gist.github.com/moonglum/f763eb257a4ede22e3008d861225535c

Slide 31

Slide 31 text

Functional (with MONADS!) takeCookies n jar = if n > jar then 0 else jar - n cat = modify (takeCookies 1) grandma = modify (+10) cookieMonster = put 0 workflow = do cat cookieMonster grandma cookieMonster run = execState workflow 5 Martin Kühl https://gist.github.com/joyclark/843932d96dbf99ab8438cb9de485d10f

Slide 32

Slide 32 text

Functional (defn take [{cookies ::cookies} to-take] (if (< to-take cookies) {::cookies (- cookies to-take)} {::cookies 0})) (defn cookie-monster [cookie-jar to-eat] (take cookie-jar to-eat)) (defn kitten [cookie-jar] (take cookie-jar 1)) (defn grandma [{cookies ::cookies} nr-baked] (if (pos? nr-baked) {::cookies (+ cookies nr-baked)} {::cookies cookies})) Joy Clark https://github.com/joyclark/cookie-jar

Slide 33

Slide 33 text

well that wasn’t that bad… @iamjoyclark

Slide 34

Slide 34 text

@iamjoyclark

Slide 35

Slide 35 text

@iamjoyclark

Slide 36

Slide 36 text

We are not alone! A friendly ghost with an appetite for cookies has started haunting the kitchen. And if the ghost reaches into the cookie jar at the same time as someone else… @iamjoyclark

Slide 37

Slide 37 text

@iamjoyclark

Slide 38

Slide 38 text

In an otherworldly dimension… In the kitchen… cookie_jar = CookieJar.new(5) cookie_jar.remove_cookies(3) ⋮ amount > @count => false ⋮ @count -= amount ⋮ cookie_jar.count_cookies => -2 cookie_jar.remove_cookies(4) ⋮ amount > @count => false ⋮ @count -= amount @iamjoyclark

Slide 39

Slide 39 text

What do we do? @iamjoyclark

Slide 40

Slide 40 text

Object-Oriented: Locks public IList TakeCookies(int aNumberOfCookies) { var cookies = new List(); lock (_jarLid) { // take cookies out!! } return cookies; } Benjamin Wolf https://github.com/programming-wolf/CookieJar

Slide 41

Slide 41 text

Object-Oriented: Locks class CookieJar @@jarLid = Mutex.new def remove_cookies(amount) @@jarLid.synchronize do if amount > @count @count = 0 else @count -= amount end end end end Lucas Dohmen https://gist.github.com/moonglum/f763eb257a4ede22e3008d861225535c

Slide 42

Slide 42 text

In an otherworldly dimension… In the kitchen… cookie_jar = CookieJar.new(5) cookie_jar.remove_cookies(3) ## The lid is off for kitten! amount > @count => false @count -= amount cookie_jar.count_cookies => 2 cookie_jar.remove_cookies(4) ## The lid is off for kitten! ## We’ll wait until it’s back on ## The lid is off for ghost! amount > @count => false @count = 0 cookie_jar.count_cookies => 0 @iamjoyclark

Slide 43

Slide 43 text

Functional (def cookie-jar (atom {::cookies 5})) (defn ghost [cookie-jar] (take cookie-jar 2)) (swap! cookie-jar grandma 5) (swap! cookie-jar kitten) (swap! cookie-jar ghost) @cookie-jar // => 7: retrieves current value of cookie-jar Joy Clark https://github.com/joyclark/cookie-jar

Slide 44

Slide 44 text

swap! explained @iamjoyclark

Slide 45

Slide 45 text

In an otherworldly dimension… In the kitchen… (def cookie-jar (atom {::cookies 5})) (swap! cookie-jar grandma 5) @cookie-jar => {::cookies 8} (swap! cookie-jar ghost) swap! retrieve {::cookies 5} (grandma {::cookies 5} 5) save! {::cookies 10} swap! retrieve {::cookies 5} (ghost {::cookies 5}) atom changed, retry! retrieve {::cookies 10} (ghost {::cookies 10}) save! {::cookies 8} @iamjoyclark

Slide 46

Slide 46 text

@iamjoyclark is really hard. But it’s something we absolutely have to consider!

Slide 47

Slide 47 text

but that’s it, right? … @iamjoyclark

Slide 48

Slide 48 text

@iamjoyclark

Slide 49

Slide 49 text

@iamjoyclark

Slide 50

Slide 50 text

@iamjoyclark

Slide 51

Slide 51 text

Is there a way to reproduce the chain of events? @iamjoyclark

Slide 52

Slide 52 text

Event Sourcing > The state of the application is determined by a sequence of business events. > Reproducibility of the states @iamjoyclark

Slide 53

Slide 53 text

Event Sourcing Cookie Jar created 1 eaten 4 eaten 6 eaten 10 baked current state @iamjoyclark

Slide 54

Slide 54 text

@iamjoyclark can be achieved by persisting the changes that have been made in our system

Slide 55

Slide 55 text

In summary… @iamjoyclark

Slide 56

Slide 56 text

How to Attack Think about the problem you are trying to solve. Identify essential state and encapsulate it. Eliminate unnecessary state. @iamjoyclark

Slide 57

Slide 57 text

How to Attack Prefer immutable values which are thread safe. Use locking and synchronized blocks. @iamjoyclark Look into what that your language offers for managing concurrency

Slide 58

Slide 58 text

How to Attack @iamjoyclark Derive the state from the events or transactions which have taken place Make sure that you are logging all necessary information

Slide 59

Slide 59 text

More Cookie Jar Examples https://github.com/joyclark/cookie-jar

Slide 60

Slide 60 text

www.innoq.com Joy Clark | @iamjoyclark | joy.clark@innoq.com https://github.com/joyclark/cookie-jar Managing state is hard… …so let’s get started!