dsignr

dsignr

Hi all, my first post here. Certainly not new here.
First of all, huge congrats on the team for 1.3. It’s amazing in so many ways that it has actually forced me to re-think the way I create applications. I found myself spending hours at coffee shops drawing diagrams, contexts, etc. and each time I do it, I discover something new about the business problem space that I didn’t think of before (as a programmer). I’m loving it so far! However, I’ve seem to hit a roadblock..

Before I dive into my question, I’d like to give you a heads up:

  • I’ve so far read all 3 of the major books on DDD
  • Watched Chris’s video of Phx 1.3
  • Searched the forum posts

So, now for the question.

I’m building an ECommerce portal based off Phoenix 1.3. Let’s assume I have just 2 contexts - CMS and Ecommerce.

- CMS
- E-Commerce

Now, it so happens that the CMS domain has a page entity. While the Ecommerce entity has a product entity. I want to create a category model within the CMS context as well as the Ecommerce context.

- CMS
--- Category
- E-Commerce
--- Category

However, when I run the generators for the category, they seem to conflict:
mix phx.gen.html CMS Category categories name:string shortcode:string description:text
mix phx.gen.html ECommerce Category categories name:string shortcode:string description:text

They seem to overwrite the controllers and the views with one another, since they are all generated inside the Web context:

* creating lib/marketer/web/controllers/category_controller.ex
lib/marketer/web/controllers/category_controller.ex already exists, overwrite? [Yn] y
* creating lib/marketer/web/templates/category/edit.html.eex
lib/marketer/web/templates/category/edit.html.eex already exists, overwrite? [Yn] y

So, community, kindly help me to understand:

A. What exactly is the web context for?
B. Why can’t my Ecommerce and CMS namespaces handle their own templates, views, etc, separately

For example:

Ecommerce/
   controllers/
        ....
   templates/
        ....

CMS/
   controllers/
        ....
   templates/
        ....

C. The whole problem seems to arise because everything is being dumped into the Web context. I don’t understand, everything is technically a web-facing entity, right? Phoenix is a web application framework, so my CMS, Ecommerce by right are all web-based functionalities already. Why should I dump it all into the web folder?

D. How would you re-architect this, instead? Clearly, I don’t seem to understand the new structure, or I’m missing something basic. I would really appreciate if someone can point me in the right direction.

Your thoughts, advice or any sort of help is much appreciated :slight_smile:

Thank you for your time.

Showing Posts 1 to 10

easco

easco

As I understand it, Contexts in Phoenix are meant to separate your model behaviors from the way those models are persisted (e.g. In a database). What you seem to want to do is separate elements in the view and controller layers using the same context concept. Seems like something you could legitimately want to do, but I just don’t think they Context concept from Phoenix 1.3 is meant to do that.

What make make more sense, in your case, is having separate applications (one for E-commerce and one for CMS) in an umbrella framework. Your two web front ends for each of those areas could share underlying logic in a third application for shared model level functionality.

dsignr

dsignr OP

Thank you for your quick response. Suddenly, Umbrella makes total sense. However, I have a rather (stupid) question - Umbrella apps can’t run on the same port, if I’m not mistaken. So, in this case, my users can’t edit CMS pages and Ecommerce products on the same port (4000) right? How do you deal with this scenario?

I’m concerned that when my port 4000 is tied to CMS, it would be something like:
URL 1: admin/cms/pages/new
And say, 4001 would be tied to Ecommerce, it would be on a url like:
URL 2: admin/ecommerce/products/new

So, my user simply/easily can’t navigate from URL 1 to URL 2, right?
Please correct me if I’m wrong.

Thank you for taking the time to help me out :slight_smile:

yurko

yurko

I don’t think there is a right (or wrong) answer here, my 2 cents: I’d probably leave the web part in one app, but refactor the generated controllers (I always do that, no matter the phoenix version). Generators are meant to be the starting point, they don’t have to define your structure.

Here is an example from 1.2 application: I have admin area with crud etc and frontend with some lists for say products. These two are different in all but models - admin needs to have a separate login etc.

So I have stuff like this in router:

scope "/", App do
...
  get "/products/:category", ProductController, :index
...

scope "/admin", App.Admin, as: :admin do
    ...
  resources "/products", ProductController

and in controllers there is an App.ProductController for frontend as well as nested App.Admin.ProductController in the admin subdirectory. Same with views and templates.

In bigger projects I use further nesting of entities, it doesn’t have to be the way to do things but treating the generator’s results as a starting point works all the time :slight_smile:

dom

dom

You can use a “proxy” app like in the Acme Bank sample project.

dsignr

dsignr OP

Hi Dom,
Thank you very much. That’s an interesting approach. Do you know if this proxy will negatively impact performance? Thank you :slight_smile:

dom

dom

The “proxy” is just a plug that looks at the URL and calls the right function: acme_bank/apps/master_proxy/lib/master_proxy/plug.ex at master · wojtekmach/acme_bank · GitHub

