Difference between processes/messages in Elixir/Erlang and objects/messages in Smalltak

The problem with that approach is that when it comes to design not all objects are created equal. For example in 2003 Domain Driven Design classified some fundamentally different categories of objects:

From the Domain Driven Design Reference:

Elixir and Erlang are concurrent programming languages first (with a heavy leaning towards fault tolerance and resilience) and functional programming (FP) languages second.

Note the recommendation: “Treat the value object as immutable.” One trait that most functional languages share is that values are immutable by default. So value objects are simply (immutable) values in FP.

See also: The Value of Values

In Elixir these values could be structs, maps, lists, tuples or any of the other basic types - not processes.

In class-based OO any capabilities pertaining to the value object would be typically implemented as methods - in Elixir/Erlang these capabilities are implemented as functions which are then collected in cohesive modules.

Does that mean that entities are implemented as processes? Not necessarily. While entities have a distinct identity they tend to change their characteristics over time. So different values may simply represent the same entity at different points in time. Also given that functional programming focuses on data transformation it is often not necessary to share an entity between multiple collaborators - instead the entity can pass through a data transformation pipeline (composed of (mostly pure) functions) that progressively refines the representation of that entity - so some entities can still be represented as values under the right circumstances.

So what a processes good for? Processes are used to manage (concurrent) runtime concerns:

Objects on the other hand are often used to separate design-time concerns. Taking “Erlang might be the only object-oriented language” at face value would be repeating Alan Kay’s mischaracterization all over again:

I’m sorry that I long ago coined the term “objects” for this topic because it gets many people to focus on the lesser idea. The big idea is “messaging” …

Imperative programming (where logic is usually composed of statements) is often well represented via flowcharts which illustrates an important point - imperative programming is about the flow of control (fundamentally a Program Counter perspective).

Functional programming (where logic is typically composed of expressions) on the other hand is primarily about data transformation, or phrased differently, the flow of data. Now in a single threaded environment you will only be transforming one piece of data at a time - but with that perspective it’s clearer what the data dependencies are (because of the data transformation pipelines) which also makes it easier to identify activities which can take place concurrently. And doing things concurrently is what processes excel at.

Also there are important differences between the message abstractions used in OO and on the BEAM (the Erlang VM).

In OO a message (often mimicked via method invocation) doesn’t just transfer data (method arguments) but it also transfers the flow of control to the receiving object which enables it to do some processing.

On the BEAM a message simply arrives in the process’s mailbox. The process code may process that message immediately - but it may not if it is already doing something else as all the logic inside a single process is executed strictly sequentially. So the message does deliver data but the raw capacity of the process to perform work isn’t directly dependent on the arrival or presence of message data.

An object often combines internal data as its state with the behaviour to mutate that state. A process is also behaviour capable of evolving its internal state. While both offer some sort of isolation and share some similar characteristics they are very different beasts.

5 Likes