The Thing About Variables, Arguments and Parameters

When dealing with variables, arguments and parameters, in IaC there are a few tips and tricks that I have picked up over the years. Below I have broken it down into a few principals and keeping some of these principles in mind has not only helped me when coding infrastructure or automating something but has also influenced how I think about the deployment view in solution architecture design.

Firstly, let's define what each of these are

  • Variable - A variable is a named storage location that can hold a value. The value of a variable can change over time. Variables are used to store information that can be used by a program or script. Variables can be :
  • in different scopes such as global, local, script, function, etc.
  • using different data types such as int, string, array, object, etc.
  • using different naming conventions such as camel case, snake case, etc.

  • Argument - An argument is a value that is passed to a function or script. Arguments are used to provide input to a function or script. Arguments can be passed by position or by name.

  • Parameter - A parameter is a variable that is used to store an argument. Parameters are used to receive input from arguments. Parameters can be defined :

  • in different scopes such as global, local, script, function, etc.
  • using different data types such as int, string, array, object, etc.
  • using different naming conventions such as camel case, snake case, etc.

The main principles

The following principles has been heavily inspired by one of my dear friends during one of our insightful and collaborative chats. The base premises is this, from a coding/compute/human effort perspective we want to make it as easy / cheap for the "machine" to do its thing. So, the following principals are based on this idea.

  1. Convention over Configuration - This is a software design principle that suggests that the default configuration should be used whenever possible. This means that the system should be able to infer the configuration from the context. This is a powerful concept that can be applied to variables, arguments and parameters. Where possible you should use convention over configuration to reduce the amount of configuration that is required but still allow it to be changed from the default if needed. This is particularly useful in functions and scripts where you can define default values for parameters. This means that the parameter can be omitted when calling the function or script and the default value will be used.

  2. Calculate / Predict - From a compute perspective it is cheaper to calculate or predict a variable/argument from something you know. Here are some real-world examples of how this can be applied, these examples are somewhat Azure specific, but the concept can be applied to any platform.:

    • Resource Naming - When creating a resource or resource group name, you can calculate the name based on the environment, region, system, subsystem and suffix. By combining these variables that are known you can "calculate" / "predict" the name of the resource group. From a compute perspective this is fast and cheap to achieve. See how I do this in my other article on naming conventions.
    • Unique Identifier - When creating a unique identifier, you can calculate the identifier based on the current date and time. This will give you a unique identifier that is easy to generate and is guaranteed to be unique.
    • Password - When creating a password, you can calculate the password based on a randomized algorithm. This will give you a password that is easy to generate and is guaranteed to be secure. I used this in password generation snippet.
  3. Interrogate - If you can't calculate it, then interrogate it. This means that you should ask the system for the value of the variable/argument. This is more expensive than calculating it but still cheaper than defining it.

    • If a variable cannot be calculated or predicted, then you should try and interrogate the system for the value of the variable/argument. In the case of Azure this could be achieved by querying the Azure Resource Manager API for the value of the variable/argument. For example: Subscription name, the value of a specific tag like environment name. the region of a resource group or resource.
  4. Define - If you can't interrogate it, then define it.

    • As a last resort you can define the variable/argument. This is the most expensive way as it requires human effort to maintain the value of the variable/argument over time. This should be avoided where possible.

Other considerations

  • Don't Repeat Yourself (DRY) - If a variable/argument is expected to have the same value then it should be defined once and used everywhere. This will make it easier to maintain and update the variable in the future.
  • Naming - When naming variable/argument:
  • make sure the name is descriptive and easy to understand. This will make it easier for other people to understand what the variable is used for.
  • use camel casing to make the variable/argument name easier to read. This means that the first letter of each word in the variable/argument name is capitalized except for the first word.
  • Scope - Make sure that the variable is scoped correctly. This means that the variable should only be available where it is needed and not available where it is not needed. This will help to reduce the risk of the variable being used incorrectly. This applies specifically where variables are passed into script blocks and functions.