So, the impact should be negligible.

dsignr

dsignr OP

Thank you, Dom.

One quick question, still relevant to the topic:

How do you handle authentication?

I foresee two scenarios:
A. I setup a separate app called “Auth” for handling authentication. But then every other app will need to go through this app to check if a given user is authenticated and is authorized to perform the requested action. (Eg. view a particular resource/page). This seems like a violation of boundaries in terms of DDD to me.

B. I setup an auth sub-module under each app, and the current_user is simply tossed around from one app to another. Honestly I have no idea how to get this done.

Additonal info:

  1. I come from a Rails background, so I’m still trying to break free of the Rails mindset. While at the same time, I want to make sure I’m not making a spaghetti (code wrangling from different modules) in the process.

  2. I use coherence for my app setup. I have no idea how to break auth and user since they seem to be tied together.

  3. After the advice on this thread, I’m now using an umbrella structure.

All I want to do:

From my previous example, when I visit Ecommerce to CMS, I would still need to be logged in.

I remember vaguely @josevalim mentioned somewhere in this forum along the lines of

Don’t pretend there are separations when there isn’t, it will only make things complicated.

I believe this is exactly where I’m stuck.

Thank you for your time, your help will be much appreciated :slight_smile:

mjadczak

mjadczak

I don’t see how this is a violation of boundaries—if you have an app whose purpose is to handle authentication and authorisation, you could write a clean interface there and it would absolutely conform to DDD. The Auth app does not necessarily need to “know” about users past e.g. their emails or IDs.

So you could have an interface that lets you, say at signup, say to the Auth app “the user with ID 78 is allowed to buy products”. On login, you could call into the Auth app with the credentials, and if correct, it could give you the user_id (to be used with the Users context) as well as perhaps some sort of identity blob. Later, e.g. in an ECommerce controller, you could have a plug which grabs this identity blob (representing a logged-in user) and ask the Auth app if the user is allowed to, say buy an item. If not, you take appropriate action.

Another thing to consider is whether you actually want to separate your frontends into two apps. It is totally valid to have three apps, one managing ECommerce logic, one managing CMS logic, and one Phoenix app being the frontend to both. I like to separate things into their own modules first, and only if it becomes clear I really am running two independent systems do I refactor those out into separate apps in the umbrella.

One big thing which I’m not sure has been mentioned, and which is really different from Rails, is that Phoenix is not your app. When people say “app” in the Elixir community, they often mean an OTP application, which is just a bunch of modules and processes running together, often under one supervision tree. The advice you’re being given is to create your business logic in separate apps without a web interface, i.e. you should be able to run your app from iex directly (also great for testability), and then you can put a Phoenix-powered web interface on top of this, where the controllers simply call the appropriate business logic functions.

dsignr

dsignr OP

Thank you for your excellent, detailed reply Matt. Much appreciated. That was a very thorough detailed reply.

My concerns regarding separation were mostly around the routes. How do you organize the routes?

For example, if Auth module is taking care of the authentication and authorization, surely it needs to be a part of every route within every other module right?
So, cms’s route file should make a reference to this auth for every request, if I’m not wrong. My logic says it’s wise to go with a shared kernel (DDD), using a pipeline for auth that every route from every other domain can use, but I honestly don’t know how to go about it. (If you’ve got some sample code, it would be great too!)

Would love to hear your thoughts.

Thank you.

mjadczak

mjadczak

I think you’re still thinking of your web interface and your actual app as the same thing. The Auth module doesn’t need to know anything about routes, or be “part” of any routes.

The Auth module is simply a piece of code you can ask whether a certain principal (e.g. user) can do a certain thing (e.g. buy a product).

Routes are only relevant in the web layer—each route will have some controller handling it, and that controller can ask the Auth module whether the current user is allowed to do the action they’re trying to, and if not, error out. If they are, the controller proceeds to call into the appropriate context module, e.g. CMS, to perform the desired action, and then renders out the results as JSON or HTML.

This means you decouple your web interface from what your app actually does—you should be able to use your app fully from the iex shell before your web layer is ready.

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
water
I’m aware of 2 such projects, are there others? git: GitHub - team-alembic/realworld: A fullstack Phoenix LiveView application with back...
New
itzmidinesh
Hi all, I’m working on a Phoenix project where I need to make external HTTP requests and I’m trying to choose between Req and HTTPoison....
New
peck
Hi everyone. My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
leoschweizer
Hi, we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New
csmr
Hi all, I’m new here and would like to hear peoples views on my Elixir/Phoenix based game-engine! :smiley: Mutonex gamedesign was finish...
New
Stef-Verniers
Hello I’ve been coding in Elixir for almost two years now because of my current job where we implemented Elixir in our application. But ...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
raa-ziq
Hi everyone :waving_hand: I wanted to share something I’ve been building — NowBlind, a random chat app designed to help people discover ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
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

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews