| Actually, shouting in the office means you coupled the FraudCheckActor to a PaymentCompleteEvent, and you coupled CancelOrderActor to FraudDetectedEvent. Your lower level actors are still coupled with each other, through quite specific events, and on top of that, dependent on a subscriber setup. Instead of declaring your own protocol and accepting messages in that protocol, now you need to understand everyone else's protocol (in the form of their event types) and react to it if you're subscribed to it. It's the worst of both worlds. Now, sure, you're right. Actors aren't like people in an office. Actors can't complain when you entangle them in a hot mess, they just carry on with whatever they're told to do. But the more experience I gain, the more I see the systems of the "real world" are in fact exactly like the systems of the "computer world". If something makes no sense in an organization made of people, then almost inevitably it'll make developers cry when having to figure out the sequence of events when implementing the same organization as a set of actors. Take it as a useful heuristic and humor my analogies. You might find a nugget of gold there. Also, there's nothing blasphemous if my supervisor can be implemented as synchronous imperative code. When people hear about a new paradigm, they believe they have to abandon everything and do things differently for no reason. No. Find some balance, what you knew still works, don't throw it out, just add the new benefits Actor offers to you. I.e. while Actors mean we can have objects that do things that you can't do in imperative/synchronous fashion, this doesn't mean we should never use actors for something that might be done in imperative/synchronous fashion. 90% of the interactions between actors still look like a request/response pattern. But those 10% when things don't look like a request/response really matter when you need that ability. Also keep in mind Actors don't care how far its subordinates are. In synchronous programming things have to happen fast, or the thread blocks. With actors a request may be sent this week, and you may get an answer next month. Things can happen very fast, or very slow, the model is not biased. How fast is fast enough is now entirely up to your app's domain logic. Also, some Actors implement persistence (which is far more trivial than trying to persist the callback graph or call stack in "normal" code), so they don't even care if the system shuts down and it has to start over from its last state. Imagine OrderActor sends a call to FraudCheckActor and then the system crashes, or (if it's a business workflow process) it's just powered down for the night. When the system is restarted, OrderActor is already waiting for that answer from FraudCheckActor. Do that with imperative/synchronous code. |
Moreover, modeling with events offers me a lot of flexibility in how I translate the real world domain into code.
I think I agree that if you're going to use actors, what you're saying makes more sense, but I honestly don't have enough production experience with that model to say yay or nay. But with the exception of event storage (which addresses your issue of figuring out what happened in what sequence) and terminology aside, the OP is proposing something which is isomorphic to CQRS, and that I have plenty of experience with, and it works just fine.