Want to see the full-length video right now for free?

Sign In with GitHub for Free Access


Our languages give us great tools in the form of primitives: things like integers, strings, and arrays. However, over-relying on these leads to problems. This practice even has it's own fancy code smell name: Primitive Obsession. In this video, Derek and Joël take a look at Primitive Obsession and the various abstraction tools languages provide to deal with it.

What does it look like in Ruby?

Over relying on hashes/arrays

Representing dollars/cents as an two-element array:

# $5.30
[5, 30]

Representing hours/minutes as an integer

# 7:30 PM

Representing a user as a hash

{ name: "Joël", age: 42 }

Why is it a bad idea?

  • Harder to read
  • Many domain concepts combined together
  • In Ruby, need to define methods somewhere
  • Allows representing invalid values
  • Hard to change

What are the solutions?

More objects

class Money
  def from_cents(cents)
    new(cents / 100, cents % 100)

  def initialize(dollars, cents)
    @dollars = dollars
    @cents = cents

What about functional languages like Elixir?

We don't have objects so what's the alternative?

  • Structs, which have predefined fields.

Discuss custom types in Haskell/Elm

Compilers reward you for avoiding primitives

type Seach = 
  { query : Maybe String
  , results : Maybe (List String)

We can eliminate the Maybe primitive by modeling with a custom type:

type Search
  = NotStarted
  | TermSelected String
  | ResultsFetched String (List String)

It's also more expressive, easier to read, and easier to extend by adding other states.

General ideas

Try to program at a higher level of abstraction with domain concepts rather than language primitives.