Episode 011: The Convention of Configuration
► Play EpisodeNate is worried about the hardcoded credentials in the code.
- It's episode 011 on 01/11. It's binary!
- "As a developer, you quickly learn what's under your control and what's not. Very little is under your control."
- Don't accidentally check in the credentials.
- "We need a configuration management system. Oh wait! That's a totally different problem."
- What about putting the configuration into an EDN file?
- Let's call it
config.edn
- Why EDN? Isn't JSON the "one, true format for config information"?
- Pros of EDN:
- native to Clojure
- can have comments
- is extensible
- Why not environment variables?
- Environment variables are great for production, but in development files are better.
- Have to restart the REPL to change env variables.
- Make a component that reads the config. That will reload config when you
reset
with component.repl. - Two main considerations:
- Dynamically reloading configuration during development
- Plumbing the configuration values through the app
- Make a namespace for
app.config
- "Files are way more fungible than the environment."
- We want both options: env for production and a file for dev.
- Make two functions in
app.config
:from-env
andfrom-file
. - Use schema to make sure both functions return the same config map.
- "A thing I have done before...you decide if it's clever."
- Define a default configuration and then
merge
the config maps with that. - Better yet,
from-env
handles defaults and wemerge
the map fromdev.edn
into that. - Can use
environ
with Leiningen profiles. Still requires restarting the REPL. - Defaults should make sense for development, so you can just check out and run.
- For bad config, we want helpful error messages, not stack traces.
- What goes in configuration?
- Items under your control
- Items that vary
- Twitter API URL does not vary.
- Even if Twitter provided sandbox URLs, those URLs don't vary. The config option should be "production" and "sandbox", not the URL. The wrapper code will select the right URL.
- Avoid the nonsense of trying to infer "sandbox" from reading the URL.
- "The hallmark of good design is: the less thinking you have to do, the better."
- "The more semantic the config, the less thinking you have to do."
- It's important to think about the data first, where it comes from, and where it goes.
Clojure in this episode:
merge
try
,catch
slurp
clojure.edn/read-string
environ.core/env
component.repl/reset
Related projects:
Code sample from this episode:
(ns app.config
(:require
[clojure.edn :as edn]
[environ.core :refer [env]]))
(defn from-env []
{:twitter-key (or (env :twitter-key) "")
:twitter-secret (or (env :twitter-secret) "")
:initial-tweets (or (env :initial-tweets) 20))
(defn config []
(merge (from-env)
(edn/read-string (try (slurp "dev.edn") (catch Throwable e "{}")))))