crenwick

crenwick

How do we organize our project

Hey yall, I have a project organization question:

We are building two internal elixir apps (i’ll call them “local_app” and “cloud_app”), which share a ton of code so we decided to go with a monorepo strat.

Here are all the elixir projects under the repo. (Note: only the _app projects are elixir applications. the other projects are simply changesets and functions.)

home
├──local_app
├──cloud_app
├──shared_models
├──local_models_api
└──cloud_models_api

Basically, what happens is that the we needed both the local_app and cloud_app to know what a shared_model is, so we abstracted away those schemas and changesets to the “shared_models” project, which both _app’s declare as a dependency using the path: ../shared_models option.

We need both apps to know how to read those models, however only one app should have right access to a specific model. For example, we might have a SharedModel.Note schema, which both apps will know how to read, and the API to get the notes might live there too (SharedModels.Notes.list_notes/0). However, we only want the local_app to have write privileges to those notes—this is so important that we don’t even want the write functions available to cloud_app at compile time—so we made a local_models_api project that exposes functions like LocalModelsAPI.Notes.create_note/1 and only the local_app uses that as a dependency.

(The reason we needed that code to live in a separate local_models_api project and not just live in the local_app project is because we needed to write test helpers for the cloud_app test suite that writes a handful of those models in order to test some other behaviors, so we have cloud_app declaring local_models_api and a test only dependency.)

Vis-versa, we only have some models that we want write access to via the cloud_app, so we created the cloud_models_api project.

This leads to messy alias APIs in our application code, for example, its really common for a server_app controller to have

use LocalWeb, :controller

alias LocalModelsAPI.Notes
alias SharedModels.Notes.Note

and we use the defdelegate pattern at the bottom of the LocalModelsAPI.Notes module to bring in all the SharedModels.Notes functions into the LocalModelsAPI.Notes namespace (which leads to compile time warnings that functions don’t exist, but we ignore those).

It also leads us to have a messy test pattern. For example, we want to test our LocalModelsAPI logic in our local_models_api project, but because it doesn’t have its own stand alone application, it cannot run a DB. So instead, we added the "../local_models_api/test" to the test_paths list in our LocalApp mix file. (Which then leads to doubling our tests for the SharedModels project, but that’s fine.)

Is there a simpler way?

To recap, the problems we need to solve:

  • Have a shared library of models
  • Have some APIs of those models only available to specific projects
  • Have all those APIs available to all the projects test helpers

First Post!

hauleth

hauleth

Seems like you wanna do synchronisation and communication via DB. In that case I have only one answer for you - don’t.

Last Post!

crenwick

crenwick

lol, good guess but no. We just already have another application taking care of syncing (just not via the DB).

Where Next?

Popular in Questions Top

rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

Other popular topics Top

New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 55125 245
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 44778 311
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 44265 214
New

We're in Beta

About us Mission Statement