Live data from Hacker News

Thinking in Actors – Challenging your software modelling to be simpler

jeremycarterau.substack.com

31–40 of 48 posts

Re: Thinking in Actors – Challenging your software modelling to be simpler

#31
post #18

Earlier quoted context omitted.

I don't see how this isn't still both possible and entirely relevant to modern systems. An actor is not necessarily a system process/thread. It has more to do with scope/context than any particular execution model. Think more like a request handling context in an async language.

It's true that an actor is not necessarily a system process. It can be a process, or a thread, or a coroutine, or etc. But "crashing" isn't anywhere near so ambiguous. Crashing doesn't mean the request fails, or the thread gets killed -- crashing means the underlying process terminates. That may not be how some folks understand the concept of crashing, but it's definitely how most folks understand it, at least insofa…

Any time you are communicating between multiple programming language communities, it is important to understand that they will have differing definitions for things, to extend grace to people trying to communicate across those barriers, and to not apply dogmatic definitions of terms that apply to the contexts you happen to be familiar with but are used differently elsewhere.

"Crash" is not a universally defined term and you will find there are plenty of communities that do not agree that "crash == OS process terminating".

Re: Thinking in Actors – Challenging your software modelling to be simpler

#32

> State can be persisted (e.g., to storage, database or event log) between messages. If an actor crashes, it can recover its state on another node and resume processing. And that's the part I never managed to solve, personally. The state of actors tend to look "a lot like" your domain objects, but you don't want to store it until the very end. Do you have a data-model for each actor to store their own snapshots ? Whe…

> When do you snapshot ?

In Durable PHP (an actor system for PHP), it tries to achieve at-most-once processing guarantee (though more often than not, it is exactly-once).

1. commit the current state

2. send outgoing messages

3. ack the original event

If we fail before 1, we simply retry

If we fail between 1-3, we simply rewind and retry

Re: Thinking in Actors – Challenging your software modelling to be simpler

#33
post #17
post #16

Earlier quoted context omitted.

Some actor frameworks (Erlang, Orleans) would interpret each order being an actor instance, and each order line being an actor instance. To make that clearer: each order row would _logically_ have an actor running somewhere in your cluster. This would mean that an order actor would, by nature, have a "add order line" receiver (i.e. method). Each is in charge of how its data is stored. In reality, you'd _probably_ onl…

What did you learn about (by using?) DDD that made you decide strongly against it?

DDD advocates for creating a shared lingo across everyone involved, including customers if they are highly embedded in the design process. This I agree with.

Ultimately DDD attempts to create real-world analogies in code; you know, dog inherits from pet inherits from mammal etc. In my opinion, this approach to OOP easily ends up creating code that is difficult to reason about. Probably because real-world things often have many responsibilities. Code becomes especially confusing when you have dozens of methods on domain objects that interact across several domains: the system-wide control flow becomes extremely complex. Now add outlier code/hacks, likely written to meet an unrealistic deadlines, and things rapidly become completely incomprehensible.

And there's more that's hard to put to words. I code for the love of it, and I truly hated every moment working in DDD code. That was I completely novel experience for me: I'm fine with boring work (it has to happen), but DDD just hit very differently.

Re: Thinking in Actors – Challenging your software modelling to be simpler

#34

I love actors as a concept and I heard some large companies (Expedia) implemented large parts using them. But I also saw how hard it is to understand a large system that built using actors. It is just hard to comprehend all the communication pathways and what happens in the system.

> It is just hard to comprehend all the communication pathways and what happens in the system.

Having worked on large scale actor-based systems before, I'll attest this is quite true. However, what often gets lost in these conversations is that this is also true of large scale OOP based systems as well.

If one takes a few steps back and squints, there's really not much difference between Objects and Actors: in both cases you have a namespaced entity (object, actor) that receives signals via some defined mechanism (methods, messages) which lead it to perform some action.

Re: Thinking in Actors – Challenging your software modelling to be simpler

#35
post #33
post #17

Earlier quoted context omitted.

What did you learn about (by using?) DDD that made you decide strongly against it?

DDD advocates for creating a shared lingo across everyone involved, including customers if they are highly embedded in the design process. This I agree with. Ultimately DDD attempts to create real-world analogies in code; you know, dog inherits from pet inherits from mammal etc. In my opinion, this approach to OOP easily ends up creating code that is difficult to reason about. Probably because real-world things often…

This sounds like DDD done wrong. Just because two concepts have the same name doesn't mean that they are the same thing. Drawing the boundaries of the bounded contexts is hard though, which is why shops often struggle with DDD.

For example if I'm building a pharmacy system a prescription means something to a patient, but also means something different (but similar) to a fulfillment team member. The prescription might have a prescriber, and its important for the patient to know the name, address and contact information of the prescriber. But for fullfulment purposes I don't care about the address or phone number, just the NPI, full name and title for labeling purposes. This doesn't just extend to data, but to actions, a patient can't "ship" a prescription and fullfulment can't "renew" a prescription. In a DDD model these should be two separate objects.

Re: Thinking in Actors – Challenging your software modelling to be simpler

#36

