Introducing Eager Design

96
Eager Design by @_md marcello duarte Introducing

Transcript of Introducing Eager Design

Eager Designby @_md

♞marcello duarte

Introducing

marcello duarte

@_md

#EagerDesign

agile is lazy

@_md#EagerDesign

"Make the commitment at the last responsible moment"

Preston Smith

decide later

software is about people

@_md#EagerDesign

age of excess

@_md#EagerDesign

subtraction

@_md#EagerDesign

subtraction��� ���

@_md#EagerDesign

laws of subtraction

@_md

laws of subtraction

what isn’t there can often trump what is. the simplest rules create the most effective experience. limiting information engages imagination. creativity thrives under intelligent constraints. break is the important part of breakthrough. doing something isn’t always better than doing nothing.

Matthew E. May

Eager Design

how♞

Jump to the problem worth solving Eagerly replace primitives with types Compose [the domain algebra] inside-out Avoid mutable state

#1 #2 #3 #4

@_md#EagerDesign

outside-in

outside-in

unit test code

refactor

acceptance

ui/controller/views

orm, libs, domain objects

framework stuff (forms…)

model/view/controller

events

outside-inUI

Domain

core

Application

Infrastructure

mobile UI

port/adapter

port/adapterDB

http

s://p

bs.tw

img.

com

/med

ia/C

HyU

AukW

gAA5

iYS.

jpg

reads

writes

the right outside

http://bit.ly/modellingbyexample

http://bit.ly/whencucumbersgobad

@_md#EagerDesign

