I’ve recently talked about my learnings regarding PowerShell toolmaking and it made me realize that most of the time, I have been rewriting the same boilerplate code over and over. I don’t know for you out there but for me it gets tedious to write the same code or even copy paste the same lines. It’s error prone and it almost feels like being in detention and writing the same sentence on a blackboard.
During my first programming class at Lionel-Groulx College, Sainte-Thérèse, Canada (circa 2001), my C++ teacher, Vincent Échelard, said words that still resonate in my mind to this day: “A good programmer is a lazy programmer”. The true meaning behind that sentence was to avoid programming what has already been done. Reuse your stuff, you will save time and avoid errors down the road.
Let’s talk about code generators
Being a lazy programmer, I love what a powerful tool like Yeoman offers. It lets you interact with the user to really tailor the generated project to the programmer’s needs. With that in mind, I’ve decided to build my own generator that encapsulates unit testing and code linting philosophies for PowerShell toolmaking.
Because sharing is caring, I’ve also decided to publish the generator to npm.
Installing the generator
A Yeoman generator is nothing more than a npm package. Installing it follows the same logic. To install Yeoman, and the generator, you need to run the following commands from a Shell.
npm install -g yo npm install -g generator-psmodule
Using the generator
First create an empty directory which will be used to generate the PowerShell module. From that directory let’s invoke the generator by running the following command:
If Yeoman and the generator are installed properly, you should get the following results:
Great! Now the generator will ask 3 questions before generating the module’s skeleton.
- The module’s name (defaulted to the current working directory)
- The module’s author
- The module’s description
And voilà! A basic PowerShell module properly configured and ready to be developed into several logical unit. From the following screenshot we can, at first glance, see that the first answer is used to name and template some of the files.
Diving into the generated module
The first thing to check out is the module’s manifest file. Within, we can see that the answers provided to the generator helped templating the file.
Sources organization philosophy
Coming from a strong C# background, I really like the “class based” architecture approach. Meaning that a source file, or I like calling them logical units, is an entity of its own without the Verb-Noun syntax. Within that unit, it’s a whole different story. The idea is to enforce proper scoping, in a public/private way for encapsulation and use the Verb-Noun syntax. For a list of supported verbs refer to the Get-Verb cmdlet. You can use your own verbs but for consistency, I prefer using the standard verbs.
Here is the example that can be found from the generated module:
I leverage the test setup provided by Pester to properly configure the environment for the logical unit under test.
- Setting the location of the script execution path. I’ve learned that it’s easier to refer to file system paths that are relative to the execution context later on.
- The actual sourcing of the logical unit under test.
- Using the Pester’s TestDrive to setup any test data that will be accessed from a test.
For each context block, specific test context can be applied:
Publishing your module
The generator also provides a mechanism to publish the module to the PowerShell gallery. I’ve already covered how to achieve this task here. Have a look at the Publish-psdawg.ps1 script.
Generators can be real time savers, and I strongly encourage you guys to keep in mind the KISS principle (Keep it simple and stupid) while doing so. A dumb generator doesn’t cost a whole lot of maintenance on your team and is easy to understand when it comes to additional functionalities.
The project’s github repository is public and you are more than welcome to submit your ideas or participate on its development.
The strength of a network, the power of a community!