Customize GenServer Behavior

Learn to customize GenServer behavior and use process registration to name individual games.

We'll cover the following

Plan the next step

Spawning and initializing a new GenServer process is a great start. However, the default callback implementations we get by using GenServer don’t go very far.

In order to build real applications, we need to change the way GenServer behaves to fit each application’s needs.

  • To do this, we’re going to follow the pattern we’ve used so far. First, write a client function that wraps a GenServer function. This, in turn, triggers a callback. We’ll define the new behavior in the callback.

  • Each time we add a new public function, we build a new piece of the interface for the game. As we go along, we’ll expose more and more of the game’s behavior. This interface acts as a boundary between the rest of the system and the game. That makes it the right place to check any values passed into the public functions.

  • We’ll need to check some conditions in each callback before determining whether the action went as planned. At a minimum, we need to check the rules for each action. Additionally, we might have to check that coordinates and islands are valid or that a player has positioned all their islands.

  • We could do this with conditional logic, but that could easily turn into a mess. Instead, we rely on Elixir’s with/1 special form. The with/1 form was designed to test multiple conditions in the same place without nested conditionals.

  • Every time we use with/1, we employ the same three blocks. The with block contains all the conditions we’re testing. The do block is for the actions we take when all the conditions pass, and the else block is where we handle errors.

Besides starting a new game, there are four behaviors we need to define:

  • Adding a second player
  • Positioning islands
  • Setting islands
  • Guessing coordinates

We’ll handle them in the same order.

Get hands-on with 1200+ tech skills courses.