EagerDesign
by @_md
♞
marcelloduarte
Introducing
marcelloduarte
@_md
#EagerDesign
agileislazy
@_md#EagerDesign
"Makethecommitmentatthelast

responsiblemoment"
Preston Smith
decide later
softwareisaboutpeople
@_md#EagerDesign
ageofexcess
@_md#EagerDesign
subtraction
@_md#EagerDesign
subtraction
@_md#EagerDesign
lawsofsubtraction
@_md
lawsofsubtraction
whatisn’ttherecanoftentrumpwhatis.thesimplest
rulescreatethemosteffectiveexperience.limiting
informationengagesimagination.creativitythrives
underintelligentconstraints.breakistheimportant
partofbreakthrough.doingsomethingisn’talways
betterthandoingnothing.
Matthew E. May
EagerDesign
how
♞
Jumptotheproblemworthsolving
Eagerlyreplaceprimitiveswithtypes
Compose[thedomainalgebra] inside-out
Avoidmutablestate
#1
#2
#3
#4
@_md#EagerDesign
outside-in
♞
outside-in
unittest code
refactor
acceptance
ui/controller/views
orm,libs,domainobjects
frameworkstuff(forms…)
model/view/controller
events
outside-in
UI
Domain
core
Application
Infrastructure
mobileUI
port/adapter
port/adapterDB
https://pbs.twimg.com/media/CHyUAukWgAA5iYS.jpg
reads
writes
therightoutside
http://bit.ly/modellingbyexample
http://bit.ly/whencucumbersgobad
@_md#EagerDesign
{
outside-in
slow
misleading
complex
restrictscomposability
when?
EagerDesign
when
done
trivial
done

nottrivial
notdone
noidea
[based on Cynefin, Snowden 03]
@_md#EagerDesign
EagerDesign
when
done
trivial
done

nottrivial
notdone
noidea
[based on Cynefin, Snowden 03]
Outside-in
@_md#EagerDesign
EagerDesign
when
done
trivial
done

nottrivial
notdone
noidea
[based on Cynefin, Snowden 03]
EagerDesign
Outside-in
@_md#EagerDesign
EagerDesign
when
done
trivial
done

nottrivial
notdone
noidea
[based on Cynefin, Snowden 03]
EagerDesign
Outside-in
¯_(ツ)_/¯
@_md#EagerDesign
Example
{
chessapp
weaddplayers
itgeneratestheschedule
wecanentertheresults
wecanseetheranking
TRIVIAL
TRIVIAL
TRIVIAL
EagerDesign
@_md
{
domainrules
playerswillplaywitheveryotherplayer
playerscan'tplaytwiceinthesameround
everyplayermustplayineveryround
playersmustplaytwicewithanotherplayer
@_md
HowdoIconvert

alistofthings

intoalistofuniquelists

ofuniquepairs?
Letmethink
a b c d e f g h
List of things
a b c d e f g h
List of things
Pairs
a b c d
h 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
( )
lawsofsubtraction
whatisn’ttherecanoftentrumpwhatis.thesimplest
rulescreatethemosteffectiveexperience.limiting
informationengagesimagination.creativitythrives
underintelligentconstraints.breakistheimportant
partofbreakthrough.doingsomethingisn’talways
betterthandoingnothing.
Matthew E. May
#1Jumptotheproblemworthsolving
@_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);
}
#3Compose
function rounds(ImmList $players, $rounds = [])

{
$rounds[] = round($players);
return count($rounds) < $players->length - 1 ?
rounds(shift($players), $rounds) :

ImmList(...$rounds);
}
#4Avoidmutablestate
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));
}
#2Eagerlyreplaceprimitiveswithtypes
@_md#EagerDesign
“Mymathbackgroundmademerealise
thateachobjectcouldhaveseveral
algebrasassociatedwithit,andthere
couldbefamiliesofthese,andthatthese
wouldbeveryveryuseful...
...Imadeupaterm"genericity"for

dealingwithgenericbehavioursina

quasi-algebraicform...
...Ididn'tlikethewaySimulaIorSimula
67didinheritance.SoIdecidedtoleave
outinheritanceasabuilt-infeatureuntilI
understooditbetter.”
AlanKay
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));
}
Composethedomainalgebra
inside-out
@_md#EagerDesign
namespace MdChessScheduleGeneration;
shift(Players $players): Players

round(Players $players): Round
rounds(Players $players): Rounds
schedule(Players $players): Schedule
♞
Players => Schedule
Players => Rounds => Schedule
♞
Players => Round => Rounds => Schedule
♞
domainrulesaredefined
againsttypes
@_md#EagerDesign
{
domainrules
playerswillplaywitheveryotherplayer
playerscan'tplaytwiceinthesameround
everyplayermustplayineveryround
playersmustplaytwicewithanotherplayer
@_md
richdomainmodelvs

leandomainmodel
S
S
S
S
S
S
@_md#EagerDesign
richdomain
ImmutableState
ImmutableState
ImmutableState
B B
leandomain
Laws
InterpretingServicesAgency
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 andThen
amend andThen
done
def execute(input:Input): Unit
path = input("path").getOrElse("specs")
loadSpecs(path) andThen
runSpecs andThen
presentResults
what’stheeagerpoint?
@_md#EagerDesign
merging2cells!!
@_md#EagerDesign
{
3cases
samevalue
differentvalue
righthandsideis
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;

});

}
EagerDesign
♞
Jumptotheproblemworthsolving
Eagerlyreplaceprimitiveswithtypes
Compose[thedomainalgebra] inside-out
Avoidmutablestate
#1
#2
#3
#4
@_md#EagerDesign
marcelloduarte
@_md
#EagerDesign
Thankyou!
♞
@_md
bit.ly/inviqa-contact bit.ly/inviqa-careers
#EagerDesign

Introducing Eager Design