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

belgoros
Following the steps described in Chapter 6 of the book, I’m stuck with running the migration as described on page 84: bundle exec sequel...
New
johnp
Hi Brian, Looks like the api for tinydb has changed a little. Noticed while working on chapter 7 that the .purge() call to the db throws...
New
edruder
I thought that there might be interest in using the book with Rails 6.1 and Ruby 2.7.2. I’ll note what I needed to do differently here. ...
New
herminiotorres
Hi @Margaret , On page VII the book tells us the example and snippets will be all using Elixir version 1.11 But on page 3 almost the en...
New
Mmm
Hi, build fails on: bracket-lib = “~0.8.1” when running on Mac Mini M1 Rust version 1.5.0: Compiling winit v0.22.2 error[E0308]: mi...
New
Chrichton
Dear Sophie. I tried to do the “Authorization” exercise and have two questions: When trying to plug in an email-service, I found the ...
New
leonW
I ran this command after installing the sample application: $ cards add do something --owner Brian And got a file not found error: Fil...
New
jskubick
I think I might have found a problem involving SwitchCompat, thumbTint, and trackTint. As entered, the SwitchCompat changes color to hol...
New
akraut
The markup used to display the uploaded image results in a Phoenix.LiveView.HTMLTokenizer.ParseError error. lib/pento_web/live/product_l...
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

Other popular topics Top

AstonJ
A thread that every forum needs! Simply post a link to a track on YouTube (or SoundCloud or Vimeo amongst others!) on a separate line an...
New
PragmaticBookshelf
Design and develop sophisticated 2D games that are as much fun to make as they are to play. From particle effects and pathfinding to soci...
New
AstonJ
SpaceVim seems to be gaining in features and popularity and I just wondered how it compares with SpaceMacs in 2020 - anyone have any thou...
New
AstonJ
There’s a whole world of custom keycaps out there that I didn’t know existed! Check out all of our Keycaps threads here: https://forum....
New
New
AstonJ
Just done a fresh install of macOS Big Sur and on installing Erlang I am getting: asdf install erlang 23.1.2 Configure failed. checking ...
New
mafinar
This is going to be a long an frequently posted thread. While talking to a friend of mine who has taken data structure and algorithm cou...
New
PragmaticBookshelf
Author Spotlight Mike Riley @mriley This month, we turn the spotlight on Mike Riley, author of Portable Python Projects. Mike’s book ...
New
New
First poster: bot
zig/http.zig at 7cf2cbb33ef34c1d211135f56d30fe23b6cacd42 · ziglang/zig. General-purpose programming language and toolchain for maintaini...
New

Sub Categories: