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

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:

Where Next?

Popular in Wikis Top

swelham
Introduction After some discussion with a few other members we thought it might be an idea to start a thread where we can post about libr...
New
axelson
Preamble This Wiki is intended to be a community-maintained (see the Contribution Guidelines if interested) resource of common “gotchas” ...
New
ibgib
Popular Elixir Packages List of popular Atom.io Elixir Packages. These can be installed via atom’s package center or a command line with ...
New
yurko
Here are few pieces of (common) Linux knowledge that we use for reasonably small one server apps. We use Ubuntu but this should work for ...
New
gmile
:httpc HTTP client is part of Erlang standard library, and as such can be easily used in Elixir code too. One particular advantage of usi...
New
Rich_Morin
I’d like to start a discussion of data serialization formats, in the context of Elixir. The rest of this note is a combination of persona...
New
nicbet
Introduction Now that the language is picking up support and maturing nicely, I’d like to start a collection of common and recurring Elix...
New
blackode
Hi and Hello Every Elixirian. After Learning the Elixir basics, I struck then. I have no idea of how to put my Elixir Knowledge in pract...
New
jdumont
Guide Using an iPad for web development can be easily split into two main parts: Setting up the iPad as a thin client Working in a remo...
New
AstonJ
Wonder if we can compile a list of learning resources, blog posts, talks, threads etc to help those who are just learning about Contexts....
New

Other popular topics Top

Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

We're in Beta

About us Mission Statement