kraades

kraades

DDD/CQRS/ES/NoSQL and functional programming

I was wondering if anyone is using Domain Driven Design and/or CQRS and/or Event Sourcing and/or NoSQL storage for a business application that is written in a functional language (in particular Elixir and/or Phoenix).

Hit or miss? I am getting some mixed signals. Any thoughts would be appreciated.

What is it?

Domain Driven Design

CQRS, Task Based UIs, Event Sourcing agh! - Greg Young
http://codebetter.com/gregyoung/2010/02/16/cqrs-task-based-uis-event-sourcing-agh/

CQRS - Martin Fowler

Event Sourcing - Martin Fowler

Some links…

Functional Data - Greg Young
Event Sourcing is “Functional Data Storage”

A Functional Foundation for CQRS/ES - Mathias Verreas

Domain Driven Design with the F# Type System - Scott Wlaschin

CQRS with Elixir and Phoenix - Jean-François Cloutier

Building a CQRS/ES web application in Elixir using Phoenix
Case study describing how I built a web app following a Command Query Responsibility Segregation and event sourcing pattern.

Most Liked Switch mode

slashdotdash

slashdotdash

I’ve created an “awesome list” of Elixir and CQRS/ES resources: Awesome Elixir and CQRS.

The list is designed for only CQRS/ES resources that explicitly target Elixir/Erlang, as there’s an existing awesome collection of general domain-driven design content.

Contributions via pull request most welcome.

hubertlepicki

hubertlepicki

I am using CQRS in one project. So this is qorking, and I see no reason why it would not.

CQRS/DDD and friends are not bound to object oriented programming at all. Also, Elixir/Erlang are not that much different from object oriented languages when you think about it.

What I am doing at the moment is that I have two supervised workers, started when my application starts:

  • CQRS.Commands
  • CQRS.Events

there’s little bit of DSL in CQRS.Commands to define the list of commands my system accepts. These look like:

public MyApp.LogIn   
public MyApp.Register
private MyApp.CreatePost
private MyApp.DeletePost`

I have a single controller exposed on /api/commands that accepts params that have command name and payload. Public commands are ones that do not require User fetched (have plug for that). Private commands are the ones that get forwarded payload, but additionally current user.

Command looks like this inside:

defmodule MyApp.Commands.Register do
  alias MyApp.Repo
  alias MyApp.User
  alias MyApp.Events

  import  MyApp.Validator

  alias MyAppCommands.Register.Form

  def execute(params, _ \\ nil) do
    form = Form.from_params(params)

    if valid?(form) do
      Events.trigger("UserRegistered", event_data(form))

      {:ok, %{message: "email conrirmation needed"}}
    else
      {:error, errors(form)}
    end
  end

  defp event_data(form) do
    %{
      id: UUID.uuid4(),
      first_name: form.first_name,
      last_name: form.last_name,
      email: form.email,
      lang: form.lang,
      password_hash: Comeonin.Bcrypt.hashpwsalt(form.password),
      email_confirmation_token: Ecto.UUID.generate
    }
  end

  defp token_for_user(user) do
    Phoenix.Token.sign MyApp.Endpoint, "user_id", user.id
  end
end

and in my system commands can either succeed :ok , then generate some events, or fail (return tuple of :error and validation messages.

I do simple validations with GitHub - CargoSense/vex: Data Validation for Elixir · GitHub.

Generated events are being dispatched by my CQRS.Events, that is also a bit of DSL that lists all the events that can happen. They return nothing and they should succeed. I do not have the strategy worked out yet on what to do when they fail. I am experimenting here, not everything is yet perfect.

But basically, commands gets executed, generates some events, those events are handled by events handlers. This is all happening in two workers that are GenServers, so one thing at a time.

In addiion to that I package all my queries into MyApp.Queries… etc. Events modify data, queries read data, I have clear separation here.

Queries are executed normally in Phoenix controllers.

I use Phoenix’ views to serialize results of my queries and send over to client either via JSON or just embed the thing into conn and pass to view.

I haven’t figured everything out yet. I will wrap it up in a library, and write a blog post soon. Maybe it’ll be useful for someone and maybe I get some good feedback. I am not CQRS/ddd expert, so will need that.

sasajuric

sasajuric

Author of Elixir In Action

It’s certainly not intentional :slight_smile:
That said, I’ve read the Evans book a long time (~ 10 years) ago, so it’s possible that some ideas got stuck in my subconsciousness and are still present in my coding style :slight_smile:

Last Post!

mkunikow

mkunikow

DDD + distributed systems

Where Next?

Trending in Wikis Top

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
type1fool
I just stumbled on a newly redesigned elixir-lang.org. :tada: It looks like @Software_Mansion did the work, and I think it is generally a...
New
akoutmos
@hugobarauna and I (Alex Koutmos) have been hard at work on writing a book on Nerves that takes you from simply blinking LEDs to building...
New

We're in Beta

About us Mission Statement