Skip to content

Instantly share code, notes, and snippets.

@ythecombinator
Created April 11, 2016 17:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ythecombinator/3a67575dc8e25391ab34b4d137c4e594 to your computer and use it in GitHub Desktop.
Save ythecombinator/3a67575dc8e25391ab34b4d137c4e594 to your computer and use it in GitHub Desktop.

(my response to https://twitter.com/apotonick/status/717105889845624832)

I haven't yet came across readily available resources for large-scale application architecture for Elixir apps. I found Programming Phoenix to be a good start for that though. And there's ~30 years of knowledge in the Erlang land :)

For web apps, I found the abstractions that Elixir/Phoenix provides to be really helpful. Indeed, the list below is somewhat ORM focused.

In the small, Ecto.Schema, Ecto.Query, Ecto.Changeset, and Phoenix.View allow me to build highly composable and side-effect free modules. I can have many schemas, changesets and queries all interacting with the same underlying DB table(s) if I want to. Most of the side-effects (through Ecto.Repo for DBs) are usually in the Phoenix.Controller (or other Plugs). When the plugs grow too large, or I need to re-use the logic somewhere else, it's easy to extract out modules (which I tend to put in web/models). To compare it to Trailblazer architecture, indeed there's no explicit Operation-like abstraction in Elixir/Phoenix which is supposed to group all business logic and be independent of DBs etc. Because most of the building blocks are side-effect free and highly composable, I don't usually feel an urge to have it though (and when I do, I'd extract the module out of plug as I mentioned above)

In the large, one builds the system out of modules and applications (collection of modules). You really need to set these things up explicitly in application specifications and supervision trees, which then provides visibility in both compile-time (see: https://gist.github.com/josevalim/67cc4fdbd66f96c647fd) and in runtime (see: :observer.start). In Phoenix, you start with one Router, Endpoint, and Repo but you're free to add more (https://dockyard.com/blog/2015/11/18/phoenix-is-not-rails, http://theerlangelist.com/article/phoenix_is_modular). Finally, for larger (or even not so large) systems, one is encouranged to use umbrella apps (http://elixir-lang.org/getting-started/mix-otp/dependencies-and-umbrella-apps.html) to make the boundaries even more explicit. There's a good chapter about umbrella apps in the "Programming Phoenix" book.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment