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
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
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
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!
Popular in Discussions
Other popular topics
Chat & Discussions>Discussions
Latest on Elixir Forum
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex











