How would PragDave separate this code?

Another goal of the article seemed to be encapsulation of data inside the process.

In objects the advantage of encapsulation is two-fold:

  • only the object’s methods can mutate the internal data
  • client objects couple with the interface (API), not the structure of the internal data.

In Elixir values are immutable so mutating a data structure is not an issue (though a name can be rebound). However if clients have to access the data structure directly they become coupled.

When it is desirable to treat the data structure as opaque then all access needs to go through module functions to decouple the caller from the internal structure. While this type of “encapsulation” isn’t enforced, it is often good enough.

So in the article it was surprising to me that the API was modified for the server version when in fact all that was needed was to go from:

@type names() :: map()

@spec new() :: names()
@spec lookup(n, k) :: {:ok, v} | :error when n: names(), k: term(), v: term()
@spec store(n, k, v) :: n when n: names(), k: term(), v: term()

to

@type names() :: pid()

@spec new() :: names()
@spec lookup(n, k) :: {:ok, v} | :error when n: names(), k: term(), v: term()
@spec store(n, k, v) :: n when n: names(), k: term(), v: term()
1 Like