Abstracting away side-effects with Higher-Order Functions in PowerShell

Cleaner, safer PowerShell code using functional abstractions

Christopher Kuech
ITNEXT
Published in
3 min readApr 6, 2020

--

I generally write PowerShell with a pathological aversion to state and side-effects. In reality, these undesirable patterns are often unavoidable, especially in DevOps. Unavoidable CLIs like git and compilers require the stateful shell cursor to move to a different directory before the CLI can be invoked; mutable collections must be maintained; integration tests and infrastructure code often requires provisioning of temporary resources in the cloud — all of these operations change the state of our system and subsequently put the system in an unknown, difficult-to-manage state.

In this article, we review a few examples of leveraging higher-order functions to abstract away side-effect management from our scripts.

Stay stateless, my friends.

Invoke-InDirectory

The Problem

Often in DevOps, you will need to run a command inside a specific directory. For example, git (unlike most PowerShell commands) does not take a directory path argument and expects you to cd into the correct directory before executing. Similarly, application building CLIs like npm, docker, dotnet, etc., generally operate best in the directory root.

We could always Push-Location or Set-Location into the directory we need, but then we would always have to remember to come back out when the script completes. Worse, we need to add boilerplate try/finally statements in case our script fails — otherwise, the person running the script will unexpectedly find their terminal in a different location than they expected.

The Solution

We can write a higher-order function named Invoke-InDirectory to abstract away the boilerplate required to invoke a command inside a given directory without causing side-effects (the terminal is in an unexpected location if the command errors).

--

--