Posey's Tips & Tricks
Best Practices for PowerShell Dot Sourcing, Part 2
Let's dive into some practical advice on naming conventions, variable management and code organization to keep dot sourced scripts efficient, consistent and secure.
In the first part of this article series, I explained that if you are going to use dot sourcing, then it is extremely important to come up with a plan for how your various scripts will fit together. However, planning the script hierarchy is only one of several best practices. As such, I want to continue the discussion by talking about some other best practices for dot sourcing.
A second best practice is to come up with a naming convention and stick to it. Having an immutable naming convention might not be such a big deal if your script only includes a few files, but having a solid naming convention is absolutely critical if you are going to be working with large numbers of files.
As an example, the scripts that are associated with the individual tabs within my application all combine the tab name with the word tab. If for example, I had a tab called Generic, then the code for that tab would reside in a script called GenericTab. The basic GUI objects would be stored in a file called GenericGUIObjects and the schema related code would reside in a file called GenericSchema.
It's worth pointing out that my script doesn't even have a tab called Generic. Even so, because my script adheres to a rigid hierarchy and a predefined naming convention, I know exactly what the filenames would be if such a tab did exist. That's why it's so important to plan the file hierarchy and establish a naming convention before you start writing code.
While I am on the subject of naming conventions, it's important to adopt a naming convention for variables and not just for scripts. As you may recall, when you use dot sourcing to open a script, that script operates in the same scope as the parent script. As such, you never want to risk having a variable within a dot sourced script overwrite an unrelated variable that is located elsewhere within the script.
My solution to this was to tie the variable names to the tab names. On the Assignments tab for example, I avoided the temptation to use a variable called $Name. Otherwise, that variable could have interfered with the Name field on the Contacts tab, the Projects tab, or one of the other tabs. Instead, I used variable names such as $AssignmentName, $ContactName, or $ProjectName. This ensured that each variable could only affect a very specific area of functionality.
Another best practice is to be selective about the type of code that you place into dot sourced files. I have heard others say that dot sourced files should only be used to store reusable code and that if you wouldn't place code into a function, then that code should not go into a dot sourced file either. In my opinion, dot sourcing can take the place of a function, but it can be used in other ways as well.
As previously mentioned, I chose to move all of my GUI objects into dot sourced files. The reason why I did this is because some of my script's tabs leverage dozens of GUI objects. While I could have included the declarations within the tab scripts, I found that moving the GUI object declarations into a separate file made it so that my tab scripts only contained the logic that was associated with the tab, nothing else. This made it way easier to write and to debug the code associated with the individual tabs.
Similarly, I also chose to use separate scripts any time that I needed to open a window and perform some sort of task. As an example, if I were to click the Add button found on the Assignments tab, it would open a window where I can enter the details associated with an assignment. All of the logic associated with this Add Assignment window is stored in its own dot sourced script.
To put it another way, each script contains either logic or GUI objects, but not both. My logic scripts are all designed to do one thing and one thing only. Such a script will either provide the logic for a tab or for one specific window. This approach makes it extremely easy to know which of my 196 scripts to go to if I have a problem. It also greatly reduces the troubleshooting effort since each script performs one specific task and nothing else.
Finally, one last best practice that I want to mention is to never dot source untrusted code. Remember, the child script runs in the same scope as the parent script. As such, if you were to dot source a malicious script or a buggy script then the child script could easily disrupt the parent script.
About the Author
Brien Posey is a 22-time Microsoft MVP with decades of IT experience. As a freelance writer, Posey has written thousands of articles and contributed to several dozen books on a wide variety of IT topics. Prior to going freelance, Posey was a CIO for a national chain of hospitals and health care facilities. He has also served as a network administrator for some of the country's largest insurance companies and for the Department of Defense at Fort Knox. In addition to his continued work in IT, Posey has spent the last several years actively training as a commercial scientist-astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space. You can follow his spaceflight training on his Web site.