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