There are a wide array of benefits that you can get from leveraging your static descriptions. This is bonus material from an earlier article.
Performance
One valid concern with the code from my declarative design article is that it performs slightly slower than the imperative version, because it checks the description each time. This doesn't matter for this example, but could matter as your description/engine grow. If you're using a language that supports macros, you can actually side step this relatively easily. This is ugly, but a lot of metaprogramming is. In my experience, this kind of thing is generally unnecessary, but I want to show how it can be done. This also won't really be very useful if you don't know Elixir. Here is a redefinition of our engine (the create
function) as a macro:
defmacrop create(object, current_user, attributes, operation_name \\ nil) do
create =
if @config[object][:audit_log?] do
quote generated: true do
result = # create object
operation_name = operation_name || "create_#{unquote(object)}"
create_audit_log(unquote(object), unquote(current_user), unquote(operation_name), unquote(attributes))
result
end
else
quote generated: true do
# create object
end
end
authorized_create =
if @config[object][:forbid_interns?] do
quote generated: true do
if is_intern?(unquote(current_user)) do
# return a 403
else
unquote(create)
end
end
else
create
end
quote generated: true do
try do
unquote(authorized_create)
after
report_timing(operation_name, System.monotonic_time() - start)
end
end
end
Documentation
A very useful thing to do with the description is to derive your in-code (and often out-of-code) documentation from it. Here is an example of that with our description:
defmodule SomeBusinessLogicDocumenter do
def doc(config) do
interns_allowed =
if config[:forbid_interns?] do
"Interns are not allowed"
else
"Interns are allowed"
end
audit_log =
if config[:audit_log?] do
"Generates an audit log"
else
"Does not generate an audit log"
end
"""
* #{interns_allowed}
* #{audit_log}
"""
end
end
defmodule SomeBusinessLogic do
@config [
person: [
forbid_interns?: true,
audit_log?: true
],
organization: [
forbid_interns?: true,
audit_log?: true
],
post: [
audit_log?: true,
forbid_interns?: false
],
audit_log: [
audit_log?: false,
forbid_interns?: false
]
]
@doc """
Creates a person.
#{doc(@config[:person])}
"""
def create_person(current_user, attributes) do
create(:person, current_user, attributes)
end
@doc """
Creates a organization.
#{doc(@config[:organization])}
"""
def create_organization(current_user, attributes) do
create(:organization, current_user, attributes)
end
@doc """
Creates a post.
#{doc(@config[:post])}
"""
def create_post(current_user, attributes) do
create(:post, current_user, attributes)
end
@doc """
Creates an audit log.
#{doc(@config[:audit_log])}
"""
defp create_audit_log(object, current_user, operation, attributes) do
create(:audit_log, current_user, attributes, "create_audit_log_for_#{operation}")
end
# ...
end
With that, my editor now gives me on hover descriptions of each operation, with very little effort overall.

