SlideShare una empresa de Scribd logo
1 de 55
Descargar para leer sin conexión
Functional
Domain Driven Design
disclaimer: is still a “work in progress”
Focus on the domain and
domain logic rather than
technology
(Eric Evans)
Why not with a functional approach?
A monad is a triple (T,	
  η,	
  μ) where T is an
endofunctor T:	
  X-­‐>X and η:	
  I-­‐>T and μ:	
  T	
  x	
  T-­‐>T
are 2 natural transformations satisfying these laws:
•  Identity law: μ(η(T))	
  =	
  T	
  =	
  μ(T(η))	
  	
  
•  Associative law: μ(μ(T	
  ×	
  T)	
  ×	
  T))	
  =	
  μ(T	
  ×	
  μ(T	
  
×	
  T))
A monad in X is just a monoid in the category
of endofunctors of X, with product × replaced
by composition of endofunctors and unit set
by the identity endofunctor
What is a monad?
software developer @ codiceplastico
@amelchiori
alessandro@codiceplastico.com
About me
F#: a gentle introduction
let	
  myString	
  =	
  "original	
  value"	
  
let	
  myString	
  =	
  "new	
  value”	
  
	
  
	
  
	
  
Immutability: values, not variables!
Duplicate definition of value ‘myString’
let	
  add	
  x	
  y	
  =	
  x	
  +	
  y	
  
add	
  2	
  2	
  
	
  
x:int	
  -­‐>	
  y:int	
  -­‐>	
  int	
  
	
  
Type inference
void	
  ProcessItems(Item[]	
  items,	
  Action<Item>	
  action)	
  
{	
  
	
  	
  	
  	
  for(int	
  i	
  =	
  0;	
  i	
  <	
  items.Length;	
  i++)	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  var	
  item	
  =	
  items[i];	
  
	
  	
  	
  	
  	
  	
  	
  	
  action(item);	
  	
  
	
  	
  }	
  
}	
  
Recursion
let	
  rec	
  processItems	
  action	
  =	
  function	
  
	
  	
  |	
  []	
  	
  	
  	
  	
  	
  	
  -­‐>	
  ()	
  	
  
	
  	
  |	
  head	
  ::	
  tail	
  -­‐>	
  
	
  	
  	
  	
  	
  	
  action	
  head;	
  
	
  	
  	
  	
  	
  	
  processItems	
  tail	
  
Recursion
let	
  add	
  x	
  y	
  =	
  x	
  +	
  y	
  
x:int	
  -­‐>	
  y:int	
  -­‐>	
  int	
  
	
  
Partial function application
let	
  add5	
  x	
  =	
  add	
  5	
  
x:int	
  -­‐>	
  int	
  
	
  
let	
  value	
  =	
  add5	
  10	
  
(value	
  =	
  15)	
  
	
  
let	
  f	
  x	
  =	
  x	
  *	
  x	
  
x:int	
  -­‐>	
  int	
  
	
  
let	
  g	
  x	
  =	
  -­‐x/2	
  +	
  5	
  
x:int	
  -­‐>	
  int	
  
	
  
	
  
	
  
Functions composition
let	
  (<<)	
  f	
  g	
  x	
  =	
  f	
  (g	
  x)	
  
