Any Elixir resources for framework agnostic architectures?

Background

I have been reading quite a lot about design and architecture in Elixir and overall FP. My latest incursions took to me the Onion Architecture and the Functional Core / Imperative shell:

Only to find out that there is no real consensus among the community. From what I understand the community overall likes decoupling but it is still finding and architecture that works.

Question

That post is however quite old, as well as the resources they link to ( some of them are from 2015 ). I was wondering if there are any books, courses and material over all where I can learn software design and architecture in Elixir ( using the Actor model perhaps together with a layered architecture ) that don’t use frameworks, like Phoenix. I am looking for something more 
 agnostic. mainly because I see Phoenix is used mainly for webapps.

Any recommendations?

1 Like

Have you seen


He uses Phoenix
 but only for the web layer :slight_smile:

The best architecture book I’ve ever read in my 25 year career is Designing for Scalability with Erlang/OTP but as the title implies, the examples are all in Erlang. The good news is it all applies in Elixir since we share OTP and BEAM, but you’ll have to invest the time to at least be able to read basic Erlang (which isn’t hard).

5 Likes

I suspect that you are now venturing into an area where focusing on Elixir-specific resources is going to isolate you from potentially useful information. Then there is the other consideration that these information sources will tend to require more work on your part to transfer value into the Elixir realm.

Given that you have already had some exposure to Scott Wlaschin, [Functional Programming] Domain Modeling Made Functional (Pragprog) (F#) may be worthwhile even if it is in F# rather than Elixir (one discussion that precipitated from it). Chapter 3 is actually called “Functional Architecture”.

Then of course there is [Erlang] Designing for Scalability with Erlang/OTP (O'Reilly) (ebooks.com, Google). While there are no “prescriptive architectures” being discussed as such, it does give you insights on the principles that the BEAM design was based on which in turn builds a better understanding which “architectural approaches” compliment or fight it.

Strangely enough sources like Principles of Service Design have some interesting tidbits (i.e. not everything is relevant) simply because it moves beyond dogmatic object thinking. E.g. Service Autonomy as aspect of a bounded context.

And a lot of the material you see today still draws from Pattern-Oriented Software Architecture, Volume 1, A System of Patterns, Patterns of Enterprise Application Architecture and Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions.

The issue is that advice is now going to be much less focused and prescriptive because of an increasingly significant “it depends” factor. For example where an Elixir solution is deployed is going to exert different architectural and design pressures.

1 Like

I take it you bought the course? What were your impressions?

Interesting, which patterns do they talk about?

@peerreynders My greatest fear is not being able to transport what I learn into Elixir. I guess I could try Domain modeling made functional, since I have watched quite a number of conferences from Scott and I don’t think F# is too different from Elixir.

If I had to pin point it, I would say that my greatest issue right now is not understanding why Elixir is so focused on Mocks when it can use Functional DI (which I have been using in JS for years now) and I am still not clear on how this approach would affect my work.

At the end of the day I really want a project easy to change/modify and understand. I know there isn’t a silver bullet but I guess I am hoping for some guideline.

Thanks for the resources!

1 Like

None of the conventional OO patterns you may be familiar with :grin: You can see the full table of contents here Designing for Scalability with Erlang/OTP [Book]

I read that book hoping to apply it to Elixir too, but I found that well over half of the content was about static typing.

Hmmm. That’s not the impression I have about Elixir. JosĂ© has even famously written about mocks Mocks and explicit contracts « Plataformatec Blog

1 Like

Check out my review here:

Also, see the comments left by others - it’s a very popular course :023:

1 Like

If I understand what you are saying, you seem to be unclear why so much “reusability” seems to revolve around Behaviors instead of functions.

Read Chapter 3. Behaviors on Google’s sample.

Processes interact through messages, not function invocations therefore process skeletons are implemented as Behaviors.



3 Likes

To add to what @peerreynders and @gregvaughn have said,

Even in OOP the best way to determine abstractions (use of design patterns) was to look at the messages between objects. Regardless of if the objects were calling methods on each other and it wasn’t at all the same as a BEAM process messaging - the way to figure out how to decouple and configure dependencies was too look at the messages and the contracts between components.

The difference lies with imperative OOP-style vs actor model and how first-class messaging is. To achieve architectural goals by inverting dependencies and implement decoupled systems with imperative-OOP requires (in my opinion) more overhead and complexity. So much so that there are entire books about the design patterns! (I really like Sandi Metz’s books on OOP because there’s less emphasis on the design patterns and more on the messages). Regardless it’s more straightforward in our actor model world. Maybe messaging contracts seem scarier because we don’t have a handy book of conventions to use?

The part of Domain Modeling Made Functional I really liked was his description of different messaging contracts between contexts. Scott broke it down into three different types (paraphrasing):

  • Shared Kernel: A shared module that separate bounded contexts or pieces of the system depend on. A given change requires coordination between both contexts. This entails high coupling and costs in exchange for properties like compliance and preventing breaking changes made by one team.
  • Consumer Driven: The downstream consumer of messages dictates how the producer must behave. If the consumer wants a change, the producer must conform to the new contract.
  • Producer Driven: The producer of the message controls how the consumer must behave. The consumer must comply to changes made by the producer or break.

A big shared kernel we have in the ecosystem are Ecto Changesets. Phoenix uses Ecto Changeset for Phoenix HTML. There’s a trade-off of dependencies but we get benefits of surfacing errors from changesets and reducing a lot of work. The mutual dependency is probably fine since Ecto is a well-established and stable open source project, but it’s there none-the-less.

So what the Elixir community uses (mocks / behaviours / messaging contracts) are in the same category as the gang of four pizazz but simpler because the actor model puts messages first class.

1 Like

Very good points overall @MrDoops, but I’d like to offer one clarification.

phoenix_html defines a protocol called FormData and implements it for Ecto.Changeset to minimize that coupling. I don’t believe F# has protocols, so it wasn’t an option in the book. Elixir copied that idea from Clojure.

2 Likes

We have an Elixir Foundation video series, with 10 episodes out and more on its way, we use elixir’s plug for the web layer, show you how to create your own project from scratch.