What's Up With Command Prefixes?
We like to say that PowerShell uses Verb-Noun naming. If we were accurate, we would say that PowerShell uses Verb-PrefixNoun naming. For instance: Get-WinEvent . WIN is a prefix for Windows. Every now and again people look at this and ask “what’s up with command prefixes ?!?”. Actually, the question usually comes from teams that are implementing Cmdlets and don’t understand why they have to use prefixes. They sometimes feel like their noun is unique or they want to own the noun or they think they may get reorganized into a different group so they are not sure what a good prefix would be (hey – is a legitimate issue for some teams – it just has nothing to do with the customer.)
Prefixes mitigate naming collisions.
Consider the case of the recent cmdlet Get-WinEvent which was developed by the Windows Diagnostics team (the same great team that brought you the super awesome W7 troubleshooting [which uses PowerShell heavily]). What would’ve happened if they’d just called it Get-Event. The PowerShell team needed to use the name Get-Event Cmdlet (I’ll explain why it doesn’t use a prefix later) so without a prefix these two Cmdlet names would collide. So what happens with a collision? Well one wins and the other loses. Specifically, last writer wins. So if you had a script that uses Get-Event, it is going to use would ever last defined that name. In other words your script will break.
(NOTE: For the record – the story is much more complicated that that. The Diag team used the name “Get-Event” first and we OKed it with them and then sometime later we got crisp about our policy for when PowerShell needs to own generic nouns and made them change it. It was an unfortunate situation and the diag team ended up “taking one for the team” and doing a bunch of extra work so that we could deliver a great customer experience. We all owe them a big THANK YOU.)
No matter what we do, naming collisions will occur so let’s talk about how you deal with that when it happens. The solution is simple, you use the full Cmdlet name. Full Cmdlet name? Yes that’s right, every Cmdlet that has a short and a full name. The names you use all day long are the short Cmdlet names. The full name Get-WinEvent is Microsoft.PowerShell.Commands.Diagnostics\Get-WinEvent. That’s right, if anyone comes along and collides with Get-WinEvent, you just go change all your scripts to use Microsoft.PowerShell.Commands.Diagnostics\Get-WinEvent. OUCH! Clearly this is an undesirable situation but at the end of the day these things happen so you have to have a solution. That said, it should be obvious why we want to avoid collisions as much as possible.
Think through the problem.
- There are lots of things that need to be named.
- Everything has to have a universally unique name. This either means a GUID or long human readable name.
- e2454d24-a4d9-4d41-b514-7b81f4257b64 vs. Microsoft.PowerShell.Commands.Diagnostics\Get-WinEvent
- You want to have short names and use them whenever possible. In other words you want to avoid having collisions that require you to use the universally unique name.
When we thought through this problem we made some guesses about how many things needed to be named. It’s been many years since we had the discussion but I believe the numbers were something like this:
- We expected there’d be hundreds of thousands of Cmdlets in the industry.
- A large customer shop might have the 30-50 thousand Cmdlets running on all machines in their enterprise.
- Any particular machine might have 1-5 thousand Cmdlets on it.
The key observation here was that we had to minimize the possibility of short names colliding on a particular machine (not a customer site or the industry).
Verb names are meant to be standard so they’re always going to collide – that’s a good thing (because it means you can guess which you want to do in your guess will be correct). So this is really an issue of increasing the Hamming Distance of noun names. Adding a 2-4 character prefix (indicating the team or product that owns the noun) in front of the noun solves this problem.
|Chance of Collision
Without a prefix
|Chance of Collision
With a prefix
|Large IT shop||Very High||Low|
NOTE: The side benefit of using prefixes is that it provides an easy way to find all the commands from a particular source. For instance, the Active Directory team chose the prefix “AD” so you can type: Get-Command *-AD* to find all their Cmdlets.
So that is the reason why we are hardcore on the guidance to use prefixes in front of your noun names.
Oh wait, I promised to tell you why PowerShell sometimes doesn’t use the prefix PS in its Cmdlets. There are three reasons for this:
- Writing the code has its privileges. :-)
- Certain nouns are going to be used all the time and PowerShell is always there (by definition) so we used our unique position to grab some names to deliver a good user experience.
- We use generic noun names whenever we provide the framework for other people to plug into.
- We used the name Get-Event because our eventing system is an extensible subsystem that anyone can plug into. Get-Event then provides a common front end to all those plugins. This is also the case for JOB, ITEM, etc
- We screwed up.
- In V2, we used the PS prefix a lot but I don’t think we were as consistent as we could have been. Certainly this was the case for V1 where there are a number of cmdlets that should have used the PS prefix. Live and learn.
But I hope this clarifies the importance of prefixing. As a community it is in your best interest to enforce this standard quite getting grief to those teams and companies that don’t adhere to it.
Jeffrey Snover [MSFT]
Visit the Windows PowerShell Team blog at: http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at: http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx