khaledh

khaledh

Continuing the discussion from Domain-oriented web folder structure:

Essentially:

hello_web
├── controllers
│   ├── foo_controller.ex
│   ├── bar_controller.ex
├── templates
│   ├── foo
│   │   ├── index.html.eex
│   │   ├── ...
│   ├── bar
│   │   ├── index.html.eex
│   │   ├── ...
├── views
│   ├── foo_view.ex
│   ├── bar_view.ex

to:

hello_web
├── foo
│   ├── foo_controller.ex
│   ├── foo_view.ex
│   ├── templates
│   │   ├── index.html.eex
│   │   ├── ...
├── bar
│   ├── bar_controller.ex
│   ├── bar_view.ex
│   ├── templates
│   │   ├── index.html.eex
│   │   ├── ...

I hope @chrismccord will consider making this easier in a future release :slight_smile:

Showing Posts 1 to 10

chrismccord

chrismccord

Creator of Phoenix

It can’t get any simpler than:

use Phoenix.View, root: "lib/hello_web/user/templates", path: "*"

So I don’t think there’s any more we can provide here. It’s already possible using the same setup that we provide out of the box :slight_smile:

bulldog_in_the_dream

bulldog_in_the_dream

No biggie, but there’s a case to be made that the folder structure @ khaledh suggests is more in accordance with DDD. Personally, I’ve always perferred this feature based division, DDD or not.

A beginner would have to dig a little bit to achieve this. For it to be default is probably wistful thinking. :slight_smile: But it would be nice to e.g. have it as an option to phx.new

chrismccord

chrismccord

Creator of Phoenix

An option to phx.new would provide two ways of doing the exact same thing, which actually could harm newcomers with an unnecessary choice. Our goals with Phoenix defaults have always been sane defaults that are easily customized for those that require it. Wrt to DDD, we treat the the web as the domain. Grouping templates, views, and controllers is file organization, which the proposed alternative is just fine, but not something the Phoenix team views as preferable. But the point is there is nothing special about our defaults, and to achieve your own desires you can use the same options we use to ship our own out-of-the-box behaviour.

10
Post #3
bulldog_in_the_dream

bulldog_in_the_dream

Fair enough. I see your point about not wanting to add an option that is a variation over the same.

khaledh

khaledh OP

Hey @chrismccord, it’s great to hear your thoughts on this issue :slight_smile:

I feel I’m missing something here. Where would this code go? I’m assuming it would replace the default in HelloWeb:

use Phoenix.View, root: "lib/hello_web/templates", namespace: HelloWeb

If that’s the case then wouldn’t this just move the template root to another folder for all views? My goal is to customize the template folder per view.

Another way to interpret your suggestion is to add that line inside each view, i.e.

defmodule HelloWeb.UserView do
  use HelloWeb, :view
  use Phoenix.View, root: "lib/hello_web/user/templates", path: "*"
end

If that’s the case, then I think we’d have to remove the call to use Phoenix.View in the HelloWeb module, otherwise it would be called twice.

Wrt to DDD, we treat the the web as the domain.

Fair enough. I can see this being easier to grasp for most people starting with Phoenix. It’s just for us who got accustomed to organizing code by domain it wasn’t so obvious, hence my question :slight_smile:

chrismccord

chrismccord

Creator of Phoenix

Correct, you could either use @tme_317’s example and keep the code inside the view function of AppWeb, or you could remove that line and call use Phoenix.View, ... as in each view.

khaledh

khaledh OP

Great! Thanks again for chiming in :slight_smile:

Crowdhailer

Crowdhailer

Creator of Raxx

For any application using Phoenix, the web is a delivery mechanism and not a Domain.
i.e. a todolist app might have two domains Tasks & UserManagement, they are both available over the web but there is no web domain.

Within Phoenix the web can be considered a domain but that would be an argument for how the Phoenix project might order its code and should not be a concern of the end user.

I made some similar comments in my recent talk on the MVC architecture. This is the resource I use to explain my reasoning is Cohesion (computer science) - Wikipedia
Grouping things because they are “controllers” is Logical cohesion and according to that page that is the second “worst” type of cohesion.

chrismccord

chrismccord

Creator of Phoenix

I think we actually agree on this point:

Phoenix is indeed only the web interface to your application. The Tasks and UserManagement contexts would live outside of app_web/.

This would be true if we encouraged users to write their application and web code together, such as app/user_management/controller.ex|user_management.ex, but this would directly couple app code and web code together. If we agree the Phoenix is the delivery mechanism to your application, then it absolutely makes sense to group controllers together, because we are only concerned with dispatching web requests into our application, and converting the results into responses.

For example, if we look at the web directory structure of such an app:

app_web
  controllers
    user_controller.ex
    task_controller.ex
    api
      v1
        task_controller.ex
    resolvers
      task_resolver.ex

It passes the test of screaming its intent, within the context of The Web. We are translating user and tasks requests into responses. Those controllers may hook into entirely decoupled parts of our application. With a glance, I can immediately see what the web layer is responsible for, down to handling user requests, a JSON an API, and servicing graphql clients for tasks. If the app had grouped the directories per user/task, I would need to hunt down what the web story actually looks like.

So for me our defaults encourage better application design exactly because the web side is only focused on being the delivery mechanism. Of course we don’t force this on folks and you are free to structure your directories as you see fit :slight_smile:

Hopefully that gives insight to our dir structure.

10
Post #9
bulldog_in_the_dream

bulldog_in_the_dream

A feature based folder structure simply divides the web context into smaller sub-contexts, still within the context of the web/presentation. The web part is still just as much focused on being the delivery mechanism. I fail to see how a folder structure like e.g. the one below is less clear than the existing one:

app_web
  task 
    task_controller.ex
    task_channel.ex
    templates
      edit.html.eex
      index.html.eex
      ...

Rails popularized the MVC architecture — but Rail’s version is in many ways a misreading/reconceptualization of the original proposal [1, 2]. It works completely fine, but I don’t think it’s a given it’s best way to do it; I think it’s more a question of what one is most familiar with.

I think of it as slicing things horizontally vs. vertically. Rails slices things into horizontal layers, but an argument could also be made for vertical slicing [3].

Django is one example of an alternative solution, .NET’s Razor Pages is another novel and simple way of doing it.

  1. http://stephenwalther.com/archive/2008/08/24/the-evolution-of-mvc
  2. http://heim.ifi.uio.no/~trygver/2007/MVC_Originals.pdf
  3. Vertical slices in ASP.NET MVC

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 94592 917
New
cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
heathen
Quite interesting article Google brought me. Didn’t find any mentions about it here. What do you think in general? Would you use togethe...
New
maennchen
:warning: Security advisory: Decimal DoS vulnerability A vulnerability has been published for decimal where very large exponents can cau...
New
marciol
It would be helpful to have a list of companies worldwide that hire engineers without prior experience in Elixir. Often, it can be quite ...
New
durvia
Anyone running long-lived stateful processes on BEAM? We’re building an AI agent runtime and would love to compare notes. We’re a small ...
New

Other Trending Topics Top

marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
webofbits
Aludel - LLM Evaluation Workbench Aludel is an embeddable Phoenix LiveView dashboard for evaluating and comparing LLM prompts across mult...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews