Another point that Dave drives home in his course is that applications really are components, and you should treat them as such. Not as “full fledged applications”. We’ve been doing that umbrella-style before, but umbrellas are confusing and I always felt that even mix phx.new --no-ecto --no-html --no-brunch api
generated a ton of fluff. In the same vein that files/modules are free and you can use them to separate api/otp glue/implementation, applications are free and you can - and I think should - use them to separate concerns. The reason therefore that I’m putting this here is that I feel it’s basically the same principle at work.
We’re setting up a new service, that will be responsible for various internal permissions related stuff. The “hard” part so far was whittling down the Phoenix generated code to something clean and manageable:
..../api$ find test lib config
test
test/support
test/support/conn_case.ex
test/test_helper.exs
lib
lib/api.ex
lib/api
lib/api/endpoint.ex
lib/api/router.ex
lib/api/user_policy_controller.ex
lib/api/application.ex
config
config/config.exs
config/deploy.exs
config/dev.exs
config/test.exs
no channels, no contexts, no mixing up of UI and business logic in a single OTP application. The sole controller:
defmodule Api.UserPolicyController do
@moduledoc """
This module contains the interface between the API and
the business logic in the user_policies application..
"""
use Api, :controller
def get_for_user(conn, user_id) do
{:ok, policy_document} = UserPolicies.get_policy_for(user_id)
json conn, policy_document
end
end
which calls out to a sibling app (using the “poncho” organization style):
.../user_policies$ find test lib config
test
test/test_helper.exs
lib
lib/user_policy.ex
lib/user_policies.ex
config
config/config.exs
I like this a lot better than the Phoenix default “we are Rails and toss everything together” mess. These are skeleton both currently applications, but it is immediately clear where things go when we start fleshing them out, there’s very nice separation of concerns, a random bypasser can pick an interest and only open that code, and so on. Frankly, with the biggest cost being a top level Makefile to drive CI builds (I’m settling on a pretty standard skeleton for that), I think it’s worth pursuing. At least experimenting with, to see how it feels. My gut says it feels much better, and after ~40 years of coding, I have learned to rely on my gut. YGMV, of course.
(and I’ll shuddup now with my heresies )
Edit: See post 20 and below for Dave’s talk on this topic and the discussion following the video.