laiboonh

laiboonh

Software architecture (Domain Modelling)

Hi all,
First to set the stage. Say we have an app that represents a Shop that sells Books amongst other things. Books have differential pricing. So we have chosen to design DB schema as two tables. Books and BookValues with 1 to many relationship. With Ecto we will get a schema struct which is something like

%Book{
  id: UUID
  prices: [%BookValue{price: 10.0}, %BookValue{price: 12.30}]
}

One way to expose this to client side browser is to simply use this struct as the underlying and generate JSON which will look like this

{
  id: "...",
  prices: [{price: 10.0}, {price: 12.30}]
}

But I feel this should not be the case. I feel we should have proper modelling and segregation of concerns.

So we should have a domain struct that models actual real life books and the JSON payload would make more sense to me (personally)

[
{id: "...", price: 10.0}, 
{id: "...", price: 12.30}
]

Argument AGAINST this is

  • JSON payload would be heavier
  • Feels like there will be a lot of needless conversion between schema struct and domain struct

Argument FOR this is

  • We decoupled concerns cleanly (presentation, biz logic, storage)

Are there any other points to support FOR/AGAINST this?

Most Liked

al2o3cr

al2o3cr

The ... here seem to be hiding something important: do both of the objects in this format have the same ID? That would make handling them as two separate “things” much more complicated.


A technique I’ve found useful for thinking through these problems is to focus on the desired operations and produce a data structure that makes those easy to write.

For this case, what happens when a user wants to buy a particular Book? Do they pick a price as well, or does the site match them somehow (by lowest price available, etc)?

If the site matches them automatically, specifying the ID for Book would be enough.

If they pick a price (think a marketplace like Discogs that shows condition, etc) then perhaps BookValue’s ID should be surfaced.

trisolaran

trisolaran

two short unrequested comments that don’t answer your question but may help.

As mentioned by @sodapopcan, never use floats for money. Binary floating point is an imprecise representation of decimal numbers, and you want your money amounts to be correct to the last cent. Always use arbitrary precision libraries like Decimal.

Keep the names in your code simple and close to the actual model: don’t name it BookValue, use BookPrice instead.

sodapopcan

sodapopcan

This is one of those big ol’ “it depends” questions (emphasis on “big ol’” since technically the answer to any question is “it depends”).

While I feel you’d just like me to take your example at face value, I think in this case more details are required. I see a book has multiple prices, but what are these prices based on? Are they categorical (like good, fair, poor)? Does two or more books having the same price have any other meaning other than they just cost the same?

I am generally not concerned about heavier JSON payloads but the above questions still stands. If prices are simply just a number, I wouldn’t even bother modelling them—just return prices: [10.0, 12.30] as a list of primitives. If prices have more to them than that I think you have to answer the question: “Do books without prices make sense?” If not, always return a list of prices; if so, don’t.

Also, I’m realizing I’m assuming you’re talking about a REST API here? I’m not actually sure. I’m so entrenched in LiveView at this point that I don’t really think about JSON payloads anymore and have been reframing your question a bit in terms of schema vs embedded_scehma, but your question stuck a chord so I thought I’d try and help!

Where Next?

Popular in Discussions Top

scouten
I’m looking for a host for the server part of a small (personal) side project that I’m working on. It’s currently written in Node.js and ...
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31707 143
New
ben-pr-p
In general I’ve been sticking to this community style guide GitHub - christopheradams/elixir_style_guide: A community driven style guide ...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 40082 209
New
marciol
Please, let me know if this kind of discussion already took place in another topic . Hi all, how do you consider if is better to build ...
New
pillaiindu
I want to convert a Phoenix LiveView CRUD website to a CRUD mobile app. What do you think is the easiest way to do so?
New
Rustixir
Hi everyone, im working on find best language/framework/system for high concurrency, high performance and stable performance after wor...
New

Other popular topics Top

electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31525 112
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

We're in Beta

About us Mission Statement