How to determine contexts with Phoenix 1.3

phoenix
contexts

#1

I am just trying to migrate my project to Phoenix 1.3 with new contexts mechanism. But I am not sure how I should split my schemas into this contexts. I read a lot about DDD and UL/Bounded Contexts in last few days, but all examples using something like large ERP systems. Also in DDD contexts used to “namespace” UL (ubiquitous language) within this contexts like Sales/Support/Analytics, etc. where Product will be used.

At other side @chrismccord used blog (post, comments) example in his ElixirConf talk. So it looks more like module organization (maybe like Django re-usable apps) and not business model separation to scope UL within this context. So how to know when bounded context should be used?

Whats if I have pretty simple project where I have no overlaps in UL? How to scale DDD down in this case? Maybe just use single context?

Should I think about contexts as module organization - Blog, Accounts, etc. or it is really DDD contexts like Sales/Support? I am confused when they are used together (at single ElixirConf talk by @chrismccord).


Phoenix Contexts - learning resources
Contexts - a barrier too high for newbies?
How to order_by in phoenix 1.3
#2

Just found @anders answer:

but I still can’t get used with this Blog example. For me it looks like some re-usable code (maybe umbrella later) and not real Bounded Context in terms of DDD :frowning:


#3

I know this might not help you much, but just try to work on your app instead of trying to hard to fit your context structure in some kind of predefined schema. In the end it’s your app; you decide what’s worth splitting up and what’s not. Also elixir makes it quite easy to move things around even at a later time.

For example in one application it might be best to leave those 2-3 functions related to registaration with the other user handling (auth, …), while in another one registering might be a quite complex task with multiple steps involved. In that case the registration is probably better moved in a own context separate from other user related tasks. When exactly it’s time to move things in different context is a decision you’ve to make on your own and as stated is mostly dependent on the very app you’re working on.


#4

Sincerely, since bounded context was introduced in version 1.3, it has been very difficult working on something. It has however exposed me to a new way of thinking. It will be better if @chrismccord and his team furnishes us with samples like they do in aspnet core. This will help us to have good understanding of this approach. I love phoenix but I couldn’t use the version 1.3 on a new project that I am working on because I was confused. I went for dotnet core even though my heart is in love with phoenix.


#5

One important thing - this is not bounded context. The primary aim is to encourage building modular code. If you use DDD and bounded contexts for this - it’s your choice. But it’s just modules & functions until you yourself decide it’s something more in your application.


#6

@michalmuskala This is quite interesting. I voted for no context as proposed by Jose. However as a work around, I am thinking of using the project name as my default context as we would do in entity framework, eg LibrilleDbContext. This will hold all the tables that will be created. If need be for new context, I could then restructure it. However, this does not eliminate the need for samples. This will help ELIXIR and PHOENIX adoption.

I wish I am really good like you in Elixir. You are always there to talk to me whether at slack or here. Thanks


#7

It’s the same with me. It feels more difficult working with Phx 1.3 compared to 1.2. However, I believe that’s because I’m too used to the Rails way…


#8

It’s really interesting how different experiences can be. I’m not coming from rails, but the php world and I’ve had the best time rewriting a website in phoenix 1.3. First I played a bit with the context generators, but I found them to generate to much stuff (whole crud for each struct/schema), so I moved to creating my own contexts. It’s now super obvious where stuff is done as each context handles a single concern of the website. The whole web layer is only there to trigger stuff deeper in the application and to translate the returned values into markup / flash messages / …. I can use the whole app via iex without ever touching a single conn struct, nor any Repo.something() calls. Sure there was some time needed to get worm with that new approach, but I didn’t find that more difficult than trying to use phoenix 1.2 for the first time.


#9

@LostKobrakai it’s good to know you find it very intuitive to work with. If you mind, can you share what you have? Perhaps the github repository if it is not private.


#10

I can’t share the code, but it’s a website where people can register for a local event and I used the following contexts: auth, email, faq, newsletter, pdf, registration, ticketing and support. These where simply the things needed for the website and which felt to be distinct enough pieces of the whole. That’s why I think nobody can really tell anyone else what contexts they should use.


#11

Thank you, thats what confused me. So contexts in terms of Phoenix means just module scoping and not real DDD? Just for @chrismccord answer at forums it looks like real DDD bounded contexts:

And when examples for different usages (module organization, DDD contexts to scope UL) appears here - I get confused


#12

Also @josevalim said it’s a bad idea to maintain relations between contexts and something like field :user_id, :integer should be used instead of belongs_to :user, MyApp.Accounts.User.

So this is a bad idea because of violation of bounded context borders (which means it’s DDD really) or because this is a module organization and may want to split this module to umbrella later (like re-usable Django apps) or both?


