Skip to content

Change what Elixir functions do via configuration values

Notifications You must be signed in to change notification settings

MainShayne233/feature_flag

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FeatureFlag

Build Status Coverage Status Hex Version

The What

FeatureFlag allows you to write functions that can have their behavior changed by setting/modifying a config value.

For instance, using FeatureFlag, you can define a function like so:

defmodule MyApp do
  use FeatureFlag

  def math(x, y), feature_flag do
    :add -> x + y
    :multiply -> x * y
    :subtract -> x - y
  end
end

This function will do one of three things depending on its feature flag value. You must set this value in your config like:

config :feature_flag, :flags, %{
  # the key here is {module_name, function_name, arity}
  {MyApp, :add, 2} => :add
}

At this point, the function would behave like so:

iex> MyApp.math(3, 4)
7

At runtime, you can change feature flag value using FeatureFlag.set/2, like so:

iex> FeatureFlag.set({MyApp, :add, 2}, :multiply)
:ok

And now the function would behave like so:

iex> MyApp.math(3, 4)
12

Boolean feature flags

If a function's feature flag will only ever be true or false, you can definie your function like so:

defmodule MyApp do
  use FeatureFlag

  def get(key), feature_flag do
    get_from_cache(key)
  else
    get_from_db(key)
  end
end

Use Case

The goal of this library is to make Elixir less pure provide an elegant and consistent mechanism for changing what a function does depending on a value that can easily be modified (i.e. a configuration value).

This could very easily be done in plain Elixir via a simple case statement:

defmodule MyApp do
  def math(x, y) do
    case Application.fetch_env!(:my_app, :math) do
      :add -> x + y
      :multiply -> x * y
      :subtract x - y
    end
  end
end

There's nothing wrong with this approach, and really no need to reach for anything else.

However, beyond removing a marginal amount of code, FeatureFlag provides a consistent interface for defining functions with this config-based branching.

Usage

Add FeatureFlag as a dependency in your mix.exs file.

def deps do
  [
    {:feature_flag, "~> 0.1.5"}
  ]
end

Run mix deps.get, then define your function:

defmodule MyApp
  use FeatureFlag

  def get(key), feature_flag do
    :old_database ->
      get_from_old_database(key)

    :new_database ->
      get_from_new_database(key)

    :get_from_newer_database ->
      get_from_newer_database(key)
  end
end

If you attempt to compile now, it will fail, because you need to explictly declare the feature flag value for this function in your config:

# config/{dev,test,prod}.exs

config :feature_flag, :flags, %{
  {MyApp, :get, 1} => :old_database
}

Then you're done! Initially, this function will simply execute the :old_database block. You can change this at runtime by running:

FeatureFlag.set({MyApp, :get, 1}, :new_database)

Mentions

I'd like to thank the following people who contributed to this project either via code and/or good ideas:

I'd also like to thank @Packlane for giving me time to work on and share this software.

About

Change what Elixir functions do via configuration values

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages