Created
September 30, 2015 15:04
-
-
Save CrowdHailer/edbbbf7440f0b85e053e to your computer and use it in GitHub Desktop.
Creating boundary modules for elixir applications. These have their implementation set during the configuration step. In this example we switch clock between system clock and a dummy clock
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This module represents a behaviour and when used picks from the Application configuration which implementation will be used | |
defmodule Clock do | |
@callback now() :: Integer.t | |
defmacro __using__([]) do | |
module = Application.get_env(:my_app, :Clock) | |
quote do | |
alias unquote(module), as: Clock | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# In config/dev.ex and in config/prod.ex we set up the module that we would like to use as the implementation for the Clock boundary | |
use Mix.Config | |
config :my_app, Clock: SystemClock | |
# In config/test.ex we use a Dummy Clock implementation | |
use Mix.Config | |
config :my_app, Clock: DummyClock |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Returns a constant value for testing purposes. | |
defmodule DummyClock do | |
def now do | |
# Time at 15:42 on 30th September 2015 | |
14436241340007622 | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# All production code just uses the Clock module and has no knowledge of the possible change in implementation | |
defmodule MyApp do | |
use Application | |
use Clock | |
def time do | |
Clock.now | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This is an implementation for the Clock boundary that asks the operating system for the current time. | |
defmodule SystemClock do | |
@behaviour Clock | |
def now do | |
round(:erlang.system_time(:nano_seconds)) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A functional program that wants to perform useful work must interact with stateful services. The simplest example I could think of was getting the current time but more likely situations would be net requests or database access.
The purpose of this code sample is to wrap these surfaces behind a single module. In tests it is very likely that you would want to not access the real services so this gives a way to provide fake implementation.