The Struggles of Module Development


The last few months I’ve been working a lot on making PowerShell Modules for internal tooling and solutions that will be used mainly by others or automation solutions.

During that time, I’ve encountered some challenges/struggles that I would like to expand a bit about and if interesting enough for others, devote specific posts about explaining how I had tackled these struggles and where I am currently in the process.

Not every solution has to immediately be a module.
Personally when I think of ‘module’, I think of ‘reusable’ and ‘generic’.

Modules shouldn’t just fit YOUR usecase, it should be usable in all kinds of scenarios.

Which immediately means that it’s just fine if some scripts stay scripts.

But once you start creating a few functions which have the same use case, you might want to look at converting them from separate scripts/functions to a module.
Or perhaps you have a few ‘helper’ functions that you always reference in scripts (functions for logs or other common tasks), you might be best off making a module for all your helper functions so you can reference them in all your scripts.

This way you don’t need to update all references if a script has a feature added or bug fixed.

Some things just sound stupid at first… why should I care what I call my module?
Well, perhaps there’s multiple modules out there which have the same or similar functionality or usecases.
Or perhaps you want to (or have to) use a (company) prefix for your module.

Take for example a PowerShell module for working with GitHub.
You can call it GitHub, or what about PS-GitHub?

Looking at the PowerShell Gallery, you might not be the first one with this brilliant idea…

GitHub modules

In these cases you might want to start looking at those prefixes again.

Something that might also be worth looking at, if you start making multiple modules:

  • Do you always use the same prefix
  • How do you seperate the prefix from the module name, do you use - or . or just everything together without spaces?

Small things to think about and luckily they can be changed in hindsight, but the more you work on modules, the more you want to think about this upfront.

I’ve devoted some previous blog posts on this subject before (here and here), but this issue will help a lot when working in a team.

Instead of having modules have random file and folder structure and setup, you’re best off using one of the scaffolding tools to make sure your modules are always the same. It really doesn’t matter which tool you use or even if you do it by hand (but please don’t do it by hand…), just make sure your modules are consistent!

The better you are at scaffolding (or using a premade tool), the easier it will be to immediately tackle some of the other issues such as build scripts, versioning and testing.

Are you going to place each function of your module in a separate file, or perhaps place them all in a single file for performance? What about helper functions, are they going to be private or publicly available to use?
These are things to think about when designing your module structure.

This is definitely something I will dedicate a separate blogpost to…(and I’ll be sure to link that post here in the future 😉).

Like all the other subjects in this post, at first versioning might seem be very simple.
You update your module, you update the version.

But where do you start? Do you start with v0.1, 0.0.1, 0.0.1-prerelease001, 1.0.0? How do you increment?

Do you use something like Semantic Versioning?
Do you want more manual control about how and when you increment or do you want to look at automating the process?

To be honest, this is still a bit of a struggle for me, as there are so many manual options, but also a few automated solutions such as based on current PSGallery version or using GitVersion.
Specifically those automated solutions really require you to KNOW what you want, what system you’re using and how this acts when, for example, merging branches (think Azure DevOps vs GitHub vs GitLab etc).

Emrys MacInally had a great talk about this at PSConfEU 2024 which you can find here on YouTube.
And for those not wanting to watch a video, he also has a blogpost where he writes about this in depth.

Surely everybody tests their code right? ….right???

Ok, once you start with your Module development, you need to start testing your code.
And while this sounds like another learning investment you don’t want hanging over your head BEFORE you can actually start working on your module, hear me out.

While I would personally recommend diving into unit tests and integration tests using Pester, I also understand the learning curve that comes with and it’s not always feasible to work like that.
What I DO recommend is to at least do Quality Assurance (QA) testing on your module.

What I mean by that is the ‘bare minimum’ I would expect from a decent module:

  • Your module should import and remove without problems
  • Each function within your module should pass PSScriptAnalyzer tests to meet best practices.
  • Each function within your module should have ‘good’ Comment Based Help
    • Synopsis
    • Description
    • All parameters described
    • Examples

Even if this is the least you do, it will make your module all the better and it will help you make high quality modules.

While you can of course make your own tests for this, you might want to look into pre-made solutions built in to tools such as Sampler, PSModule Development and many more.
The best thing here is that you can pick and choose what YOU find important and make your own standard.

Build scripts can help you automate a lot of the earlier discussed points to make your life easier.
Automatically test your module and if successfull increment the version of your module to the latest version.

But build scripts can also do much more than that:

  • They can allow you to locally test the latest version while getting all required dependencies
  • Automatically load all your functions, cmdlets, variables and aliasses into your module .psd1 (to allow for autocompletion without having to specifically import the module).
    This can use the Export-ModuleMember (in case you weren’t familiar with this option).
  • Automatically import all functions into your .psm1 file for performance gains
  • and more…

You can again use premade tools under Sampler and PSModule Development, but there are also tools such as PSake which can help you with premade build scripts.

Last but not least, you need to make it so that people can use your modules!
This sounds like a simple choice:

Just publish your module to the PowerShell Gallery and make yourself and the community happy!
Unfortunately this isn’t always possible, especially when dealing with company specific code (intellectual property) or reasons outside of your control.

You can also create local repositories which can host your PowerShell Module(s), see it as a private PowerShell Gallery!

In my case, I’ve actually set up Azure DevOps to use an Artifacts Feed as local repository, so that I can have my build agents automatically access the updated modules right off the bat.
If there’s enough interest (or if I have spare time), I’ll devote another post on how I’ve accomplished this and what the pros and cons are to using this.

Working on PowerShell Modules can be a lot of fun (don’t let the items above discourage you!).
The more you play with it, the more I’ve noticed I’m approaching it with more of a developer mindset though.

While the points above are definitely not all required, they will help you make modules of quality and make it easier on yourself and others to contribute.

The most important thing about this all is to play around, see what options are available and see what kind of options the community have made available for you to use.

Based on my recent experiences and the challenges I’m still working through, I’m planning to dive deeper into versioning solutions first - it’s the area I’m most actively wrestling with right now.
After that, I’ll likely dedicate a post on distributing your PowerShell modules using Azure DevOps Artifacts Feeds.

In case there’s a specific subject you want me to dive deeper into for a next blogpost, please hit me up on LinkedIn and let me know!

Happy scripting and have fun! 😃