Ancestors

Toot

Written by ismasan on 2024-12-21 at 18:56

Rethinking the roles of commands and reactions in the Decide, Evolve, React pattern. Decide really is just about invariants and nothing else. React is the real brains of the system.

=> More informations about this toot | More toots from ismasan@ruby.social

Descendants

Written by ismasan on 2024-12-21 at 18:57

Which makes me think that both Decide and React are terrible names for what they actually do.

=> More informations about this toot | More toots from ismasan@ruby.social

Written by ismasan on 2024-12-21 at 19:08

React decides what state change to try next by running a command, and gathers any context needed to fulfill the command. Decide just makes sure the attempted state update doesn’t break any rules. Events are the state change.

React calls the shots.

=> More informations about this toot | More toots from ismasan@ruby.social

Written by thinkbeforecoding on 2024-12-21 at 19:30

@ismasan we need to take some time to discuss this, as I am the one who diceded to call it Decide 😋

=> More informations about this toot | More toots from thinkb4coding@mastodon.social

Written by thinkbeforecoding on 2024-12-21 at 19:32

@ismasan I can explain cleary why I chose this terminology

=> More informations about this toot | More toots from thinkb4coding@mastodon.social

Written by ismasan on 2024-12-21 at 20:00

@thinkb4coding oh please do! Sorry I didn’t mean to overstep, just thinking out loud. I don’t mean that we should change the names of your pattern, I mean that I should perhaps change the names in my implementation since it’s deviating from your pattern into something else.

=> More informations about this toot | More toots from ismasan@ruby.social

Written by thinkbeforecoding on 2024-12-21 at 20:19

@ismasan I didn't have time to read your post yet, but seing the schema I think O see where it's going

There are some things I did not publish yet on the subject that you could find interesting.

And it involves a react function but not exactly at the same place.

=> More informations about this toot | More toots from thinkb4coding@mastodon.social

Written by ismasan on 2024-12-21 at 20:23

@thinkb4coding I would absolutely love to hear that! Yeah also my current thinking is drifting away from the blog post I wrote, as I work on implementation and examples.

=> More informations about this toot | More toots from ismasan@ruby.social

Written by thinkbeforecoding on 2024-12-21 at 21:56

@ismasan i've been discussing the patterns of event modeling a lot with @adymitruk and I have something that fits really well with the decider pattern

=> More informations about this toot | More toots from thinkb4coding@mastodon.social

Written by ismasan on 2024-12-21 at 21:59

@thinkb4coding @adymitruk yeah react is for processors / automations, presumably. Looking forward to learning about your take on it.

=> More informations about this toot | More toots from ismasan@ruby.social

Written by Paweł Świątkowski on 2024-12-22 at 19:44

@ismasan I understand that when decisions are binary (either do something or don't do it because of an error X). But as soon as the decider starts to potentially return multiple events, I think perspective changes (at least mine).

=> More informations about this toot | More toots from katafrakt@ruby.social

Written by ismasan on 2024-12-22 at 20:06

@katafrakt can you elaborate? I wanted to record my current thinking but I don’t think I’ve reached clarity yet.

=> More informations about this toot | More toots from ismasan@ruby.social

Written by ismasan on 2024-12-22 at 20:09

@katafrakt but yeah you’re right. Deciders can also express behaviour via events that goes beyond guarding invariants… I guess depending on how you think about invariants 🤔

=> More informations about this toot | More toots from ismasan@ruby.social

Written by Paweł Świątkowski on 2024-12-22 at 20:18

@ismasan that's more or less what I meant. When you are just guarding invariants, your decision is only a success/failure. However it might be different in some domains.

For example, when you have Loans, in response to "register payment" you might decide just "payment registered" but also additionally "loan paid back" if it's the last installment. This is beyond invariants and IMO is the heart of a domain.

=> More informations about this toot | More toots from katafrakt@ruby.social

Written by Paweł Świątkowski on 2024-12-22 at 20:20

@ismasan another example could be the meetup clone example I shared. When the user "cancels RSVP" you can just remove them from the attendance list, but maybe also bring in someone from the waitlist or mark the event as not full anymore.

=> More informations about this toot | More toots from katafrakt@ruby.social

Written by ismasan on 2024-12-22 at 20:26

@katafrakt yes that’s an interesting example because there’s an argument that the command handler shouldn’t do that extra work, and that a processor should instead look at the state of things after the fact and decide to dispatch a new command to signup someone from the wait list.

=> More informations about this toot | More toots from ismasan@ruby.social

Written by ismasan on 2024-12-22 at 20:28

@katafrakt I’m not necessarily sold on this btw, just reflecting how it’s argued elsewhere. For example in Event Modeling command handlers that emit more than one event are not forbidden; but sort of seen as a design red flag.

=> More informations about this toot | More toots from ismasan@ruby.social

Written by Paweł Świątkowski on 2024-12-22 at 20:34

@ismasan I see. In that case I think one is indeed reducing decider to be a guardian of the invariants (and a boring thing).

Returning multiple events was the main thing that drew me to the decider pattern. I think it's quite clear in Jeremie's blog post that it's "legal". I won't easily give that up, even if I would be doing something "impure" ;)

