View Source Errata.DomainError behaviour (Errata v0.1.0)
Support for creating custom domain error types, which can either be returned as error values or raised as exceptions.
Domain errors are named, structured types that represent error conditions within a problem domain or bounded context. Being named types means that errors have a meaningful name within a particular context, and that name should be part of the Ubiquitous Language of the context. Being structured types means that errors can have arbitrary contextual information attached to them for logging or debugging purposes.
Domain errors can be defined by creating an Elixir module that uses the Errata.DomainError
module. Error types defined in this way are Elixir Exception
structs with the following keys:
message
- human readable string describing the nature of the errorreason
- an atom describing the reason for the error, which can be used for pattern matching or classifying the errorextra
- a map containing arbitrary contextual information or metadata about the error
Because these error types are defined with defexception/1
, they can be raised as exceptions
with raise/2
. However, because they represent domain errors rather than system or
infrastructure errors, in most cases it is more appropriate to create instances of the error
structs using new/1
or create/1
and use them as return values from domain functions,
either directly or wrapped in an error tuple such as {:error, my_domain_error}
.
Usage
To define a new custom domain error type, use/2
the Errata.DomainError
module in your own
error module:
defmodule MyApp.SomeError do
use Errata.DomainError,
default_message: "something isn't right"
end
To create instances of the error, to use as an error return value from a function, say, you can
use either new/1
or create/1
, passing params with extra information as desired. Note that
if you use create/1
, you must first require
the error module, since this callback is
implemented as a macro. For example:
defmodule MyApp.SomeModule do
require MyApp.SomeError, as: SomeError
def some_function(arg) do
{:error, SomeError.create(reason: :helpful_tag, extra: %{arbitrary: "metadata", arg: arg})}
end
end
To raise errors as exceptions, simply use raise/2
passing extra params as the second argument
if desired:
defmodule MyApp.SomeModule do
require MyApp.SomeError, as: SomeError
def some_function!(arg) do
raise SomeError reason: :helpful_tag, extra: %{arbitrary: "metadata", arg: arg}
end
end
Summary
Types
Type to represent the :env
field of domain error structs.
Type to represent allowable keys to use in params use for creating domain error structs.
Type to represent allowable values to be passes as params for creating domain error structs.
Type to represent domain error structs as defined by this module.
Callbacks
Invoked to create a new instance of a domain error struct with default values and the current ENV.
Invoked to create a new instance of a domain error struct with the given params and the current ENV.
Invoked to create a new instance of a domain error struct with default values.
Invoked to create a new instance of a domain error struct with the given params.
Invoked to convert a domain error to a plain, JSON-compatible map.
Functions
Creates a new domain error struct of the given error_type
using the given params
.
Creates a new domain error struct of the given error_type
using the given params
and env
.
Formats the given domain_error
as a string.
Returns true
if term
is a type of Errata.DomainError
; otherwise returns false
.
Types
@type env() :: %{ context: Macro.Env.context(), context_modules: Macro.Env.context_modules(), file: Macro.Env.file(), function: Macro.Env.name_arity() | nil, line: Macro.Env.line(), module: module() }
Type to represent the :env
field of domain error structs.
This struct is a subset of of Macro.Env
and contains the following fields:
context
- the context of the environment; it can be nil (default context), :guard (inside a guard) or :match (inside a match)context_modules
- a list of modules defined in the current contextfile
- the current absolute file name as a binaryfunction
- a tuple as {atom, integer}, where the first element is the function name and the second its arity; returns nil if not inside a functionline
- the current line as an integermodule
- the current module name
@type param() :: :message | :reason | :extra
Type to represent allowable keys to use in params use for creating domain error structs.
See also params/0
.
Type to represent allowable values to be passes as params for creating domain error structs.
This effectively allows for using either a map or keyword list with allowable keys defined by
param/0
.
@type t() :: %{ :__struct__ => module(), :__exception__ => true, :message => String.t(), :reason => atom() | nil, :extra => map() | nil, :env => env() | nil, optional(atom()) => any() }
Type to represent domain error structs as defined by this module.
Error structs are Exception
structs that have additional fields to contain extra contextual
information, such as an error reason or details about the context in which the error occurred.
Callbacks
@macrocallback create() :: Macro.t()
Invoked to create a new instance of a domain error struct with default values and the current ENV.
See create/1
.
Invoked to create a new instance of a domain error struct with the given params and the current ENV.
Since this is a macro, the __ENV__/0
special form is used to capture the Macro.Env
struct
for the current environment and the public fields of this struct are placed in the exception
struct under the :env
key. This provides access to information about the context in which the
error was created, such as the module, function, file, and line. See env/0
for further
details.
Note that because this is a macro, callers must require/2
the error module to be able to use it.
@callback new() :: t()
Invoked to create a new instance of a domain error struct with default values.
See new/1
.
Invoked to create a new instance of a domain error struct with the given params.
Invoked to convert a domain error to a plain, JSON-compatible map.
Functions
Creates a new domain error struct of the given error_type
using the given params
.
@spec create(module() | struct(), params(), Macro.Env.t()) :: t()
Creates a new domain error struct of the given error_type
using the given params
and env
.
Formats the given domain_error
as a string.
Uses the :message
field of the domain_error and combines the :reason
field with it, if it is not nil.
Returns true
if term
is a type of Errata.DomainError
; otherwise returns false
.
Allowed in guard tests.