PowerShell Pipeline
Writing Readable PowerShell Code for Your Future Self (And Others)
Code with aliases and comments may help you to keep your place, but will you remember what it means a couple years down the road?
I see it time and time again. Whether it is in a blog or looking at a script that someone put together, I see code that is hard to read either by the use of aliases, variable names that do not make sense or even something such as code formatting that seems to be all over the place. While at the time, you may be able to read the code and troubleshoot issues after it has been placed into production or handed off to another group to use.
Aliases in Scripts
Aliases are something that is great to use in the console but when it comes to using these in your scripts, it is best to write the full command and/or parameter out. For instance, the following code gets the top 10 process with the most memory utilization:
gps | sort WS -des | select -fi 10
This is still readable for the most part, but even this can make you think a minute on what it is actually doing prior to running it. What happens if this actually does something that could potentially bring down a system? Of course, in this case it is nothing more than a piece of code that does nothing more than provide a report. But unless you start to break down each alias, you may end up running something that could potentially do some damage.
Now let's break this out to something more readable:
Get-Process | Sort-Object -Property WS -Descending |
Select-Object -First 10
This is more to type and uses more characters, but it certainly makes things easier to understand. Imagine a script where everything (or mostly everything) is written using aliases.
One last thing on this subject: Where-Object and ForEach-Object are common cmdlets that really have a couple of aliases that could be used. Where-Object has ? and Where while ForEach-Object has % and ForEach. This really is an edge case where the aliases of Where and ForEach would be more acceptable in a script as you can still easily understand what is going on in the code. Should you still use the full name? Sure, but using Where and ForEach won't exactly hurt the readability of the script like using ? and % would.
Skimping on Variable and Parameter Names
Another key thing to avoid is using unreadable names for variables and parameters. This really goes along the lines of using aliases that I mentioned above. Short names such as CN instead of Computername for a parameter or $d instead of $Date for a variable name. Both of these might make sense to you at the time, but when you are reading this code a couple years from now or someone else is now looking at your code to troubleshoot or add more functionality to it, some extra may be taken to translate what each of these may mean. It is better to take the time to write out the full variable name so it can more easily be read to determine what its purpose is.
Readable parameters are a must if you plan to place your code out for others to use. Take the help example here:
Unless you dive into the help a little more (assuming it has been written), you really have no idea what these parameters are and what they may do. Well, except for –ToFile as that is pretty self-explanatory. But what about –CN and –Re? I can only make assumptions that CN would be Computername and Re is Recurse. These may make sense to you as these were created by you, but passing the code to someone else could lead to some confusion as to how to use the parameters. If you really want to have the benefits of these aliased parameters, simply use the [Alias()] attribute for the parameter to supply those extra aliases.
Function Test-Something {
[cmdletbinding()]
Param(
[parameter()]
[Alias('CN')]
[string[]]$Computername,
[parameter()]
[Alias('Re')]
[switch]$Recurse,
[string]$ToFile
)
}
Now we have readable parameters but can still use the aliases that you know and love!
Only Comment Where Needed
This probably sounds a little odd, but trust me, we want to know what is happening in the code but do not need a full dissertation on it or explaining the obvious. Commenting is one of the best ways to help someone reading your code (and your future self) to show what is supposed to be happening or why you are coding a particular portion that way that you are. Keep in mind that using Write-Verbose and Write-Debug should be used to help debug the code while it is running to better see what values are being used as well as showing different points where a specific action in the code is occurring.
To dive a little more into this, let's assume that you a portion of your code is done using Get-Process to get some processes and you want to sort them by name…just because. You shouldn't comment it like below to say that you are getting processes because that is redundant. The beauty of PowerShell, especially with the cmdlets, is that it can be self-documenting assuming you use the full commands and not aliases (see my first section in this article).
The point is that we can tell what is happening in this instance without the need for a comment.
This example shows that areas are commented where it may not be completely evident as to what is going on. Sure we might be able to figure out the first line about creating the listener, but understanding Pending() and AcceptClient() would most likely lead to researching online as to their purpose. Adding a quick comment can at least give the person an idea as to what is happening. Also note the use of Write-Verbose statement to help show that a new connection has been made. Not exactly a comment, but something like this can help with troubleshooting a script if need be.
That wraps up today's article on writing readable PowerShell code. Using these tips can help to ensure that your future self will be able to quickly look at your past code and perform troubleshooting or add more functionality to it!
About the Author
Boe Prox is a Microsoft MVP in Windows PowerShell and a Senior Windows System Administrator. He has worked in the IT field since 2003, and he supports a variety of different platforms. He is a contributing author in PowerShell Deep Dives with chapters about WSUS and TCP communication. He is a moderator on the Hey, Scripting Guy! forum, and he has been a judge for the Scripting Games. He has presented talks on the topics of WSUS and PowerShell as well as runspaces to PowerShell user groups. He is an Honorary Scripting Guy, and he has submitted a number of posts as a to Microsoft's Hey, Scripting Guy! He also has a number of open source projects available on Codeplex and GitHub. His personal blog is at http://learn-powershell.net.