Photo by Maxime VALCARCE on Unsplash

Actor Model, “To be, or not to be, that is the question”

The actor model is a programming model to deal with concurrent computation. The model is great to build scalable and fault-tolerant software. Scalable software that can scale up to multiple cores or scale out to distributed computing enviornments such as cloud environments. Fault-tolerant following the Erlang's "let it crash" model where the failure of an actor will not have an impact on the global state of the application.

If you are not familiar with the actor model, the blog post from Brian Storti here https://www.brianstorti.com/the-actor-model/ is an excellent and short introduction to the actor model. Also, check reference section at the end of the post for more material regarding actor model 

Actor model is the base of the Erlang language, the Elixir framework for Erlang, the Akka framework for the JVM, the Celluloid for Ruby and more.

But actor model suggests that everything should be an actor, but is this efficient? You might be tempted to have everything as an actor but this sounds like "if all you have is a hammer, everything looks like a nail", right?

Not all aspects of an application can be modeled as an actor, similarly not all aspects of an application can be modeled as an object and that's why we see more and more functional programming mixins now days, but this topic is out of the scope for now.

My experience with Actor model comes from working with Akka framework where I identified several tasks and design patterns that actor model is not suitable. 

For this I developed two rules that can be used when trying to decide if actor model fits the task or not.

  • If the task execution is not somehow connected to an actor, the task shouldn't be modeled as an actor.
  • If the task outcome has no impact on the actor state, the task shouldn't be modeled as an actor.

Here are some examples for tasks in an application that shouldn't be actors:

  • a task to keep audit logs. Audit logs can be considered metadata of an application main operations. A task to store audit logs, shouldn't be modeled as an actor since the task execution is (MUST) be disconnected by the main operations of the application and also the outcome of the task (MUST) has no impact on the state of the application.
  • a task to collect metrics and statistics. Application metrics and statistics are provided as a way to monitor application performance. A task to collect and store metrics and statistics shouldn't be modeled as an actor since the task execution is (MUST) be disconnected by the main operations of the application and also the outcome of the task (MUST) has no impact on the state of the application.
  •  a task to update usage data. Application usage data can be used for accounting or marketing purposes. A task to collect and store such usage data shouldn't be modeled as an actor since the task execution is (MUST) be disconnected by the main operations of the application and also the outcome of the task (MUST) has no impact on the state of the application.

On the contrary, for the following tasks using an actor seems the proper design

  • actor representing shopping basket in an eshop application.
  • actor representing device in an IoT application

Of course it all comes down to the the nature of the application, if for example the application main concern is to collect metrics, audit logs and generate reports etc, then an actors should represent those functions now.

Actor model is powerful tool but it comes with great responsibility. Trying to fit all application requirements in the actor model is wrong approach and will lead to problems than solutions.

Reference

This article was updated on February 19, 2019

Comments