Integrate a "pure functions" core with DB via Ecto

Here’s a post that may be somewhat relevant (probably less for the data structure discussion but more for the migrating to GenServer bit coming later): The Erlangelist - To spawn, or not to spawn?

There is something that sits between an Ecto schema and a map - an Elixir struct (see defstruct in the docs) - it give your data a more defined shape than a pure map but without binding to the persistence mechanism. An Ecto schema is really just an Elixir struct with some extra fruit.

Depending on the whole scope I would most likely build this kind of thing using elixir structs for most of the data types going in and out of the core functions. I may start out with plain maps and lists while I’m iterating, but prefer structs for the extra safety net they provide (e.g. you can use pattern matching to ensure your core functions are only called with the correct data structure). I’d make the core function work how I really want them to work without considering persistence. Then I’d look at persistence and if it just so happened that one of the structs looks more or less like the database table that would be used for persistence I might upgrade that struct to an Ecto schema. I wouldn’t generally return a changeset from a core function - the persistence functions should be responsible for converting what the core functional layer is doing into something that can be pushed into the database.

There’s a bit of a discussion about generating changesets from plain structs here:

There is a also a highly relevant discussion in “Designing Elixir Systems with OTP” (Chapter 9) - a Pragmatic Programmer title (so you can probably get a discount). This also includes a pattern for dependency injection of the persistence mechanism if you want to take decoupling layers to the next level.

5 Likes