DRY and Immutable are two key terms well known in traditional coding, they are two sides of the same coin.
What is DRY?
You may or may not have heard of the term DRY in regards to infrastructure as code. The term DRY is a reference to Don’t Repeat Yourself. The opposite is WET code or Write Everything Twice.
The concept of keeping your code DRY is quite important to terraform. The ability to only mention something once reduces the possibility of introducing errors or conflicts.
DRY is a principle of software development aimed at reducing repetition of software patterns, replacing it with abstractions or using data normalization to avoid redundancy.
The DRY principle is Every piece of knowledge must have a single, unambiguous, authoritative representation within a system. When applying the DRY principle successfully, a modification of any single element of a system does not require a change in other logically unrelated elements. Additionally, elements that are logically related all change predictably and uniformly, and are thus kept in sync.
As an analogy, DRY and WET are not that bad a concept, WET clothes are heavier than DRY clothes, they are hard to maintain or manipulate, for example you wouldn’t pack wet clothes into your wardrobe they would go moldy. Dry clothes are by contrast, lighter in weight, easier to fold and store in your wardrobe, also they will not go moldy and start smelling.
WET and DRY code fits this analogy very well, WET code is in the main haphazard, The possibility of fat fingering an input in increased each time you need to enter it. Each time you need to write a set of code you can introduce errors and or conflicts, and the risk of error increases with more repetition.
What is Immutable?
Immutable means unchanging over time. in the context of coding and infrastructure, immutable means that there’s only a single place where changes are authored: at the code level. This sets off processes (pipelines) that replace the previous version of an application build or infrastructure configuration with a new version. The key here is that the existing application or infrastructure are immutable: not changed, but replaced alltogether.
Why do we need DRY and Immutable Terraform Code
When we first started writing our LAMP Stack deployment we had a single environment and a single file. This code, we could say, was this code was dripping wet. This is often done to make sure that things just work. Quick and dirty. Unfortunately Quick and Dirty often becomes production code. And that’s how we’ve always done it and it’s not broken so don’t fix it are the enemy of Good and the antithesis of Great. Reworking badly formed code and infrastructure is hard and as such we will instinctively shy away from attempting to rework it to a simpler form.
In the Terraform series, we did re-work our code. When we originally wrote the LAMP Stack code it was for a single availability zone. We had no real variables declared, no reusable modules. As we moved though the series it soon became apparent that we had coded ourselves in to a WET box and needed a code rewrite to handle the growth of the code to accomodate for more services, more availability zones and more.
This meant looking at modules, variables, folder layout effectively butting the code in the dryer to dehydrate it and make it immutable.
The end result is code that is easier to manage, quicker to fix, more readable and re-usable across Dev, Test and Prod; the only things changing between each environment are variables and scale. This is DRY and Immutable code.
Advantages for DRY and Immutable Code
Now you understand why DRY and Immutable code are useful; let us investigate the advantages.
As there is now a defined logic to your code, variables and modules, the ability to change a module or variable is simpler, as from the perspective of your infrastructure it is only consuming outputs or providing inputs. It separate the logic (or function) from the specific inputs. The ability to change a modules’ logic without affecting its outputs or inputs means that it is more maintainable and the risks of everything blowing up in your face is vastly reduced.
By breaking the code into usable modules you can understand the flow and infer meaning much more easily and can see the flow of inputs and outputs.
The is no requirement to define or write things more that once instead you will utilize already written modules. This reduces duplication of effort, freeing up time for improvements of that same code.
Just like when you created your first VMware template to streamline your deployment of virtual machines you are not continually re-inventing the wheel every time you deploy a new environment. This makes you the friend of the finance team as you are effectually reducing costs out of projects by decreasing the time to value metric.
Unit testing is much easier with DRY and Immutable code. There is no requirement to define configuration and functional testing for every module; only modified code needs testing.
That said this is not a panacea. A little bit of caution here… Not everything can be DRY. Sometimes it is OK for a little bit of dampness.
Getting to 100% DRY code will not be worth the effort. Like all things in life it is the 80/20 rule and the law of diminishing returns applies here as well.
Not everything needs merging into a single piece, indeed doing so to the n’th degree can actually increase costs, complicate readability and manageability.
DRY and Immutable code is your endpoint in developing your Infrastructure-as-Code deployments. Working towards it will improve your environment, making your code more readable and manageable. However, do not let it become an albatross around your neck. Sometimes the effort to make your code truly immutable and DRY is not worth the effort of moving past the 80% mark as the costs of work to undertake that last mile is excessive against the benefits that it will bring.