> State can be persisted (e.g., to storage, database or event log) between messages. If an actor crashes, it can recover its state on another node and resume processing. And that's the part I never managed to solve, personally. The state of actors tend to look "a lot like" your domain objects, but you don't want to store it until the very end. Do you have a data-model for each actor to store their own snapshots ? Whe…

This is what I’ve struggled with when trying to learn erlang/elixir/gleam: If I go all in, then modelling as actors makes sense. The domain model is modelled as in-memory actors, using erlang features for persistence and what not. But most of the time this isn’t what we want in modern software: instead our state is in a database and we are executing in a request-response setup. This seems to be mismatched with actors…

a few years back i had one side project that i did in elixir/phoenix felt like a good fit specifically because it had a lot of state that needed to live outside of the request/resp cycle but also didn't live in a db

Specifically the project was an app that ran terraform commands inside an actor and streamed the logs to the browser

each actor had a terraform config and each message was a command to run on that config

so in that case the actor model felt like it aligned really well with how the program needed to work

Re: Thinking in Actors – Challenging your software modelling to be simpler

#37
This is where erlang/elixir really shines! Using actor processes (aka genservers) to model business workflows and logic helps to align the programmer's and stakeholder's shared understanding and language of a feature, which leads to the implementation and expectations about it to be much more "correct".

Too many of us jump straight to modeling the domain objects as database tables without formalizing the the data model of the actual business need. Explicit state changes and considering "time" are way more important than database layout at that point.

And please either use operation explicit types and/or finite state machines when modeling the main domain objects.

My last three jobs started with untangling a bunch of "status" fields into explicit and hierarchical structures so that the whole company could agree and define what each of them actually meant. Common language, yo! It's the secret sauce!

Re: Thinking in Actors – Challenging your software modelling to be simpler

#38

I love actors as a concept and I heard some large companies (Expedia) implemented large parts using them. But I also saw how hard it is to understand a large system that built using actors. It is just hard to comprehend all the communication pathways and what happens in the system.

> But I also saw how hard it is to understand a large system that built using actors.

Indeed, it can be just as much of a spaghetti mess as any other code, but it becomes easier if actors are the preferred abstraction for a platform already, for instance as it is for Erlang/Elixir on the BEAM VM.

The platform comes with a few benefits such as:

  1) Immutable data: inside each actor the state is explicitly evolved from one message to the next. It's passed as an explicit argument to functions. Erlang is even better as the variable binding itself is immutable.

  2) Isolated heaps: actors all have isolated heaps. You can have millions of them per OS process and they can't reach in and modify each other's memory. They have to send and receive a message.

  3) Supervision trees: actors that work together can be grouped into a tree hierarchy so that if one starts, it start the others and they have "links" between them. If some crash, others crash with them. After the crash they can be restarted safely. It can be done safely because they have isolated heaps. Restarting a bunch of OS threads in a regular C/Java/etc program cannot be done safely, usually. These supervision hierarchies is how the system can be organized. A top level actor might serve as the API endpoint for its children so message go through it.

  4) Tracing/live debugging: every message that is sent or function call can be traced dynamically by connecting to a live system. That can be helpful of making sense of the mess when debugging.
There are many "actor" systems out there. It's not a big deal to write a function to send a message to a lockless "mailbox" to be received by a thread in pretty much any modern language/platform. Doing that seems like it gets you 90% there to "actors", but without those 4 points above it only gets there 10% of the way. You can build a quick demo, but it would become a nightmare in a production system.

Re: Thinking in Actors – Challenging your software modelling to be simpler

#39
post #20

Earlier quoted context omitted.

Why F# there?

I was thinking of Mailbox Processor and available Actor libraries. Here's a pretty good rundown I found for some[0]: > Actor Model in .NET > In the .NET world, there are at least a few battle-tested frameworks that allow you to build stateful systems using the actor model. The famous ones are Akka.NET[1], Orleans[2], Proto.Actor[3], and Dapr[4]. All of these systems support distributed mode, as well as a bunch of oth…

Clarification: Dapr's actor system is not limited to .NET[0]

It currently supports .NET, Java, and Python

[0] https://docs.dapr.io/developing-applications/building-blocks...

Re: Thinking in Actors – Challenging your software modelling to be simpler

#40
post #31
post #18

Earlier quoted context omitted.

It's true that an actor is not necessarily a system process. It can be a process, or a thread, or a coroutine, or etc. But "crashing" isn't anywhere near so ambiguous. Crashing doesn't mean the request fails, or the thread gets killed -- crashing means the underlying process terminates. That may not be how some folks understand the concept of crashing, but it's definitely how most folks understand it, at least insofa…

Any time you are communicating between multiple programming language communities, it is important to understand that they will have differing definitions for things, to extend grace to people trying to communicate across those barriers, and to not apply dogmatic definitions of terms that apply to the contexts you happen to be familiar with but are used differently elsewhere. "Crash" is not a universally defined term…

For sure, yes. But terms of art, like "crash", generally have commonly-understood definitions. And the commonly-understood definition of the term of art "crash" is that it means OS process terminating. Not always! Not all the time. But in general, yes, that's what it means, to most people, most of the time.
Post reply on HN