I briefly discussed this with José in an issue a while back and got to thinking about it again recently. (I don’t work with Phoenix day to day.)
He made the case that single-component modules are discouraged.
I still don’t quite understand/agree with the reasoning, so I thought this forum could be a good place to continue the discussion and solicit more opinions. I’m hoping to get a better idea of the idiom, or even to convince someone that perhaps it’s not such a bad approach
To me it seems quite reasonable to use single-component modules, for a few reasons:
- You only need to name one thing, not two.
MyWeb.NoUsernameComponent.render
vsMyWeb.NameThisModule.no_username
. This assumes a conventional, generic function name likerender
that you don’t need to think about. The framework could make that function call implicit. - If the component makes use of private functions, those have high cohesion, as opposed to a module where component A uses two private functions and component B uses two other private functions.
- It’s intuitive and easy to navigate to some desired component when you can find it by file name. (Some editor setups also let you navigate by function, but I believe finding by filename is rather more common.)
José mentioned that compilation will be slower with more files – that’s fair, but perhaps a secondary concern, unless the app has a very high number of components? I suspect people generally don’t optimise for a minimal number of modules, but use them as a way to organise the code.
He also argued that functions and not modules are the building blocks of Elixir, and e.g. Enum
has a bunch of functions, rather than having Enum.Map.call
and so on. My counter-argument would be that modules also play some roles. A co-worker made the case that GenServers are very module-centric. LiveViews themselves are modules with a conventional render
function, called implicitly when you do live_render(@conn, MyApp.MyLiveView)
.
Would love to hear more arguments and opinions.
To make it less abstract – I’d love to hear what you’d do with components like NoUsernameComponent
and NoContentComponent
. What module/function names would you use?
cc @thiagomajesk (who seemed to also favour single-component modules in another GH issue).
I can’t decide whether it’d be more polite to at-mention José or not here, since he must be exceptionally busy. I’ll err on the side of fewer notifications.