Skip to main content

Aggregating the Behaviour

The combine is a binary operation over the decider, view and saga, satisfying associativity and having an identity/empty element.

Associativity facilitates parallelization by giving us the freedom to break problems into chunks that can be computed in parallel.

Functional paradigm and category theory define this algebra as a Monoid. Stated tersely, a monoid is a type together with a binary operation (combine) over that type, satisfying associativity and having an identity element (zero/empty).

combine operation is also commutative / commutative monoid

associative: (decider1 + decider2) + decider3 = decider1 + (decider2 + decider3)
commutative: decider1 + decider2 = decider2 + decider1
zero: decider1 + decider0 = decider1

By combining two or more deciders you get the new decider.

This is a formal signature of the combine function defined on the decider:

combine<C2, S2, E2>(decider2: Decider<C2, S2, E2>): Decider<C | C2, S & S2, E | E2>

Example:

const restaurantDecider: Decider<RestaurantCommand, Restaurant | null, RestaurantEvent>

const orderDecider: Decider<OrderCommand, Order | null, OrderEvent>

// Combining two deciders into one big decider that can handle all commands of the system.
const decider: Decider<RestaurantCommand | OrderCommand, (Order & Restaurant) | null, RestaurantEvent | OrderEvent> =
restaurantDecider.combine(orderDecider);

Mappable


Additionally, Decider<C, S, E> provides map functions:

mapContraOnCommand<Cn>(f: (cn: Cn) => C): Decider<Cn, S, E>

dimapOnEvent<En>(fl: (en: En) => E, fr: (e: E) => En): Decider<C, S, En>

dimapOnState<Sn>(fl: (sn: Sn) => S, fr: (s: S) => Sn): Decider<C, Sn, E>