Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the actor model not an anti-pattern, as the fire-and-forget style forces actors to remember a state?

When learning Scala, one of the first things I learned was that every function returns something. There is no "void"-function/method as there is, for instance in Java. Thus many Scala-functions are true functions, in a mathematic way, and objects can remain largely stateless.

Now I learned that the actor model is a very popular model among functional languages like Scala. However, actors promote a fire-and-forget style of programming, and callers usually don't expect callees to directly reply to messages (except when using the "ask"/"?"-method). Therefore, actors need to remember some sort of state.

Am I right assuming that the actor model is more like a trade-off between scalability and maintainability (due to its statefulness), and could sometimes even be considered an anti-pattern?

like image 599
Felix Gehring Avatar asked Oct 19 '16 08:10

Felix Gehring


People also ask

What is actor model used for?

The actor model can be used as a framework for modeling, understanding, and reasoning about a wide range of concurrent systems. For example: Electronic mail (email) can be modeled as an actor system. Accounts are modeled as actors and email addresses as actor addresses.

What is actor model in context of a programming language?

The Actor model adopts the philosophy that everything is an actor. This is similar to the everything is an object philosophy used by some object-oriented programming languages, but differs in that object-oriented software is typically executed sequentially, while the Actor model is inherently concurrent.

Which of the following implements the actor model?

Carl Hewitt took the idea and created the actor model. Years later, these same ideas of message passing would influence Erlang to create an implementation of the actor model as well. Erlang is often quoted as the first & most successful implementation of the actor model.

Do actors share memory?

The main difference is that actors are completely isolated from each other and they will never share memory. It's also worth noting that an actor can maintain a private state that can never be changed directly by another actor.


2 Answers

Yes you're essentially right (I'm not quite sure what you have in mind when you say scalability vs maintainability).

Actors are popular in Scala because of Akka (which presumably is in turn popular because of the support it gets from Lightbend). It is, not however, the case that actors are overwhelmingly popular in general in the functional programming world (although implementations exist for all the languages I'm thinking of). Below are my vastly simplified impressions (so take them with the requisite amount of salt) of two other FP language communities, both of which use actors (far?) less frequently than Scala does.

  • The Haskell community tends to use either STM/channels (often in an STM context). Straight up MVars also get used surprisingly often.
  • The Clojure community sometimes touts its own built-in version of STM, but its flagship concurrency model is really core.async, which is at its heart again channels.

As an aside STM, channels, and actors can all be layered upon one another; its sort of weird to compare them as if they were mutually exclusive approaches. In practice though it's rare to see them all used in tandem.

Actors do indeed involve state (and in the case of Akka skirt type safety) and as a result are very expressive and can pretty much do anything concurrency-wise. In this way they're similar to side-effectful functions, which are more expressive than pure functions. Indeed actors in a way are the pure essence of OO, with all its pros and cons.

As such there is a sizable chunk of the Scala community that would say yes, if most of the time when you face concurrency issues, you're using actors, that's probably an anti-pattern.

  • If you can, try to get away with just using Futures or scalaz.concurrent.Tasks. In return for less expressiveness you get more composability.
  • If your problem naturally lends itself to a single, global state (e.g. in the form of global invariants that you want to enforce), think about STM. In the Scala community, although an STM library exists, my impression is that STM is usually emulated by using actors.
  • If your concurrency problems mainly revolves around streaming multiple sources of data, think about using one of Scala's streaming libraries.
like image 77
badcook Avatar answered Oct 13 '22 19:10

badcook


Actors are specifically a tool in the toolbox for handling and distributing state. So yes, they should have state - if they don't then you just could use Futures.

Please note however that Actors (at least Akka Actors) handle distribution (running location-transparently on multiple nodes) which neither functions of Futures are able to do. The concurrency aspects of Actors are a result of them handling the more complex case - networking. In that sense, Actors unify the remote case with the local case, by making the remote case be first-class. And as it turns out, on networks messaging is exactly what you can both count and build on if you want reliable, resilient and also fast systems.

Hope this answers the "big picture" part of your question.

like image 39
Konrad 'ktoso' Malawski Avatar answered Oct 13 '22 20:10

Konrad 'ktoso' Malawski