How to approach editing in layered approach from "Designing Elixir Systems with OTP"?

Throughout the book, the examples deal mostly with creating data. When the quiz runs, it always persists new answers.

Let’s say I want to add UI for creating quizzes, and it has ability to edit templates for the quiz. How would you design the core API for that function? I came up with something like this:

def edit_template(quiz, template, fields_to_update)

It is a little bit awkward to test, though. Because I need to get the template from a sequence of pipes like this:

quiz =
  |> Quiz.add_template(template_fields)

template = Quiz.get_template_by_name(name)

quiz =
  Quiz.edit_template(quiz, template, template_fields)

Is there a clearly better aproach? Or maybe dealing with mutable/nested data always will be a little awkward.

Pinging @JEG2 since you were very helpful with the last question :slight_smile:

My instinct is that we could add a new data structure for tracking quiz building. It might look something like this:

defmodule QuizBuilder do
  defstruct quiz:, templates: # …

  # functions here take and modify the struct above

Then I suspect edits will compose much better, with normal pipes.

@JEG2 I wonder what would you add as a key in that map. Let’s say I’ve added UUID to the template, and I generate one in

def new(template_fields) do
  template_fields =
    |> Keyword.merge(uuid: UUID.generate())
  struct!(%__MODULE__{}, template_fields)

Then, if the map is %{uuid => template} it doesn’t help a lot. I still need to extract the template uuid.

Alternatively, I could try not generating UUID in the new function, then test builders would normally create the UUID as other fields, so the functions would be of shape.

def edit_template(quiz_builder, template_uuid, template_fields)
# previously, it was `template` struct instead of `temlate_uuid`

Now, there is another problem: where do I generate the UUID? I don’t think I want API user to pass the UUID every time when they create new template. Is it OK to generate the UUID in the API layer?

I was thinking you might store them by name, to skip step two of your example.

I was also thinking about storing them by name but then I can’t edit the name, so I thought some kind of permanent id (uuid) would work better.