What are the design patterns to share same functionality in elixir?
For example, I have an app that "takes" a structure, "transforms" structure to different format and "pushes" it to some storage. I have 3 structures that go thru this pipeline with 3 transformation rules and 3 storages.
the project uses gen_stage package and it has following structure:
(book) |producer| -> |transformer| -> |indexer|
(article)|producer| -> |transformer| -> |indexer|
(post) |producer| -> |transformer| -> |indexer|
Each stage is a separate module, i.e. Book.Producer, Book.Transformer, Book.Indexer.
Stages on the same vertical line doing the same thing but with different entities. I.e. Book.Producer taking books from database, Article.Producer taking articles from database, etc.
The "Taking from database" piece is fairly general and can be re-used across all pipelines, i.e.
alias Experimental.GenStage
defmodule Books.Producer do
use GenStage
def start_link do
GenStage.start_link(__MODULE__, [], name: __MODULE__)
end
def init([]) do
{:producer, []}
end
def handle_demand(demand, processed) when demand > 0 do
events = Repo.all Book
{:noreply, events, processed ++ events}
end
end
The transformer runs a function on an entity produced from database. The indexer pushes the transformer records into another storage.
In a naive approach with a lot of duplication, I could have 9 (3 for Book, 3 for Article, 3 for Post) modules that's doing all these steps.
What options do I have to extract bits of similar functionality and share it between modules that use it.
Perhaps I can configure it via passing params at initialization stage, or just still have 9 modules, but refactor functions into another module. What is the best practice?