#13

You can use contexts to fullfil the DDD principles, but you don’t need to - it all depends on how you’re going to use them in your application. If you deem it appropriate to adhere to DDD - go ahead. If you don’t, all you have to do is make explicit functions for all the operations that are allowed in your app, instead of sprinkling Repo and other services access over controllers.

That’s something @chrismccord also says in his keynote - contexts are inspired by DDD, but are not inherently tied to it.


#14

Thank you! I will watch this keynote one more time (there is no subtitles and hard to understand sometimes). I just bought Eric Evans BBB already. So I will split to modules (like normal Elixir w/o DDD) and maybe refactor later (after reading).


#15

The more I read about contexts the more I think it’s a bad idea.There seems to be a big push for “Phoenix is not your application” which, as far as I can tell, is nonsense. It’s a very big anti-rails movement.

Phoenix is your application. It’s a framework that serves as the foundation which you build on top of.

Ecto, Plug e.t.c. are libraries which are not your application. You use them as libraries and as such they don’t impose any structure. You’re free to do use them as you please.

A relevant quote from dhh.

It doesn’t help that the two main people behind Phoenix and these changes propose this complex new structure and both reply with the same “oh no we can’t give examples because it all depends on what you’re building.” I don’t mean to sound too critical but this screams change for the sake of changing.

What we have now is a situation where we have multiple isolated contexts in the same app but are discouraged from actually using them as a whole. e.g. we shouldn’t have relationships to other contexts in schemas. This is pretty backwards because if you have these in the same app you are certainly going to want to use everything together.

I personally don’t think that contexts is the right solution. I also don’t think we actually had a problem in the first place. If you really need separate isolated contexts then they don’t even belong in the same app.

Contexts as they are now are a bastardization of DDD and the repository pattern.

Umbrella apps are where the attention should have been focused. Fully separate apps where necessary and a web app that ties them all together.

If I am wrong then please tell me. I realize that I sound very negative but I assure you that I’m very open to ideas.


#16

Contexts are literally well named modules and functions, and we ask you to think about the API boundaries are you are building your well-named modules an functions. That’s it. If you think that’s a bad idea, then you are saying the way we all build functional programs is a bad idea :slight_smile:

When you build a phoenix project, it literally is an “OTP application”. This conflation w/ the above tweet ignores a lot of details about the elixir and ruby worlds. In Rails, your project is a special directory structure tailored to a Rails application. The entire program is started and stopped according to special rails init code. Contrast that with the way we build Elixir applications, they are all OTP applications, with standard start/stop mechanisms and explicit application relationships. “Phoenix is not your application” absolutely applies here and pushes folks to think differently about Elixir as a platform, since it’s unlike what they’ve been exposed to before.

Baby-steps! :slight_smile: This is exactly what mix phx.new my_app --umbrella does. [quote=“martinm, post:15, topic:4367”]
If I am wrong then please tell me. I realize that I sound very negative but I assure you that I’m very open to ideas.
[/quote]

You are wrong :stuck_out_tongue: . Thanks for the feedback!


#17

@ssbb You are tying 1.3 to DDD literature too strictly. You are right that contexts really are about module organization, asking folks to think about isolating their features behind well named modules and functions

Both. First and foremost, we are asking folks to isolate functionality behind modules and functions, but we can then point at DDD and say look, if you have multiple representations of a “user” in the system, we can apply these ideas from DDD to avoid giant entities in the system with implicit coupling everywhere.


#18

This is good! Thinking is harder than not thinking, so some effort is expected :smiley:

It’s important to note, that the generators are learning tools only. Saying you couldn’t use version 1.3 on a project doesn’t make sense because phoenix is not stopping you from writing any kind of code you want.

This could be helpful, but it’s tricky because 1.3 is asking you to actually think about designing your system, and the Phoenix team could try to dream up real’ish apps, but ultimately we can’t design everyone’s application for them. Some larger examples for the community could be helpful, but it’s not something the Phoenix-core team itself should focus on.


#19

Phoenix is not the foundation to the application. It’s the foundation of the web layer, which is part of your application. E.g. the website I talked about above. All it’s functionality is accessable through the actual website powered by phoenix, but also via iex bypassing everything phoenix is doing. It’s an elixir app, which includes phoenix to make serving web requests easy. And it’s not like phoenix would offer anything more I couldn’t use because of that.


#20

Just to buttress your point, I saw three days ago, a demo of elixir, cowboy and react. It feels so sweet how powerful elixir is. I love it. The app is so fast.

We can actually use a different layer to the web without using phoenix.

However, phoenix is an application inside series of applications going by the concept of OTP.

Phoenix is not your application but one of the applications.

It is fun to think of