Skip to content
No description, website, or topics provided.
Ruby Makefile
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
actor_like
aggregate_root
duck_typing
extracted_state
functional_aggregate
lib Aggregate with extracted state. Jan 21, 2019
polymorphic
poro
query_based
rails_way
repository Polishing Mar 24, 2019
roles
test
ui
yield_based
Gemfile ActiveRecord-based implementation Jun 1, 2019
Gemfile.lock ActiveRecord-based implementation Jun 1, 2019
Makefile
README.md

README.md

Aggregates

An experiment of different aggregate implementations. All implementations must pass same test suite: arranged with commands, asserted with events.

Experiment subject

Quite typical workflow of an issue in a popular task tracking software (Jira).

workflow

Existing experiments

Classical example

source

  • probably most recognized implementation (appeared in Greg Young's CQRS example)
  • does not expose its internal state via reader methods
  • testability without persistence (just check if operation yields correct event)

Module source: https://github.com/RailsEventStore/rails_event_store/tree/5378b343dbf427f5ea68f7ddfc66d6a449a6ff82/aggregate_root/lib

Aggregate with exposed queries

source

  • clear separation of state sourcing (with projection)
  • aggregate not aware of events
  • handler queries aggregate whether particular action is possible

Aggregate with extracted state

source

  • aggregate initialized with already sourced state

Functional aggregate

source

  • no single aggregate, just functions that take state and return events

Polymorphic

source

  • domain classes per each state
  • no messaging in domain classes
  • no id in domain class
  • invalid state transition cared by raising exception

More: https://blog.arkency.com/make-your-ruby-code-more-modular-and-functional-with-polymorphic-aggregate-classes/

Duck typing

source

  • domain classes per each state
  • no messaging in domain classes
  • no id in domain class
  • invalid state transition cared by not having such methods on objects (duck)

Aggregate with yield

source

  • yield is used to publish events (no unpublished_events in aggregate)
  • aggregate repository separated from logic

Aggregate with repository

source

  • aggregate is unware of infrastructure
  • aggregate can built itself from events (but it could be recreated in any way)
  • aggregate keeps the state in PORO way
  • aggregate registers events aka changes
  • aggregate provides API to read registered events
  • Infrastructure (through repository in this case) is responsible for building/saving the aggregate so it could be done in any way - Event Sourcing, serialization etc

Roles/DCI

source

  • better mental model by not having separate classes per state
  • one object which changes roles
  • extend(Role.clone) is used as Ruby ignores subsequent extend with the same module

PORO with attributes

source

  • clear separation of state sourcing (with projection)
  • aggregate not aware of events
  • aggregate object is still responsible for holding invariants
  • no id in domain class
You can’t perform that action at this time.