Even in simple, smaller applications we have to deal with configuration of some kind. Since we all know that hardcoding config values sucks, we tend to pick the easy-yet-flexible and powerful method - reading values from environmental variables. In this short post, I’ll show you how to embrace functional concepts and make configuration reading type safe. And, as a bonus, you’ll get fancy error reporting in case something goes left.
Our goal is to read all necessary values at app startup — we absolutely don’t want to find out that the database password is missing in the middle of http request processing — and terminate with a human-readable message in the console if something is missing or invalid.
Enough talk, let’s start with the code!
As you can see, decoding yields transform either the value or error if something fails.
Guilio provides us with a few built-in decoders and combinators, so we can create our reader by combining them (as any decent functional developer would do).
Primitive decoders don’t do anything fancy:
But as soon as we combine them, the magic starts to happen:
Let’s say, we need to read db user, password, and port that our application will be listening on. We use type combinator for composing the decoder:
Maybe we want some of the properties to be optional and to supply default values:
Now we can extract static type from the decoder instance:
And use it in our application like this:
Happy functional coding! λ
Even in simple, smaller applications we have to deal with configuration of some kind. Since we all know that hardcoding config values sucks, we tend to pick the easy-yet-flexible and powerful method - reading values from environmental variables.
At Cookielab, we use and contribute to many open source projects (OSS). Our primary motivation is not necessarily to give back to the community (which we care about greatly). The fact is that we use open source tools to help us to be more productive, and we usually use them for client-facing work.
Write tests, do proper code reviews, run your code before deployment, use database transactions, update dependencies, and on and on and on. Do these things - no matter your seniority - and be one of the good ones!