Boundary pattern in send-receive?

How do I organise code with an event-driven approach in Elixir?. I want to establish boundaries in the gaps between the senders and the receivers. What are the library/pattern/convention should I go with?

I want to move beyond the MyApp ← MyAppWeb approach.

Functions are hard-bound. They are modular and composable only until they get called. Once they start calling one another, they form a single rigid system without actual boundary.

Most words I read about boundary are rules of curbing or restricting function calls. The MyApp ← MyAppWeb pattern pretends that MyApp is a library MyAppWeb depends on, like an Elixir project depends on Elixir and a Phoenix project depends on Phoenix.

In this approach, the hierarchy is not as clear as listing them in the deps unless you make it an umbrella and actually put your code in the deps. And this negative approach of not doing something feels too implicit unless you use the Boundary library for it.

One more question I have is the DB side of the app, or Ecto, being the “core business logic”. Isn’t DB as particular as the web? Elixir should be an orchestrator for the DB part, the web part, and the other parts.

So I’ve been thinking about placing the boundaries in the gaps of message-passing. Processes could hold better boundaries than modules. Instead of selectively calling functions, the app comprises a network of processes talking to each other.

I’ve been collecting information but my knowledge is too narrow to penetrate the essence. Where should I define the specs of communication? How do modules align with this approach? Do I spill it everywhere? Can I dedicate the top-level module for it? Can I make it comprehensive without introducing an involved PubSub system?

Reference

1 Like

This sounds like you might quickly fall for the following:
https://hexdocs.pm/elixir/process-anti-patterns.html#code-organization-by-process

4 Likes

Where did you get this from? It’s certainly not true for any project I worked on. Or perhaps you meant that people encode too much logic inside their schema modules?

It is, via a library, and that library is ecto, and ecto_sql, and most likely postgrex as well.

Not sure what you mean here. TLA+ exists but it’s not exactly mainstream.

1 Like

Turned out I was imagining a CQRS/ES pattern without knowing about those approaches. :sweat_smile: It’s a lot involved than I initially thought, but was a good study.

This is something else, but: learning about them, I realised that functional and concurrent (process-oriented) approaches are two completely different paradigms that should be understood differently.

My perspective of Elixir has changed. All this time they confused me because the functional part covers the entire façade of Elixir, even spawning too. If I introduce Elixir to someone next time, I’ll emphasise the distinction like “80% functional and 20% process-oriented”, not together like “functional and concurrent”.

I understood OTP explained with functions, but I didn’t know what to make out of processes. (I thought I did because I understood the basics of OTP)

Processes haven’t been fully visualised in my mind in conjunction with functions. I’ve read Elixir Docs and Elixir in Action several times, but it was a few community posts that enlightened me.

I think the learning path misses something between functions and OTP. Process is introduced for its general concept but not much about how it forms an Elixir/BEAM system and how the user can juggle with them. Then it proceeds to OTP preemptively.

This post deserves a place in the Elixir Docs I suppose:

https://www.theerlangelist.com/article/spawn_or_not

You are right.

I need some teaching to graduate from the MyApp-MyAppWeb idea and grow out of phx.new. I didn’t know what to think about all the Ecto modules embedded deep inside of MyApp. Probably I need to see MyAppDB myself.

Other than that, I was going for CQRS/ES pattern. Thanks!

From the description I think you might only need CQRS part? Event sourcing is a big paradigm shift and often not exactly needed for many cases. Unfortunately, these two concepts became very coupled and there’s not too many examples of CQRS without ES.

Thanks for linking my blog post, by the way :wink:

1 Like