thiagomajesk

thiagomajesk

What's your process on splitting application logic?

Hello everyone!

There’s a common concern/ discussion I have with my peers and I’d like to collect insights from the community regarding this topic which is: how are you splitting the code between your contexts and schemas?

I’m a little bit more familiarized with DDD applications from my previous experiences as a software architect while the majority of my peers seem to come from a “classic” Rails MVC background. Because of this, I’m facing some challenges trying to articulate properly some architectural concerns regarding our application domain that are not usually implicit to them.

I acknowledge that DDD practices sound sometimes too conservative for people accustomed to a less structured way of building applications. Besides that, it goes without saying that the whole decision-making process becomes a lot harder than it should be because there’s too much convincing going on most of the time (IMHO, this wouldn’t happen if there were more overlapping knowledge in this specific area).

I framed some questions that might help us get this sorted out:

  • Are you using schema’s functions to return only Ecto changesets?
  • Where are you currently placing your domain/ model/ entity logic?
  • Do your schemas deal with “domain/model” concerns or not?
  • Are your contexts the only public interface between outside code and your schema?

As a side note: I’m looking for some objective and concrete techniques or concepts you’ve been applying to identify and organize your application logic with Elixir. I say this because I think this information would resonate better with more pragmatic people.

I think you got the gist. Please, feel free to elaborate further if necessary.

My best regards to everyone.

Most Liked

hlx

hlx

In Programming Ecto there is a chapter called “Optimizing Your Application Design > Separating the Pure from the Impure” which basically says that pure functions (with no side effect) can be placed in schemas while impure (with side effects like database access) can be placed in contexts. This means that changesets, queries and multi’s can go in the schema and the rest in the context.

I really like this idea and I’ve been using it a lot and it works well for me, but after reading Saša’s comment I’m eager to try out putting changesets as private functions in the context for this current project I’m working on.

sasajuric

sasajuric

Author of Elixir In Action

I personally don’t think that changeset functions belong to schema. About a year ago I’ve started consulting an agency, and proposed the team to write changesets as private functions in context modules, and that’s been working really well. In most cases I’ve seen, a changeset function is used in exactly one place, which is not a schema, so making this function public and moving it to another module makes little sense to me, and it complicates the reading experience. Even when it’s used in multiple places, there’s typically a strong cohesion between all callers (they work on the same data), so they are a part of the same context module, and hence changeset as a private function in that same module works fine.

We usually don’t have functions in schemas, but we may add some helpers for computing derived properties. E.g. say that the OrderItem schema has fields quantity and price. If I need a function total_price, I’d define it in the schema.

We mostly stay away from virtual fields. I think there was one case where we used it to store some derived value computed at the database level.

In context modules.

They are our main domain types, since we don’t transfer data from schemas to pure Ecto-independent data structures.

Schemas are returned from contexts to web tier, and they are used by controllers, resolvers, and views to produce the output. Therefore, they are not an internal implementation detail of contexts.

Note that I’m not suggesting this as a universal pattern, but it’s been working well for the client’s projects, which I’d categorize as small-to-moderately complex.

sasajuric

sasajuric

Author of Elixir In Action

When a context module grows large, we split it and/or extract some related group of private functions into internal private modules which are only used from within the context layer.

Where Next?

Popular in Discussions Top

Other popular topics Top

chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I fore...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "eq...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 47849 226
New

We're in Beta

About us Mission Statement