{ outside-inslow misleading complex restricts composability

when?

Eager Designwh

endone trivial

donenot trivial

not done

no idea[based on Cynefin, Snowden 03]

@_md#EagerDesign

Eager Designwh

endone trivial

donenot trivial

not done

no idea[based on Cynefin, Snowden 03]

Outside-in

@_md#EagerDesign

Eager Designwh

endone trivial

donenot trivial

not done

no idea[based on Cynefin, Snowden 03]

Eager Design

Outside-in

@_md#EagerDesign

Eager Designwh

endone trivial

donenot trivial

not done

no idea[based on Cynefin, Snowden 03]

Eager Design

Outside-in

¯\_(ツ)_/¯

@_md#EagerDesign

Example

{ chess appwe add players it generates the schedule we can enter the results we can see the ranking

TRIVIA

L

TRIVIA

L

TRIVIA

L

Eager Design

@_md

{ domain rulesplayers will play with every other player

players can't play twice in the same round

every player must play in every round

players must play twice with another player

@_md

How do I converta list of things

into a list of unique listsof unique pairs?

Let me think

a b c d e f g hList of things

a b c d e f g hList of things

Pairsa b c dh g f e

Pairs

a b c d

h g f e

Shift to the right

a b c d

h g f ee

We haz roundz! :o)

a b c d

h g f ee

r1 r2 r3 r4

r5 r6 r7

+r1 r2 r3 r4

r5 r6 r7

inverse( )

r1 r2 r3 r4

r5 r6 r7 r8

r9 r10 r11 r12

r13 r14

shuffle( )

laws of subtraction

what isn’t there can often trump what is. the simplest rules create the most effective experience. limiting information engages imagination. creativity thrives under intelligent constraints. break is the important part of breakthrough. doing something isn’t always better than doing nothing.

Matthew E. May

#1 Jump to the problem worth solving

@_md#EagerDesign

http://github.com/MarcelloDuarte/phunkie

ImmList

a b c d e f g hhead

a b c d e f g htail

a b c d e f g hinit

a b c d e f g hlast

concat( head($players), last($players), init(tail($players))

function shift(ImmList $players){ return concat(head($players), last($players), init(tail($players)) );}

function shift(ImmList $players){ return concat(head($players), last($players), init(tail($players)) );}

function round(ImmList $players) { $sides = $players->splitAt($players->length/2); return $sides->_1->zip($sides->_2->reverse());}

function rounds(ImmList $players) {

}

function rounds(ImmList $players, $rounds = []) { $rounds[] = round($players);

return count($rounds) < $players->length - 1 ? rounds(shift($players), $rounds) : ImmList(...$rounds);}

function rounds(ImmList $players, $rounds = []){ $rounds[] = round($players);

return count($rounds) < $players->length - 1 ? rounds(shift($players), $rounds) : ImmList(...$rounds);}

function rounds(ImmList $players, $rounds = []){ $rounds[] = round($players);

return count($rounds) < $players->length - 1 ? rounds(shift($players), $rounds) : ImmList(...$rounds);}

function rounds(ImmList $players, $rounds = []){ $rounds[] = round($players);

return count($rounds) < $players->length - 1 ? rounds(shift($players), $rounds) : ImmList(...$rounds);}

#3 Compose

function rounds(ImmList $players, $rounds = []){ $rounds[] = round($players);

return count($rounds) < $players->length - 1 ? rounds(shift($players), $rounds) : ImmList(...$rounds);}

#4 Avoid mutable state

function rounds(ImmList $players, $rounds = []) { $rounds[] = round($players);

return count($rounds) < $players->length - 1 ? rounds(shift($players), $rounds) : ImmList(...$rounds);}

function schedule(ImmList $players) { return concat(rounds($players), inverse(rounds($players));}

#2 Eagerly replace primitives with types

@_md#EagerDesign

“My math background made me realise that each object could have several

algebras associated with it, and there could be families of these, and that these

would be very very useful...

...I made up a term "genericity" fordealing with generic behaviours in a

quasi-algebraic form...

...I didn't like the way Simula I or Simula 67 did inheritance. So I decided to leave

out inheritance as a built-in feature until I understood it better.”

Alan Kay

http://bit.ly/meaning-­‐of-­‐oo

type Player = string;type Players = ImmList<Player>; type Match = Pair<Player,Player> type Round = ImmList<Match>; type Rounds = ImmList<Round>; type Schedule = Rounds;

function shift(Players $players): Players{ return concat(head($players), last($players), init(tail($players)) );}

function round(Players $players): Round { $sides = $players->splitAt($players->length/2); return $sides->_1->zip($sides->_2->reverse());}

function rounds(Players $players, $rounds = []) : Rounds{ $rounds[] = round($players);

return count($rounds) < $players->length - 1 ? rounds(shift($players), $rounds) : ImmList(...$rounds);}

function schedule(Players $players): Rounds { return concat(rounds($players), inverse(rounds($players));}

Compose the domain algebra inside-out

@_md#EagerDesign

namespace Md\Chess\ScheduleGeneration;

shift(Players $players): Players round(Players $players): Roundrounds(Players $players): Roundsschedule(Players $players): Schedule

Players => Schedule

Players => Rounds => Schedule

Players => Round => Rounds => Schedule

domain rules are defined against types

@_md#EagerDesign

{ domain rulesplayers will play with every other player

players can't play twice in the same round

every player must play in every round

players must play twice with another player

@_md

rich domain model vs lean domain model

S

S

S

S

S

S

@_md#EagerDesign

rich domain

Immu

table S

tate

Immu

table S

tate

Immu

table S

tate

B B

lean domain

Laws

Interpreting Services Agency

Example

@_md#EagerDesign

def request def decline def amend def accept def done

def request(details:JobDetails): Job def decline(ref:JobRef): Job def amend(details:JobDetails): Job => Option[TimeSheet] def accept(ref:JobRef): Job => Option[TimeSheet] def done(ref:JobRef): TimeSheet => Remittance

trait JobService

{ def request(details:JobDetails): Job def decline(ref:JobRef): Job def amend(details:JobDetails): Job => Option[TimeSheet] def accept(ref:JobRef): Job => Option[TimeSheet] def done(ref:JobRef): TimeSheet => Remittance

}

trait JobService

{ def request(details:JobDetails): Job def decline(ref:JobRef): Job def amend(details:JobDetails): Job => Option[TimeSheet] def accept(ref:JobRef): Job => Option[TimeSheet] def done(ref:JobRef): TimeSheet => Remittance

}

f(a:A):M[B]

g(a:B):M[C]

f(a:A):M[B]

f(a) map g = M[M[C]]

g(a:B):M[C]

f(a:A):M[B]

join f(a) map g = M[C]

g(a:B):M[C]

f(a:A):M[B]

andThen

g(a:B):M[C]

request andThenamend andThendone

def execute(input:Input): Unit path = input("path").getOrElse("specs")

loadSpecs(path) andThen runSpecs andThen presentResults

what’s the eager point?

@_md#EagerDesign

merging 2 cells!!

@_md#EagerDesign

{ 3 casessame value different value right hand side is empty

if ($this->value == $another->value) {

return Pair(Cell(), Cell($this->value + $another->value));

} elseif ($another->isEmpty()) {

return Pair(Cell(), Cell($this->value));

}

return Pair(Cell($this->value), Cell($another->value));

if ($this->value == $another->value) {

return Pair(Cell(), Cell($this->value + $another->value));

} elseif ($another->isEmpty()) {

return Pair(Cell(), Cell($this->value));

}

return Pair(Cell($this->value), Cell($another->value));

if ($this->value == $another->value) {

return Pair(Cell(), Cell($this->value + $another->value));

} elseif ($another->isEmpty()) {

return Pair(Cell(), Cell($this->value));

}

return Pair(Cell($this->value), Cell($another->value));

function swipe($lines){ return $lines->map(function ($line) { $lineCopy = mergeLine($line);

while (!isLineMerged($lineCopy)) { $lineCopy = mergeLine($lineCopy); }

return $lineCopy; }); }

Eager Design

Jump to the problem worth solving Eagerly replace primitives with types Compose [the domain algebra] inside-out Avoid mutable state

#1 #2 #3 #4

@_md#EagerDesign

marcello duarte

@_md

#EagerDesign

Thank you!

@_md

bit.ly/inviqa-contact bit.ly/inviqa-careers

#EagerDesign