markhildreth

markhildreth

Domain Modeling Made Functional questions

@swlaschin

Written in the persistence chapter under the section “Writing to a relational database”, that “we convert our domain object to a DTO and then execute an insert or update command.” I have a few questions on this.

1.) This doesn’t really seem to handle deletes. How would you recommend handle a command which deletes the root aggregate (and presumably all of its “children”)? Would the DTO just end up being a “null” which the persistence mechanism takes to mean “delete it all”?

2.) More troublesome, how would the aggregate root not be deleted but a child be deleted (e.g., removing an order line from an order).

Would we need to “mark” the line as deleted in our aggregate in order to know during persistence that it should be deleted? That seems like it would complicate the model for reasons of persistence.

Or perhaps our persistence logic deletes all order lines in the DB with IDs that are not in the order line DTO array?

Or maybe we retrieve the current state of the database as a DTO, do a diff with the DTO created as a result of our command

3.) In both of these questions (and specifically the second), there is the problem of concurrent transactions affecting the same aggregate. Are we essentially forced to use serializable transactions or record locking if we want to ensure that two transactions are not stepping on each others toes? Or is there another strategy here (besides strategies like event sourcing).

Thanks

First Post!

swlaschin

swlaschin

Author of Domain Modeling Made Functional

Thanks for the questions!

  1. Deletes generally just need an entity id, not a DTO. For a compound object like an Order, if the database supports it, I would set up a cascade delete. Otherwise you could query for the subobjects and explicitly delete them. In both cases I would hide all this logic inside the infrastructure component (API call wrapper) rather than exposing it to the domain logic.

  2. Removing a line from an Order would be treated as an Update from the domain’s point of view. It depends whether you want to expose the logic to the domain layer. If you want to hide it, I would pass in the modified DTO without the line and then, inside the infrastructure component (the API call wrapper), figure out which lines are missing (delete), which lines are added (insert), and which lines are changed (update). This approach means that ANY updates to the aggregate root (additions, subtractions, etc) are handled the same way, using the same infrastructure method. More complicated, but it keeps the domain logic simple.

  3. The problem of concurrent changes to the same aggregate is not specific to any particular design method and there are standard approaches you can use. If you have independent processes updating the database, you can use pessimistic concurrency (locks, transactions) or optimistic concurrency (versioning, timestamps). If everything is handled by one server (e.g. when doing microservices), then you can represent each aggregate root with an agent, and changes to the object are queued up and serialized that way. Or, yes, you can use event sourcing :slight_smile:

Hope this helps!

Where Next?

Popular Pragmatic Bookshelf topics Top

raul
Page 28: It implements io.ReaderAt on the store type. Sorry if it’s a dumb question but was the io.ReaderAt supposed to be io.ReadAt? ...
New
cro
I am working on the “Your Turn” for chapter one and building out the restart button talked about on page 27. It recommends looking into ...
New
gilesdotcodes
In case this helps anyone, I’ve had issues setting up the rails source code. Here were the solutions: In Gemfile, change gem 'rails' t...
New
New
adamwoolhether
When trying to generate the protobuf .go file, I receive this error: Unknown flag: --go_opt libprotoc 3.12.3 MacOS 11.3.1 Googling ...
New
jgchristopher
“The ProductLive.Index template calls a helper function, live_component/3, that in turn calls on the modal component. ” Excerpt From: Br...
New
adamwoolhether
I’m not quite sure what’s going on here, but I’m unable to have to containers successfully complete the Readiness/Liveness checks. I’m im...
New
mert
AWDWR 7, page 152, page 153: Hello everyone, I’m a little bit lost on the hotwire part. I didn’t fully understand it. On page 152 @rub...
New
Henrai
Hi, I’m working on the Chapter 8 of the book. After I add add the point_offset, I’m still able to see acne: In the image above, I re...
New
dachristenson
I just bought this book to learn about Android development, and I’m already running into a major issue in Ch. 1, p. 20: “Update activity...
New

Other popular topics Top

brentjanderson
Bought the Moonlander mechanical keyboard. Cherry Brown MX switches. Arms and wrists have been hurting enough that it’s time I did someth...
New
AstonJ
You might be thinking we should just ask who’s not using VSCode :joy: however there are some new additions in the space that might give V...
New
AstonJ
I ended up cancelling my Moonlander order as I think it’s just going to be a bit too bulky for me. I think the Planck and the Preonic (o...
New
AstonJ
In case anyone else is wondering why Ruby 3 doesn’t show when you do asdf list-all ruby :man_facepalming: do this first: asdf plugin-upd...
New
rustkas
Intensively researching Erlang books and additional resources on it, I have found that the topic of using Regular Expressions is either c...
New
PragmaticBookshelf
Use WebRTC to build web applications that stream media and data in real time directly from one user to another, all in the browser. ...
New
AstonJ
We’ve talked about his book briefly here but it is quickly becoming obsolete - so he’s decided to create a series of 7 podcasts, the firs...
New
PragmaticBookshelf
Develop, deploy, and debug BEAM applications using BEAMOps: a new paradigm that focuses on scalability, fault tolerance, and owning each ...
New
PragmaticBookshelf
A concise guide to MySQL 9 database administration, covering fundamental concepts, techniques, and best practices. Neil Smyth MySQL...
New
xiji2646-netizen
Woke up to this today: Claude Code’s complete source code exposed via npm source map. Not a snippet. All 512,000 lines. 1,900 TypeScript ...
New

Sub Categories: