Naming conventions when breaking up contexts

I want to split up a large context into different modules, but I’m not sure how to name them.

Here’s a simplified example where the Media context has grown large. I want to extract functions for Post and Link into their own modules, but I already have schemas defined with those names.

I can move the functions into the schemas, but that doesn’t feel right. I’m tempted to use LinkService and PostService, but that feels OO and reminds of Ruby and Rails more than Elixir and Phoenix.

What do others usually name their modules when they split contexts?

defmodule App.Media do
  @moduledoc """
  The Media context.
  """
  import Ecto.Query, warn: false
end

defmodule App.Media.Post do
  use Ecto.Schema
end

defmodule App.Media.Link do
  use Ecto.Schema
end

I just name them whatever is appropriate for what they do (though I just call them modules instead of contexts, I don’t get the ‘context’ name). Every one will be different, it just depends on each one. ^.^

2 Likes

As @OvermindDL1 said. I like to think what I am doing with the media or with the links and posts. Instead of thinking “it is the module of links” (this feels OO to me), I go more like “it is the module that does insert here action with links”.

If you want to keep what you have, you could add Schema respectively. For example App.Media.Schema.Link

3 Likes

Using %Schema.Foo{} is a good suggestion, although I don’t like having to qualify the schema namespace in my controllers. change(%Schema.Link{}), for example.

Assuming I add a Schema namespace and move the Link and Post functions from Media into Link and Post, I would end up with something like this:

defmodule App.Media do
  @moduledoc """
  The Media context.
  """
end

defmodule App.Media.Schema.Post do
  use Ecto.Schema
end

defmodule App.Media.Schema.Link do
  use Ecto.Schema
end

defmodule App.Media.Post do
  import Ecto.Query, warn: false
  def get_post(id), do: Repo.get(Post, id)
end

defmodule App.Media.Link do
  import Ecto.Query, warn: false
  def get_link(id), do: Repo.get(Link, id)
end

Media becomes nothing more than a namespace as I expose Media.Link and Media.Post to the public API, or…

… I don’t use the Schema namespace. Instead, it’s easier to take the functions in Media and add them to link_functions.ex and post_functions.ex and expose them via defdelegate in Media.

Choices choices!

2 Likes

Functional programming is “new” and phoenix is what the best developer came to make the OO programers confortable to work with FP. Dosesn’t matter what you choose. When you finish, you will have a clearer mind and you always can refactor it. It is one of the wonderful thing FP has.

At the end what matter is that you make a choice.

1 Like