=> More informations about this toot | More toots from katafrakt@ruby.social

Written by ismasan on 2024-12-22 at 20:45

@katafrakt so do you run side effects in Decide, then? I think in Jeremie ‘s original post Decide functions are supposed to be pure, too (but I could be wrong)

=> More informations about this toot | More toots from ismasan@ruby.social

Written by Paweł Świątkowski on 2024-12-22 at 21:03

@ismasan definitely no side effects in the decider for me. I introduced a side effects runner and called it reactor, which takes a list of events and reacts to them one by one. But I should probably change the name, because it triggers some people - as a reactor in f model, for example, is something different.

I'm mostly only after separating logical decision from infrastructural execution. I think I should write a blog post about that motivation.

=> More informations about this toot | More toots from katafrakt@ruby.social

Written by ismasan on 2024-12-22 at 21:57

@katafrakt how do you track those side effects though. Presumably the reactor (I call them reactors too) runs the side-effect and then dispatches a new command with the results? And if the side effect can result in different scenarios, then the reactor can decide what command to send next. I think that level of decision-making in the reactor is what collided (in my mind) with the decision-making in Deciders.

=> More informations about this toot | More toots from ismasan@ruby.social

Written by Paweł Świątkowski on 2024-12-22 at 22:16

@ismasan do I need to track them? So far it's making a DB insert/update or scheduling a background job. If I run it in a transaction it either all fails or all succeeds. The reactor does not send any commands itself.

I get this might be naive, but so far in my experimentation I did not need anything more.

=> More informations about this toot | More toots from katafrakt@ruby.social

Written by ismasan on 2024-12-22 at 22:19

@katafrakt but for example if the side effect is to make a payment using Stripe’s API. If the payment succeeds, you continue with the happy path of the workflow. If it fails (say because of lack of funds), you do something else.

=> More informations about this toot | More toots from ismasan@ruby.social

Written by Paweł Świątkowski on 2024-12-22 at 22:24

@ismasan this would happen inside a background job (scheduled by a reactor). And the job calls the thingy that coordinates decider with reactor (Phoenix context in my case, but might be any other orchestrating layer), just as a web request from the user would do.

=> More informations about this toot | More toots from katafrakt@ruby.social

Written by ismasan on 2024-12-22 at 22:41

@katafrakt right ok but conceptually it’s the reactor scheduling the side effect and the next command. The bg job is just the scheduling mechanism

=> More informations about this toot | More toots from ismasan@ruby.social

Written by Paweł Świątkowski on 2024-12-23 at 07:41

@ismasan I would say it's Stripe gateway issuing a command, just like the user is issuing a command by filling out a form and hitting "submit". However I am starting to see some gaps in this concept. I think I will have to re-examine it.

I guess I'm reluctant to reactor producing commands because they will be very infra-oriented, like "send email", "update database record". These are very different from domain-oriented commands.

=> More informations about this toot | More toots from katafrakt@ruby.social

Written by thinkbeforecoding on 2024-12-22 at 21:11

@ismasan @katafrakt yes decide is pure (there can be some exception though)

=> More informations about this toot | More toots from thinkb4coding@mastodon.social

Proxy Information
Original URL
gemini://mastogem.picasoft.net/thread/113692338244899638
Status Code
Success (20)
Meta
text/gemini
Capsule Response Time
493.391536 milliseconds
Gemini-to-HTML Time
9.238322 milliseconds

This content has been proxied by September (3851b).