Making Our Server into a Component

Understand how to split the server code into major components.

Earlier, we said that what Elixir calls an application, most people would call a component or a service. That’s certainly what our sequence server is: a freestanding chunk of code that generates successive numbers.


Our implementation puts three things into a single source file:

  • The API.
  • The logic of our service (adding one).
  • The implementation of that logic in a server.

Have another look at the code in the previous lesson. If we didn’t know what it did, how would we find out? Where’s the code that does the component’s logic? Imagine working with a really complex one with lots of logic. That’s why we’re experimenting with splitting the API, implementation, and server into three separate files.

We’ll put the API in the top-level lib/sequence.ex module, and we’ll put the implementation and server in the two lower-level modules. The API is the public face of our component. It’s simply the top half of the previous server module:

defmodule Sequence do

  @server Sequence.Server
  def start_link(current_number) do
    GenServer.start_link(@server, current_number, name: @server)

  def next_number do, :next_number)

  def increment_number(delta) do
    GenServer.cast(@server, {:increment_number, delta})


This forwards calls on to the server implementation:

defmodule Sequence.Server do
  use GenServer
  alias Sequence.Impl
  def init(initial_number) do
    { :ok, initial_number }
  def handle_call(:next_number, _from, current_number) do
    { :reply, current_number, }

  def handle_cast({:increment_number, delta}, current_number) do
    { :noreply, Impl.increment(current_number, delta) }

  def format_status(_reason, [ _pdict, state ]) do
    [data: [{'State', "My current state is '#{inspect state}', and I'm happy"}]] 

Unlike the previous server, this code contains no business logic (which in our case is adding either 1 or some delta to our state). Instead, it uses the implementation module to do this:

defmodule Sequence.Impl do

  def next(number),             do: number + 1
  def increment(number, delta), do: number + delta


Run the code using the following:

iex> Sequence.Impl.start_link 123  
{:ok, #PID<0.179.0>}
iex> Sequence.Impl.increment(123,100)

Use commands in the above snippet to run the code below:

Get hands-on with 1200+ tech skills courses.