Summary: Microsoft Scripting Guy, Ed Wilson, talks about the importance of formatting your Windows PowerShell code, returning objects, and other stuff.
Microsoft Scripting Guy, Ed Wilson, is here. It is Sunday in Charlotte, North Carolina. I have been busy grading scripts since early this morning. The last event, Event 10, appeared on April 13, but there is still one more week during which time contestants are turning in their final scripts. This is the time when the leaderboard will begin to dramatically shift. So I still cannot talk about issues from the last five events, but I can talk about some of the earlier events.
Neatness counts
I am not talking about being really crazy and making sure that everything lines up perfectly. I had a professor in college who used to take a ruler to the green bar paper we had to turn in, and he subtracted 1 point for each space that was not perfectly aligned. Regardless of how the code ran, it had to look perfect—in fact; it had to print out perfectly. I am NOT talking about that at all.
But, keep in mind that a fundamental concept is that you should be able to read and understand your script. If you can do that, you reduce the amount of troubleshooting by at least 50% (and no, I have not actually measured that—it is more of a guess). It is in my Windows PowerShell Best Practices book in the chapter about troubleshooting scripts.
So, what am I talking about when I talk about neatness? Here are a few quick guidelines:
- Avoid making someone scroll. Keep your code to the width of your screen, so that it does not flow off of the screen. When code is hidden from view, it is easy to make mistakes.
- Avoid using line continuation marks. The grave accent ( ` …I call it a backtick) is line continuation. It makes code hard to read, and is especially error prone. I have had many scripts that ran perfectly on my computer. Then when I posted them to the Hey, Scripting Guy! Blog, they no longer worked because it picked up an extra space or something. The grave accent is picky, and it is best to avoid it if possible.
- Break your code at the pipe ( | ) character. Leave your pipe characters on the right, and thus avoid line continuation.
- Indent subordinate clauses. Let’s say that you have an IF statement and your condition on one line. Now you have an ELSE clause. Intent the ELSE clause. How much? I generally use two spaces. The reason is that it is a visible indicator of an indent (it is easier to spot than one space), but it does not use as much space as a tab. Remember Rule 1: Keep your code narrow and avoid scrolling. If you use eight spaces for a tab, and you press tab tab tab, you just ate up 24 spaces, and you do not have much room for code after that. So I keep my indents to two spaces.
- Avoid using the Tab key for your tabs. This is because an actual Tab key (ASCII 9) is different than a space (ASCII 32). Some editors allow you to substitute spaces for the Tab key, and they even allow you to specify how many spaces to insert when you do hit the Tab key. This is useful, because some mediums do not correctly interpret a tab when it shows up in code. For this reason, I avoid using the actual Tab key, and I instead use spaces.
- Consider where you put the braces ({ }). This is really a personal preference. I played with putting the braces on their own lines, and lining up the opening and the closing brace. I fact, I still often do that. But at times, when the script is short, I will open the brace on the beginning line, and close it at the end of the last line; and therefore, the braces are not on their own individual lines.
- Avoid in-line comments. Instead put the comments on the line ahead of the line it comments. This is because when code is moved around, edited, or whatever, an in-line comment can break the code that follows. In addition, in-line comments are not as noticeable as comments on their own individual lines.
Return an object…please
It is best if you return an object. This is because anyone who uses your code can pipe the results to other cmdlets, such as Where-Object, Sort-Object, or even Format-Table or Out-GridView. But they are not required to do so. If you spend a lot of time in your script creating your own custom formatting, the person who uses your code cannot process it further. When you send something to Format-Table, Format-List, or Format-Wide, you are done. No further processing can be done because you no longer have the original object—you have a series of formatting objects that behave completely differently than the original object. When you return an object, you permit others to use your code in the way that they want to use it. It makes the eco-system better.
Meet the requirements
If my boss asks me to write a script that does x, y, and z, and I spend two days creating a really cool script that does a, b, and c, my boss is not going to be too happy. Because although he now has a script that does a, b, and c, he still needs a script to do x, y, and z. Part of developing solutions involves first analyzing the requirements, determining the inputs and the outputs from the script, examining use case scenarios, and finally, beginning to write the code. In fact, in many projects, the actual coding time is far less than the other tasks put together.
Well, that is about all I have time for today. I have a lot of scripts to grade. Take care, and I will see you tomorrow when I will have expert solutions to Beginner and Advanced Events 1.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy