amacgregor

amacgregor

I had a couple of questions around contexts and best practices, or at the very least I’m trying to validate the my understanding of the subject is okay.

As I understand Contexts or Bounded contexts are nothing more than a code design practice that Phoenix 1.3 is introducing and laxly enforcing, the core concept makes sense and in principle it sounds like a good practice to set boundaries between the multiple components of an application.

What I’m finding is that the idea of contexts is fairly abstract and it only gets murkier when trying to put into practice, DDD in particular cares a lot (primarily) about the domain core and for someone that has no experience trying to define boundaries let alone optimal boundaries can be challenging, specially without experience.

Things can get even more challenging on situations where there might be overlap and the boundaries are not as clear or easily defined, for example a table or data needs to be accessed from multiple contexts (users would be a good example) I’ve seen a lot of mixed opinions on how to best tackle the problem.

As I see it right now Contexts just introduced a lot of confusion and uncertainty to developers, mostly because of the lack of experience and the introduction of particular way of designing/architecting code that most people will find strange.

The other thing that keeps jumping on the back of my mind is the idea of “Modelling by Example” introduced by Konstantin Kudryashov a while back ago in the php community, it tries to marry BDD+DDD and it does into what I think is a pretty elegant fashion, check it out here:

And the following talk on BDD:
https://skillsmatter.com/skillscasts/6240-taking-back-bdd

Sorry for the mini mental dump. Curious to hear what other people think.

Showing Posts 1 to 7

chrismccord

chrismccord

Creator of Phoenix

Yes, contexts are a design practice that the phx.gen.html|json|context use to help newcomers think about application design.

It is an abstract set of a practices and I agree this has tripped some people up. When it comes down to it, we can’t write the application for our users, and writing any nontrivial app to model a given domain can’t be distilled into “follow these steps and you’re done”. What we can do is nudge people into proper mindset when designing an application to set them up for long-term success. We can, and will in the upcoming guides, show suggestions on general practices to follow for common scenarios, but not everything can be distilled into a hard rule-set.

Our 1.3 guides will review some of these challenges and offer possible solutions, as well as what to think about when depending on data access across contexts. So stay tuned on that front.

Our guides will show common cross-context challenges and solutions specifically around your “users” point. You see mixed opinions in part because your data access layer at large is going to be dependent on your application and the tradeoffs you want to make. Sometimes a SQL join is exactly what you want. For example, generating complex aggregate reports across lots of tables in your database that happen to span many contexts. Efficiently trying to aggregate this data by some exposed API on your contexts would be very difficult or impossible to do efficiently. On the other hand, if you can easily avoid joining across the context then your system can grow with fewer dependency and maintenance burden. You’ll see different opinions based on different use-cases, but hopefully when our 1.3 guides drop we’ll iron out some common solutions for you to think about.

I think much of the confusion and uncertainty is because we haven’t yet provided the guides and shipped a 1.3 final so folks are going partially blind. One point I want to highlight here is the context generators were made exactly to address “the lack of experience of a particular way of designing code”. They are learning tools specifically to help folks build a mental model about designing their greater application.

I also want to re-iterate while I used the “bounded context” definition from Folwer in one of my talks, it was to show where we were taking some of these ideas from, but we aren’t asking folks to go find a 400 page DDD book and apply a particular pattern.

bdarla

bdarla

When shall we expect the 1.3. guides? It seems that the relatively long transition phase from 1.2 to 1.3 is holding back the development of new projects.

In any case, the community appreciates the excellent work of the core team!

net

net

1.3 has been a release candidate for so long everyone’s forgotten it’s a release candidate. (Not that the wait concerns me.)

OvermindDL1

OvermindDL1

Welcome to my hell if you have to do this. ^.^;
/me works with an ancient Oracle database that was apparently designed by intellect-less committee…
Avoid it if you can!
If you cannot though, look at Absinthe. I’ve been hiding the hell behind it’s GraphQL interface and I make GraphQL calls from in-server to in-server, it has become an excellent ‘Context’ in the system for data calls distributed across everything. ^.^

peerreynders

peerreynders

Actually there is a reason the OLTP vs OLAP dichotomy evolved. Your domain runs against a set of schemas on the online transactions processing systems side while your reporting, analysis, and intelligence runs on the online analysis processing side - typically reorganized in star schemas which are optimized towards the needs of data warehousing. So for reporting purposes data is duplicated from the OLTP system to the OLAP systems (Philip Greenspun: Data Warehousing for Cavemen (1997), Data Warehousing (2003)).

So it wouldn’t be too outlandish to suggest that for reporting purposes data should be “exported” to separate reporting schemas. In Phoenix when running multiple contexts against the same database one has the “luxury” of using a SQL join - but at the same time one has to be aware that one is engaging in an integration database.

When a context is promoted to a microservice this has to stop because an integration database violates service autonomy (a notion of “context autonomy” is probably appropriate as a context is all about cohesion). The typical solution to serve reporting needs is an Event Data Pump (Building Microservices p. 98) - while conducting it’s responsibilities each domain microservice emits events that are processed separately to be included in a reporting database - and that reporting database is used by the reporting service.

One interesting thing about contexts is that there are times where contexts legitimize violating DRY - but only when necessary in order to promote loose coupling because DRY can lead to tight coupling.

Development By Slogan with DRY (2015)

chrismccord

chrismccord

Creator of Phoenix

Right, there are certainly prior art to look at for a robust reporting system. The “tradeoffs” I mentioned revolve around these ideas you’ve shared. You can either 1) perform complex - but easy to write - SQL joins, or 2) re-architect your system with Event Data Pumps, et al. I agree this reporting use-case done “right”, would definitely not crunch on live data, rather exported or against a mirrored DB, but this is a separate conversation from contexts, where we’re talking about contexts as starting points. The vast majority of folks just want to crunch on and report against live data, without going down the rabbit hole of the mentioned material.

So our goal with contexts isn’t to solve the question of “when to use Event Data Pumps vs SQL joins”, but rather set folks up from the start with an external context API that allows them to grow their systems to these places without having to rewrite their entire application. So if they are set up from day one with SalesReports.list_daily_revenue(30), if we later grow this to crunch against an exported data store just for reporting, our callers don’t care. If folks are thinking about isolation and decoupling up front, they would be in a much better position to grow their system into the different data warehousing architectures you mentioned, should they require it.

peerreynders

peerreynders

I fully understand where you are coming from … but at the same time we have to acknowledge that from a beginner’s perspective setting up boundaries to isolate contexts while at the same time violating these boundaries with SQL joins creates a bit of cognitive dissonance.

The only way to remove that is to emphasize:

  • contexts serve only the domain
  • while reports/analysis/intelligence are legitimate user features they typically aren’t considered part of the core domain
  • therefore reports are a concern separate from the core domain (and the goals contained therein)
  • therefore SQL joins for reporting purposes aren’t viewed as violating any boundaries**
  • and ultimately those reporting SQL joins need to be considered a “shortcut” because that approach to reporting simply doesn’t scale. The perception of boundaries being violated is gone once reporting is moved to a separate database (not with a mirrored schema - but with a data warehousing schema).

**However there still is contention in the sense that whenever you change the context’s schema you also have to update your reporting query.

— All posts loaded —

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
caslu
I want to open this thread for you all to discuss and help those who really like Ash but are still hesitant to use it in a real project. ...
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
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
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
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
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