('b	
  -­‐>	
  'c)	
  -­‐>	
  ('a	
  -­‐>	
  'b)	
  -­‐>	
  'a	
  -­‐>	
  ’c	
  
let	
  h	
  x	
  =	
  f	
  <<	
  g	
  
x:int	
  -­‐>	
  int	
  
	
  
let	
  square	
  x	
  =	
  x	
  *	
  x	
  
let	
  add	
  x	
  y	
  =	
  x	
  +	
  y	
  
let	
  toString	
  x	
  =	
  x.ToString()	
  
	
  
let	
  complexFunction	
  x	
  =	
  toString	
  (add	
  5	
  (square	
  x))	
  
Pipeline operator
let	
  (|>)	
  x	
  f	
  =	
  f	
  x	
  
let	
  complexFunction	
  x	
  =	
  x	
  |>	
  square	
  |>	
  add	
  5	
  |>	
  toString	
  
let	
  div	
  x	
  y	
  =	
  x	
  /	
  y	
  
x:int	
  -­‐>	
  y:int	
  -­‐>	
  int	
  
	
  
div	
  10	
  5 	
   	
   	
  //	
  2	
  
div	
  10	
  0 	
   	
   	
  //	
  System.DivideByZeroException	
  
	
  
Option type
let	
  safeDiv	
  x	
  y	
  =	
  
	
  	
  	
  	
  if	
  y	
  =	
  0	
  then	
  None	
  
	
  	
  	
  	
  else	
  Some(x/y)	
  
x:int	
  -­‐>	
  y:int	
  -­‐>	
  int	
  option	
  
	
  
let	
  safeDiv	
  x	
  y	
  =	
  
	
  	
  	
  	
  match	
  y	
  with	
  
	
  	
  	
  	
  	
  	
  	
  	
  |	
  0	
  -­‐>	
  None	
  
	
  	
  	
  	
  	
  	
  	
  	
  |	
  _	
  -­‐>	
  Some(x/y)	
  
	
  
Pattern matching
let	
  safeDiv	
  x	
  y	
  =	
  
	
  	
  	
  	
  match	
  y	
  with	
  
	
  	
  	
  	
  	
  	
  	
  	
  |	
  0	
  -­‐>	
  None	
  
	
  	
  	
  	
  	
  	
  	
  	
  |	
  1	
  -­‐>	
  Some(x/y)	
  
	
  
Incomplete pattern matches on this expression.
For example, the value '2' may indicate a case not covered by
the pattern(s)
	
  
type	
  State	
  =	
  
	
  	
  	
  	
  |	
  On	
  
	
  	
  	
  	
  |	
  Off	
  
	
  
let	
  x	
  =	
  On	
  
let	
  y	
  =	
  Off	
  
	
  
Discriminated unions
let	
  div	
  (x,	
  y)	
  =	
  …	
  	
  
(int	
  *	
  int)	
  -­‐	
  >	
  int	
  
	
  
	
  
Tuples
let	
  div	
  (x,	
  y)	
  =	
  
	
  match	
  (x,	
  y)	
  with	
  
	
   	
  |	
  (_,	
  0)	
  -­‐>	
  None	
  
	
   	
  |	
  (_,	
  _)	
  -­‐>	
  Some(x/	
  y)	
  
	
  
	
  
type	
  site	
  =	
  {	
  Title	
  :	
  string;	
  Url	
  :	
  string	
  }	
  
	
  
	
  
Records
let	
  homepage	
  =	
  	
  
	
  {	
  Title	
  =	
  "Google";	
  Url	
  =	
  "http://www.google.com"	
  }	
  
	
  
let	
  next	
  =	
  {	
  homepage	
  with	
  Title	
  =	
  "NextPage"	
  }	
  
	
  
	
  
OK! Let’s go…
public	
  class	
  Company	
  
{	
  
	
  public	
  String	
  BusinessName	
  {	
  get;	
  set;	
  }	
  
	
  public	
  String	
  TaxCode	
  {	
  get;	
  set;	
  }	
  
	
  public	
  String	
  VatNumber	
  {	
  get;	
  set;	
  }	
  
	
  
	
  public	
  String	
  AssignedBank	
  {	
  get;	
  set;	
  }	
  
	
  public	
  Boolean	
  IsBankAuthorized	
  {	
  get;	
  set;	
  }	
  
}	
  
Value object
An immutable object, like money or a date
range, whose equality isn't based on identity
(in general equality is based on all fields
equality)
Martin Fowler
Value object
An immutable object, like money or a date
range, whose equality isn't based on identity
(in general equality is based on all fields
equality)
Martin Fowler
public	
  class	
  CompanyProfile	
  
{	
  
	
  public	
  String	
  BusinessName	
  {	
  get;	
  private	
  set;	
  }	
  
	
  public	
  String	
  TaxCode	
  {	
  get;	
  private	
  set;	
  }	
  
	
  public	
  String	
  VatNumber	
  {	
  get;	
  private	
  set;	
  }	
  
	
  
	
  public	
  CompanyProfile(String	
  businessName,	
  String	
  taxCode,	
  	
  
	
   	
   	
   	
   	
   	
  String	
  vatNumber=null)	
  
	
  {	
  
	
   	
  //	
  check	
  if	
  parameters	
  are	
  valid	
  
	
   	
  BusinessName	
  =	
  businessName;	
  
	
   	
  TaxCode	
  =	
  taxCode;	
  
	
   	
  VatNumber	
  =	
  vatNumber;	
  
	
  }	
  
}	
  
Value object
public	
  class	
  CompanyProfile	
  
{	
  
	
  //	
  same	
  as	
  before…	
  
	
  public	
  override	
  Boolean	
  Equals(Object	
  other)	
  
	
  {	
  
	
   	
  var	
  target	
  =	
  other	
  as	
  CompanyProfile;	
  
	
   	
  return	
  target	
  ==	
  null	
  ?	
  false	
  :	
  	
  
	
   	
   	
  target.BusinessName	
  ==	
  this.BusinessName	
  	
  
	
   	
   	
  &&	
  target.TaxCode	
  ==	
  this.TaxCode	
  	
  
	
   	
   	
  &&	
  target.VatCode	
  ==	
  this.VatCode;	
  
	
  }	
  
	
  
	
  public	
  override	
  Int32	
  GetHashCode()	
  
	
  {	
  
	
   	
  //	
  ...	
  
	
  }	
  
}	
  
Value object’s equality
type	
  CompanyProfile	
  =	
  {	
  
	
  BusinessName	
  :	
  string;	
  
	
  TaxCode	
  :	
  string;	
  
	
  VatNumber	
  :	
  string	
  
}	
  
Value object in F#
option;	
  
let	
  profile	
  =	
  {	
  	
  
	
  BusinessName	
  =	
  “CodicePlastico”;	
  
	
  TaxNumber	
  =	
  “1234567890”;	
  
}	
  
Ubiquitous Language is the concept of
defining a language (spoken and written) that
is equally used across developers and domain
experts
Ubiquitous language
public	
  class	
  Company	
  
{	
  
	
  ...	
  
	
  
	
  public	
  String	
  AssignedBank	
  {	
  get;	
  set;	
  }	
  
	
  public	
  Boolean	
  IsBankAuthorized	
  {	
  get;	
  set;	
  }	
  
}	
  
Ubiquitous language
Rule 1:
A company must have a bank to work with
Rule 2:
A company can be authorized to work with its
assigned bank
Rule 3:
A company can be not authorized to work with
its assigned bank
Business logic
Make illegal states unrepresentable
Ubiquitous language
type	
  Bank	
  =	
  Bank	
  of	
  string	
  
type	
  UnauthorizedBank	
  =	
  UnauthorizedBank	
  of	
  Bank	
  
type	
  AuthorizedBank	
  =	
  AuthorizedBank	
  of	
  Bank	
  
	
  
type	
  AssignedBank	
  =	
  
	
  |	
  Unauthorized	
  of	
  UnauthorizedBank	
  
	
  |	
  Authorized	
  of	
  AuthorizedBank	
  
	
  
Business logic in F#
type	
  CompanyProfile	
  =	
  {	
  
	
  BusinessName:	
  string,	
  
	
  TaxCode:	
  string,	
  
	
  VatCode:	
  string	
  option	
  	
  
}	
  
	
  
	
  
	
  
type	
  Bank	
  =	
  Bank	
  of	
  string	
  
type	
  UnauthorizedBank	
  =	
  	
  
	
   	
  UnauthorizedBank	
  of	
  Bank	
  
type	
  AuthorizedBank	
  =	
  	
  
	
   	
  AuthorizedBank	
  of	
  Bank	
  
type	
  AssignedBank	
  =	
  
	
  |	
  Unauthorized	
  of	
  UnauthorizedBank	
  
	
  |	
  Authorized	
  of	
  AuthorizedBank	
  
	
  
	
  
type	
  Company	
  =	
  {	
  
	
  Profile:	
  CompanyProfile,	
  
	
  Bank:	
  AssignedBank	
  	
  
}	
  
	
  
Ubiquitous language to the rescue
The central idea of specification is to
separate the statement of how to match
a candidate, from the candidate object
that it is matched against
Specification
type	
  SpecificationResult	
  =	
  	
  
	
  	
  	
  	
  |	
  Success	
  
	
  	
  	
  	
  |	
  Failure	
  of	
  string	
  
	
  
type	
  Spec<'a>	
  =	
  'a	
  -­‐>	
  SpecificationResult	
  
Specification
type	
  Category	
  =	
  	
  
	
  	
  	
  	
  |	
  Default	
  
	
  	
  	
  	
  |	
  Premium	
  
	
  	
  	
  	
  |	
  Gold	
  
	
  
type	
  Customer	
  =	
  {	
  
	
  	
  	
  	
  Name:	
  string;	
  
	
  	
  	
  	
  Category:	
  Category;	
  
}	
  
	
  
Specification: our (simple) domain
type	
  Item	
  =	
  {	
  
	
  	
  	
  	
  Code:	
  string;	
  
	
  	
  	
  	
  Quantity:	
  int;	
  
}	
  
	
  
type	
  Order	
  =	
  {	
  
	
  Number:	
  string;	
  
	
  Customer:	
  Customer;	
  
	
  Items:	
  Item	
  list;	
  
}	
  
let	
  isOrderFullFilled	
  :	
  Spec<Order>	
  =	
  
	
  	
  	
  	
  let	
  p	
  order	
  =	
  
	
  	
  	
  	
  	
  	
  	
  	
  match	
  Seq.isEmpty	
  order.Items	
  with	
  
	
  	
  	
  	
  	
  	
  	
  	
  |	
  true	
  -­‐>	
  Failure("Items'	
  list	
  empty")	
  
	
  	
  	
  	
  	
  	
  	
  	
  |	
  false	
  -­‐>	
  Success	
  
	
  	
  	
  	
  in	
  p	
  
	
  
let	
  isGoldCustomer	
  :	
  Spec<Customer>	
  =	
  
	
  	
  	
  	
  let	
  p	
  customer	
  =	
  
	
  	
  	
  	
  	
  	
  	
  	
  match	
  customer.Category	
  with	
  
	
  	
  	
  	
  	
  	
  	
  	
  |	
  Gold	
  -­‐>	
  Success	
  
	
  	
  	
  	
  	
  	
  	
  	
  |	
  _	
  -­‐>	
  Failure("No-­‐gold	
  customer")	
  
	
  	
  	
  	
  in	
  p	
  
Specification
let	
  And	
  (left:	
  Spec<'a>)	
  (right:	
  Spec<'a>)	
  :	
  Spec<'a>	
  =	
  
	
  let	
  p	
  entity	
  =	
  
	
   	
  match	
  left	
  entity	
  with	
  
	
   	
  |	
  Success	
  -­‐>	
  right	
  entity	
  
	
   	
  |	
  _	
  -­‐>	
  Failure("And	
  specification	
  is	
  not	
  satisfied")	
  
	
  in	
  p	
  
Specification
let	
  order	
  =	
  {	
  
	
  	
  	
  	
  Number	
  =	
  "1234";	
  
	
  Customer	
  =	
  {	
  Name	
  =	
  "Alessandro";	
  Category	
  =	
  Gold};	
  
	
  	
  	
  	
  Items	
  =	
  [	
  
	
  	
  	
  	
  	
  	
  	
  	
  {	
  Code	
  =	
  "Code1";	
  Quantity	
  =	
  1};	
  
	
  	
  	
  	
  	
  	
  	
  	
  {	
  Code	
  =	
  "Code2";	
  Quantity	
  =	
  2};	
  
	
  ];	
  
}	
  
	
  
let	
  isOrderValid	
  =	
  And	
  	
  
	
  isOrderFullFilled	
  	
  
	
  (adapt	
  isGoldCustomer	
  (fun	
  order	
  -­‐>	
  order.Customer))	
  
	
  
let	
  isValid	
  =	
  isOrderValid	
  order	
  
Specification
CQRS & Event Sourcing
A single model cannot be appropriate for
reporting, searching and transactional
behavior
Greg Young
CQRS
State transition are an important part of our
problem space and should be modeled within
our domain
Greg Young
Event Sourcing
public	
  void	
  AddItemToCart(Item	
  item)	
  
{	
  
	
  //	
  validation	
  
	
  if	
  (item	
  ==	
  null)	
  
	
   	
  throw	
  new	
  ArgumentNullException();	
  
	
  
	
  //	
  execution	
  
	
  _items.Add(item.Id);	
  
}	
  
Commands, events and…fold (step 1)
public	
  void	
  AddItemToCart(Item	
  item)	
  
{	
  
	
  if	
  (item	
  ==	
  null)	
  
	
   	
  throw	
  new	
  ArgumentNullException();	
  
	
  
	
  var	
  domainEvent	
  =	
  new	
  ItemAddedToCart	
  	
  
	
   	
  {	
  CartId	
  =	
  this.Id,	
  ItemId	
  =	
  item.Id	
  };	
  
	
  Apply(domainEvent)	
  
}	
  
	
  
private	
  void	
  Apply(ItemAddedToCart	
  domainEvent)	
  
{	
  
	
  _items.Add(domainEvent.ItemId);	
  
}	
  
Commands, events and…fold (step 2)
public	
  void	
  AddItemToCart(Item	
  item)	
  
{	
  
	
  if	
  (item	
  ==	
  null)	
  
	
   	
  throw	
  new	
  ArgumentNullException();	
  
	
  
	
  var	
  domainEvent	
  =	
  new	
  ItemAddedToCart	
  	
  
	
   	
  {	
  CartId	
  =	
  this.Id,	
  ItemId	
  =	
  item.Id	
  };	
  
	
  Apply(this,	
  domainEvent)	
  
}	
  
	
  
private	
  void	
  Apply(Cart	
  target,	
  ItemAddedToCart	
  domainEvent)	
  
{	
  
	
  target._items.Add(domainEvent.ItemId);	
  
}	
  
Commands, events and…fold (step 3)
public	
  static	
  Cart	
  Apply(Cart	
  target,	
  CartCreated	
  domainEvent)	
  
{	
  
	
  return	
  new	
  Cart	
  {	
  Id	
  =	
  domainEvent.CartId,	
  _items	
  =	
  new	
  String[0]	
  };	
  
}	
  
	
  
public	
  static	
  Cart	
  Apply(Cart	
  target,	
  ItemAddedToCart	
  domainEvent)	
  
{	
  
	
  var	
  items	
  =	
  target._items.ToList();	
  
	
  items.Add(domainEvent.ItemId);	
  
	
  
	
  return	
  new	
  Cart	
  {	
  Id	
  =	
  domainEvent.CartId,	
  _items	
  =	
  items	
  };	
  
}	
  
	
  
public	
  static	
  Cart	
  Apply(Cart	
  target,	
  ItemRemovedFromCart	
  domainEvent)	
  
{	
  
	
  var	
  items	
  =	
  target._items.ToList();	
  
	
  items.Remove(domainEvent.ItemId); 	
  	
  
	
  
	
  return	
  new	
  Cart	
  {	
  Id	
  =	
  domainEvent.CartId,	
  _items	
  =	
  items	
  };	
  
}	
  
Commands, events and…fold (step 4)
 
	
  
	
  
	
   	
   	
  Cart.Apply(null,	
  new	
  CartCreated	
  {	
  CartId=1	
  })	
  
Commands, events and…fold (step 5)
 
	
  
	
   	
  Cart.Apply(	
  
	
   	
   	
  Cart.Apply(null,	
  new	
  CartCreated	
  {	
  CartId=1}),	
  
	
   	
   	
  new	
  ItemAddedToCart	
  {	
  CartId	
  =	
  1,	
  ItemId	
  =	
  "A"	
  }	
  
	
   	
  )	
  
Commands, events and…fold (step 5)
 
	
  Cart.Apply(	
  
	
   	
  Cart.Apply(	
  
	
   	
   	
  Cart.Apply(null,	
  new	
  CartCreated	
  {	
  CartId=1}),	
  
	
   	
   	
  new	
  ItemAddedToCart	
  {	
  CartId	
  =	
  1,	
  ItemId	
  =	
  "A"	
  }	
  
	
   	
  ),	
  
	
   	
  new	
  ItemAddedToCart	
  {	
  CartId	
  =	
  1,	
  ItemId	
  =	
  "B"	
  }	
  
	
  )	
  
Commands, events and…fold (step 5)
Cart.Apply(	
  
	
  Cart.Apply(	
  
	
   	
  Cart.Apply(	
  
	
   	
   	
  Cart.Apply(null,	
  new	
  CartCreated	
  {	
  CartId=1}),	
  
	
   	
   	
  new	
  ItemAddedToCart	
  {	
  CartId	
  =	
  1,	
  ItemId	
  =	
  "A"	
  }	
  
	
   	
  ),	
  
	
   	
  new	
  ItemAddedToCart	
  {	
  CartId	
  =	
  1,	
  ItemId	
  =	
  "B"	
  }	
  
	
  ),	
  
	
  new	
  ItemRemovedFromCart	
  {	
  CartId	
  =	
  1,	
  ItemId	
  =	
  "A"	
  }	
  
)	
  
Commands, events and…fold (step 5)
Executing a command:
type	
  Exec	
  =	
  	
  
	
  (	
  CartState	
  *	
  Command	
  )	
  -­‐>	
  DomainEvent	
  
Applying an event:
type	
  Apply	
  =	
  	
  
	
  (	
  CartState	
  *	
  DomainEvent	
  )	
  -­‐>	
  CartState	
  	
  
Commands, events and…fold (step 6)
type	
  Command	
  =	
  	
  
	
  |	
  Create	
  of	
  string	
  
	
  |	
  AddItem	
  of	
  int	
  
	
  |	
  RemoveItem	
  of	
  int	
  
	
  |	
  RemoveAllItems	
  
	
  |	
  Checkout	
  
type	
  Event	
  =	
  	
  
	
  |	
  Created	
  of	
  string	
  
	
  |	
  ItemAdded	
  of	
  int	
  
	
  |	
  ItemRemoved	
  of	
  int	
  
	
  |	
  AllItemsRemoved	
  
	
  |	
  Checkedout	
  
Commands, events and…fold (step 7)
type	
  CartState	
  =	
  {	
  
	
  	
  	
  	
  Name:	
  string;	
  
	
  	
  	
  	
  Items:	
  List<int>;	
  
	
  	
  	
  	
  Active:	
  bool;	
  
}	
  
	
  
let	
  apply	
  state	
  =	
  function	
  
	
  	
  	
  	
  |	
  Created	
  x	
  -­‐>	
  {	
  Cart.empty	
  with	
  Name	
  =	
  x	
  }	
  
	
  	
  	
  	
  |	
  ItemAdded	
  x	
  -­‐>	
  {	
  state	
  with	
  Items	
  =	
  List.append	
  state.Items	
  [x]	
  }	
  
	
  	
  	
  	
  |	
  ItemRemoved	
  x	
  -­‐>	
  	
  
	
  	
  	
  {	
  state	
  with	
  Items	
  =	
  List.filter	
  (fun	
  i	
  -­‐>	
  i	
  <>	
  x	
  )	
  state.Items	
  }	
  
	
  	
  	
  	
  |	
  Removed	
  _	
  -­‐>	
  {	
  state	
  with	
  Items	
  =	
  List.empty	
  }	
  
	
  	
  	
  	
  |	
  Checkedout	
  _	
  -­‐>	
  {	
  state	
  with	
  Active	
  =	
  false	
  }	
  
	
  
Commands, events and…fold (step 8)
let	
  domainEvents	
  =	
  [	
  
	
  	
  	
  	
  Created("cart1");	
  
	
  	
  	
  	
  ItemAdded(1);	
  
	
  	
  	
  	
  ItemAdded(2);	
  
	
  	
  	
  	
  Removed;	
  
	
  	
  	
  	
  ItemAdded(3);	
  
	
  	
  	
  	
  Checkedout;	
  
]	
  
	
  
let	
  state	
  =	
  List.fold	
  apply	
  Cart.empty	
  domainEvents	
  
Commands, events and…fold (step 9)
Tackling Complexity in the
Heart of Software
Eric Evans
…but, when DDD?
TechDay: Functional DDD - Alessandro Melchiori

Más contenido relacionado

Más de Codemotion

Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Codemotion
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Codemotion
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Codemotion
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 - Codemotion
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Codemotion
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Codemotion
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Codemotion
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Codemotion
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Codemotion
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Codemotion
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Codemotion
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...Codemotion
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Codemotion
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Codemotion
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Codemotion
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Codemotion
 
Mike Kotsur - What can philosophy teach us about programming - Codemotion Ams...
Mike Kotsur - What can philosophy teach us about programming - Codemotion Ams...Mike Kotsur - What can philosophy teach us about programming - Codemotion Ams...
Mike Kotsur - What can philosophy teach us about programming - Codemotion Ams...Codemotion
 
Mete Atamel - Serverless with Knative - Codemotion Amsterdam 2019
Mete Atamel - Serverless with Knative - Codemotion Amsterdam 2019Mete Atamel - Serverless with Knative - Codemotion Amsterdam 2019
Mete Atamel - Serverless with Knative - Codemotion Amsterdam 2019Codemotion
 
Rahul Shetty - Corporate relocation prediction - Codemotion Amsterdam 2019
Rahul Shetty - Corporate relocation prediction - Codemotion Amsterdam 2019Rahul Shetty - Corporate relocation prediction - Codemotion Amsterdam 2019
Rahul Shetty - Corporate relocation prediction - Codemotion Amsterdam 2019Codemotion
 
Mario Viviani - Designing apps for fire TV - Codemotion Amsterdam 2019
Mario Viviani - Designing apps for fire TV - Codemotion Amsterdam 2019Mario Viviani - Designing apps for fire TV - Codemotion Amsterdam 2019
Mario Viviani - Designing apps for fire TV - Codemotion Amsterdam 2019Codemotion
 

Más de Codemotion (20)

Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
Michel Schudel - Let's build a blockchain... in 40 minutes! - Codemotion Amst...
 
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
Richard Süselbeck - Building your own ride share app - Codemotion Amsterdam 2019
 
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
Eward Driehuis - What we learned from 20.000 attacks - Codemotion Amsterdam 2019
 
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 - Francesco Baldassarri  - Deliver Data at Scale - Codemotion Amsterdam 2019 -
Francesco Baldassarri - Deliver Data at Scale - Codemotion Amsterdam 2019 -
 
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
Martin Förtsch, Thomas Endres - Stereoscopic Style Transfer AI - Codemotion A...
 
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
Melanie Rieback, Klaus Kursawe - Blockchain Security: Melting the "Silver Bul...
 
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
Angelo van der Sijpt - How well do you know your network stack? - Codemotion ...
 
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
Lars Wolff - Performance Testing for DevOps in the Cloud - Codemotion Amsterd...
 
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
Sascha Wolter - Conversational AI Demystified - Codemotion Amsterdam 2019
 
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
Michele Tonutti - Scaling is caring - Codemotion Amsterdam 2019
 
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
Pat Hermens - From 100 to 1,000+ deployments a day - Codemotion Amsterdam 2019
 
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
James Birnie - Using Many Worlds of Compute Power with Quantum - Codemotion A...
 
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
Don Goodman-Wilson - Chinese food, motor scooters, and open source developmen...
 
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
Pieter Omvlee - The story behind Sketch - Codemotion Amsterdam 2019
 
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
Dave Farley - Taking Back “Software Engineering” - Codemotion Amsterdam 2019
 
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
Joshua Hoffman - Should the CTO be Coding? - Codemotion Amsterdam 2019
 
Mike Kotsur - What can philosophy teach us about programming - Codemotion Ams...
Mike Kotsur - What can philosophy teach us about programming - Codemotion Ams...Mike Kotsur - What can philosophy teach us about programming - Codemotion Ams...
Mike Kotsur - What can philosophy teach us about programming - Codemotion Ams...
 
Mete Atamel - Serverless with Knative - Codemotion Amsterdam 2019
Mete Atamel - Serverless with Knative - Codemotion Amsterdam 2019Mete Atamel - Serverless with Knative - Codemotion Amsterdam 2019
Mete Atamel - Serverless with Knative - Codemotion Amsterdam 2019
 
Rahul Shetty - Corporate relocation prediction - Codemotion Amsterdam 2019
Rahul Shetty - Corporate relocation prediction - Codemotion Amsterdam 2019Rahul Shetty - Corporate relocation prediction - Codemotion Amsterdam 2019
Rahul Shetty - Corporate relocation prediction - Codemotion Amsterdam 2019
 
Mario Viviani - Designing apps for fire TV - Codemotion Amsterdam 2019
Mario Viviani - Designing apps for fire TV - Codemotion Amsterdam 2019Mario Viviani - Designing apps for fire TV - Codemotion Amsterdam 2019
Mario Viviani - Designing apps for fire TV - Codemotion Amsterdam 2019
 

TechDay: Functional DDD - Alessandro Melchiori

  • 1. Functional Domain Driven Design disclaimer: is still a “work in progress”
  • 2. Focus on the domain and domain logic rather than technology (Eric Evans)
  • 3. Why not with a functional approach?
  • 4. A monad is a triple (T,  η,  μ) where T is an endofunctor T:  X-­‐>X and η:  I-­‐>T and μ:  T  x  T-­‐>T are 2 natural transformations satisfying these laws: •  Identity law: μ(η(T))  =  T  =  μ(T(η))     •  Associative law: μ(μ(T  ×  T)  ×  T))  =  μ(T  ×  μ(T   ×  T)) A monad in X is just a monoid in the category of endofunctors of X, with product × replaced by composition of endofunctors and unit set by the identity endofunctor What is a monad?
  • 5.
  • 6. software developer @ codiceplastico @amelchiori alessandro@codiceplastico.com About me
  • 7. F#: a gentle introduction
  • 8. let  myString  =  "original  value"   let  myString  =  "new  value”         Immutability: values, not variables! Duplicate definition of value ‘myString’
  • 9. let  add  x  y  =  x  +  y   add  2  2     x:int  -­‐>  y:int  -­‐>  int     Type inference
  • 10. void  ProcessItems(Item[]  items,  Action<Item>  action)   {          for(int  i  =  0;  i  <  items.Length;  i++)          {                  var  item  =  items[i];                  action(item);        }   }   Recursion
  • 11. let  rec  processItems  action  =  function      |  []              -­‐>  ()        |  head  ::  tail  -­‐>              action  head;              processItems  tail   Recursion
  • 12. let  add  x  y  =  x  +  y   x:int  -­‐>  y:int  -­‐>  int     Partial function application let  add5  x  =  add  5   x:int  -­‐>  int     let  value  =  add5  10   (value  =  15)    
  • 13. let  f  x  =  x  *  x   x:int  -­‐>  int     let  g  x  =  -­‐x/2  +  5   x:int  -­‐>  int         Functions composition let  (<<)  f  g  x  =  f  (g  x)   ('b  -­‐>  'c)  -­‐>  ('a  -­‐>  'b)  -­‐>  'a  -­‐>  ’c   let  h  x  =  f  <<  g   x:int  -­‐>  int    
  • 14. let  square  x  =  x  *  x   let  add  x  y  =  x  +  y   let  toString  x  =  x.ToString()     let  complexFunction  x  =  toString  (add  5  (square  x))   Pipeline operator let  (|>)  x  f  =  f  x   let  complexFunction  x  =  x  |>  square  |>  add  5  |>  toString  
  • 15. let  div  x  y  =  x  /  y   x:int  -­‐>  y:int  -­‐>  int     div  10  5      //  2   div  10  0      //  System.DivideByZeroException     Option type let  safeDiv  x  y  =          if  y  =  0  then  None          else  Some(x/y)   x:int  -­‐>  y:int  -­‐>  int  option    
  • 16. let  safeDiv  x  y  =          match  y  with                  |  0  -­‐>  None                  |  _  -­‐>  Some(x/y)     Pattern matching let  safeDiv  x  y  =          match  y  with                  |  0  -­‐>  None                  |  1  -­‐>  Some(x/y)     Incomplete pattern matches on this expression. For example, the value '2' may indicate a case not covered by the pattern(s)  
  • 17. type  State  =          |  On          |  Off     let  x  =  On   let  y  =  Off     Discriminated unions
  • 18. let  div  (x,  y)  =  …     (int  *  int)  -­‐  >  int       Tuples let  div  (x,  y)  =    match  (x,  y)  with      |  (_,  0)  -­‐>  None      |  (_,  _)  -­‐>  Some(x/  y)      
  • 19. type  site  =  {  Title  :  string;  Url  :  string  }       Records let  homepage  =      {  Title  =  "Google";  Url  =  "http://www.google.com"  }     let  next  =  {  homepage  with  Title  =  "NextPage"  }      
  • 21. public  class  Company   {    public  String  BusinessName  {  get;  set;  }    public  String  TaxCode  {  get;  set;  }    public  String  VatNumber  {  get;  set;  }      public  String  AssignedBank  {  get;  set;  }    public  Boolean  IsBankAuthorized  {  get;  set;  }   }  
  • 22. Value object An immutable object, like money or a date range, whose equality isn't based on identity (in general equality is based on all fields equality) Martin Fowler
  • 23. Value object An immutable object, like money or a date range, whose equality isn't based on identity (in general equality is based on all fields equality) Martin Fowler
  • 24. public  class  CompanyProfile   {    public  String  BusinessName  {  get;  private  set;  }    public  String  TaxCode  {  get;  private  set;  }    public  String  VatNumber  {  get;  private  set;  }      public  CompanyProfile(String  businessName,  String  taxCode,                String  vatNumber=null)    {      //  check  if  parameters  are  valid      BusinessName  =  businessName;      TaxCode  =  taxCode;      VatNumber  =  vatNumber;    }   }   Value object
  • 25. public  class  CompanyProfile   {    //  same  as  before…    public  override  Boolean  Equals(Object  other)    {      var  target  =  other  as  CompanyProfile;      return  target  ==  null  ?  false  :          target.BusinessName  ==  this.BusinessName          &&  target.TaxCode  ==  this.TaxCode          &&  target.VatCode  ==  this.VatCode;    }      public  override  Int32  GetHashCode()    {      //  ...    }   }   Value object’s equality
  • 26. type  CompanyProfile  =  {    BusinessName  :  string;    TaxCode  :  string;    VatNumber  :  string   }   Value object in F# option;   let  profile  =  {      BusinessName  =  “CodicePlastico”;    TaxNumber  =  “1234567890”;   }  
  • 27. Ubiquitous Language is the concept of defining a language (spoken and written) that is equally used across developers and domain experts Ubiquitous language
  • 28. public  class  Company   {    ...      public  String  AssignedBank  {  get;  set;  }    public  Boolean  IsBankAuthorized  {  get;  set;  }   }   Ubiquitous language
  • 29. Rule 1: A company must have a bank to work with Rule 2: A company can be authorized to work with its assigned bank Rule 3: A company can be not authorized to work with its assigned bank Business logic
  • 30. Make illegal states unrepresentable Ubiquitous language
  • 31. type  Bank  =  Bank  of  string   type  UnauthorizedBank  =  UnauthorizedBank  of  Bank   type  AuthorizedBank  =  AuthorizedBank  of  Bank     type  AssignedBank  =    |  Unauthorized  of  UnauthorizedBank    |  Authorized  of  AuthorizedBank     Business logic in F#
  • 32. type  CompanyProfile  =  {    BusinessName:  string,    TaxCode:  string,    VatCode:  string  option     }         type  Bank  =  Bank  of  string   type  UnauthorizedBank  =        UnauthorizedBank  of  Bank   type  AuthorizedBank  =        AuthorizedBank  of  Bank   type  AssignedBank  =    |  Unauthorized  of  UnauthorizedBank    |  Authorized  of  AuthorizedBank       type  Company  =  {    Profile:  CompanyProfile,    Bank:  AssignedBank     }     Ubiquitous language to the rescue
  • 33. The central idea of specification is to separate the statement of how to match a candidate, from the candidate object that it is matched against Specification
  • 34. type  SpecificationResult  =            |  Success          |  Failure  of  string     type  Spec<'a>  =  'a  -­‐>  SpecificationResult   Specification
  • 35. type  Category  =            |  Default          |  Premium          |  Gold     type  Customer  =  {          Name:  string;          Category:  Category;   }     Specification: our (simple) domain type  Item  =  {          Code:  string;          Quantity:  int;   }     type  Order  =  {    Number:  string;    Customer:  Customer;    Items:  Item  list;   }  
  • 36. let  isOrderFullFilled  :  Spec<Order>  =          let  p  order  =                  match  Seq.isEmpty  order.Items  with                  |  true  -­‐>  Failure("Items'  list  empty")                  |  false  -­‐>  Success          in  p     let  isGoldCustomer  :  Spec<Customer>  =          let  p  customer  =                  match  customer.Category  with                  |  Gold  -­‐>  Success                  |  _  -­‐>  Failure("No-­‐gold  customer")          in  p   Specification
  • 37. let  And  (left:  Spec<'a>)  (right:  Spec<'a>)  :  Spec<'a>  =    let  p  entity  =      match  left  entity  with      |  Success  -­‐>  right  entity      |  _  -­‐>  Failure("And  specification  is  not  satisfied")    in  p   Specification
  • 38. let  order  =  {          Number  =  "1234";    Customer  =  {  Name  =  "Alessandro";  Category  =  Gold};          Items  =  [                  {  Code  =  "Code1";  Quantity  =  1};                  {  Code  =  "Code2";  Quantity  =  2};    ];   }     let  isOrderValid  =  And      isOrderFullFilled      (adapt  isGoldCustomer  (fun  order  -­‐>  order.Customer))     let  isValid  =  isOrderValid  order   Specification
  • 39. CQRS & Event Sourcing
  • 40. A single model cannot be appropriate for reporting, searching and transactional behavior Greg Young CQRS
  • 41. State transition are an important part of our problem space and should be modeled within our domain Greg Young Event Sourcing
  • 42. public  void  AddItemToCart(Item  item)   {    //  validation    if  (item  ==  null)      throw  new  ArgumentNullException();      //  execution    _items.Add(item.Id);   }   Commands, events and…fold (step 1)
  • 43. public  void  AddItemToCart(Item  item)   {    if  (item  ==  null)      throw  new  ArgumentNullException();      var  domainEvent  =  new  ItemAddedToCart        {  CartId  =  this.Id,  ItemId  =  item.Id  };    Apply(domainEvent)   }     private  void  Apply(ItemAddedToCart  domainEvent)   {    _items.Add(domainEvent.ItemId);   }   Commands, events and…fold (step 2)
  • 44. public  void  AddItemToCart(Item  item)   {    if  (item  ==  null)      throw  new  ArgumentNullException();      var  domainEvent  =  new  ItemAddedToCart        {  CartId  =  this.Id,  ItemId  =  item.Id  };    Apply(this,  domainEvent)   }     private  void  Apply(Cart  target,  ItemAddedToCart  domainEvent)   {    target._items.Add(domainEvent.ItemId);   }   Commands, events and…fold (step 3)
  • 45. public  static  Cart  Apply(Cart  target,  CartCreated  domainEvent)   {    return  new  Cart  {  Id  =  domainEvent.CartId,  _items  =  new  String[0]  };   }     public  static  Cart  Apply(Cart  target,  ItemAddedToCart  domainEvent)   {    var  items  =  target._items.ToList();    items.Add(domainEvent.ItemId);      return  new  Cart  {  Id  =  domainEvent.CartId,  _items  =  items  };   }     public  static  Cart  Apply(Cart  target,  ItemRemovedFromCart  domainEvent)   {    var  items  =  target._items.ToList();    items.Remove(domainEvent.ItemId);        return  new  Cart  {  Id  =  domainEvent.CartId,  _items  =  items  };   }   Commands, events and…fold (step 4)
  • 46.            Cart.Apply(null,  new  CartCreated  {  CartId=1  })   Commands, events and…fold (step 5)
  • 47.        Cart.Apply(        Cart.Apply(null,  new  CartCreated  {  CartId=1}),        new  ItemAddedToCart  {  CartId  =  1,  ItemId  =  "A"  }      )   Commands, events and…fold (step 5)
  • 48.    Cart.Apply(      Cart.Apply(        Cart.Apply(null,  new  CartCreated  {  CartId=1}),        new  ItemAddedToCart  {  CartId  =  1,  ItemId  =  "A"  }      ),      new  ItemAddedToCart  {  CartId  =  1,  ItemId  =  "B"  }    )   Commands, events and…fold (step 5)
  • 49. Cart.Apply(    Cart.Apply(      Cart.Apply(        Cart.Apply(null,  new  CartCreated  {  CartId=1}),        new  ItemAddedToCart  {  CartId  =  1,  ItemId  =  "A"  }      ),      new  ItemAddedToCart  {  CartId  =  1,  ItemId  =  "B"  }    ),    new  ItemRemovedFromCart  {  CartId  =  1,  ItemId  =  "A"  }   )   Commands, events and…fold (step 5)
  • 50. Executing a command: type  Exec  =      (  CartState  *  Command  )  -­‐>  DomainEvent   Applying an event: type  Apply  =      (  CartState  *  DomainEvent  )  -­‐>  CartState     Commands, events and…fold (step 6)
  • 51. type  Command  =      |  Create  of  string    |  AddItem  of  int    |  RemoveItem  of  int    |  RemoveAllItems    |  Checkout   type  Event  =      |  Created  of  string    |  ItemAdded  of  int    |  ItemRemoved  of  int    |  AllItemsRemoved    |  Checkedout   Commands, events and…fold (step 7)
  • 52. type  CartState  =  {          Name:  string;          Items:  List<int>;          Active:  bool;   }     let  apply  state  =  function          |  Created  x  -­‐>  {  Cart.empty  with  Name  =  x  }          |  ItemAdded  x  -­‐>  {  state  with  Items  =  List.append  state.Items  [x]  }          |  ItemRemoved  x  -­‐>          {  state  with  Items  =  List.filter  (fun  i  -­‐>  i  <>  x  )  state.Items  }          |  Removed  _  -­‐>  {  state  with  Items  =  List.empty  }          |  Checkedout  _  -­‐>  {  state  with  Active  =  false  }     Commands, events and…fold (step 8)
  • 53. let  domainEvents  =  [          Created("cart1");          ItemAdded(1);          ItemAdded(2);          Removed;          ItemAdded(3);          Checkedout;   ]     let  state  =  List.fold  apply  Cart.empty  domainEvents   Commands, events and…fold (step 9)
  • 54. Tackling Complexity in the Heart of Software Eric Evans …but, when DDD?