Some food for thought on designing and building PowerShell CmdLets.
The PowerShell team has done a good job of attempting to define some basic standards for us to follow when building CmdLets. They have even pushed these standards into the design tools in the SDK. We can choose to browse and select from any of the Verb categories that have been pre-defined.
Is this enough?
I see that many PowerShell users are designing scripts and functions that attempt to enforce the Verb-Noun requirement.; I am not sure this was what the PS team had in mind.
It is my strong belief that, by using the Verb-Noun nomenclature in functions and scripts, we will clutter up the basic PS environment.
Why would this happen?
PowerShell CmdLets have basic guidelines for deployment. Among these guidelines are the necessity of providing ‘Help” support via an XML file, “HelpMessage” support for properties, support for required default behaviors and more.
Designing a function called Get-ComputerUser looks nice and “Power Shelly” but it is a function masquerading as a CmdLet. It will never have complete internal support by the PowerShell runtime because it can’t be completely hooked into the shell.
PowerShell CmdLets are NET objects that are intended to extend the shell in significant ways. Functions are not truly NET objects even if they are managed as objects by PowerShell. They are not “hooked” into the runtime in the same ways as a CmdLet.
The idea of using a Verb-Noun nomenclature comes from areas of formal system design. The intention is to make the use of the function, CmdLet, procedure or script more obvious to the user. It is also a way of reminding the designer that a procedure should have an action-object relation to the system.
This can be used for functions as well as CmdLets but in PowerShell the use of the Verb then the “dash” then the Noun should be reserved for CmdLets to avoid confusion.
A function can be named in the action-object mode by using the verb and noun without the dash and naming the function in Pascal Case which is a recommendation of the PowerShell team. Instead of:
function Get-ComputerUser ()
function GetComputerUser ()
This same naming rule should be applied to scripts also.
About what a PowerShell CmdLet should be used for.
When should we build a separate PowerShell CmdLet? Should we build one whenever we are using the same thing over and over in script? Isn’t that what functions and script files are for?
So if functions and script file can do this and so many other things what are CmdLets for anyway?
Looking at the PowerShell built-in CmdLets it is somewhat clear that these CmdLets perform global tasks. They are divided up into functional areas defined by their verb category. Here is a list of verb categories currently used in PowerShell.
PowerShell Verb Categories
Add, Clear, Copy, Get, Join, Lock, Move, New, Remove, Rename, Select, Set, Split, Unlock
Connect, Disconnect, Read, Receive, Send, Write
Backup, Checkpoint, Compare, Convert, ConvertFrom, ConvertTo, Dismount, Export, Import, Initialize, Limit, Merge, Mount, Restore, Update, Quit
Debug, Measure, Ping, Resolve, Test, Trace
Disable, Enable, Install, Restart, Resume, Start, Stop, Suspend, Uninstall
Block, Grant, Revoke, Unblock
The full list with rules is at: Cmdlet Verb Names
These categories are a very good start to providing a clue as to what the designers have in mind for PowerShell. They seem to have covered most of our needs for CmdLet design. It is also useful to note that this list took some time to develop. Many from the user community were consulted during the beta phase of PowerShell. Blogs by the PowerShell team indicate that they believe that this is a near complete set of categories. It may well be as it seems to follow very closely after the System Model for Windows or for most other systems for that matter.
PowerShell Object Naming Conventions
It seems pretty clear that these verbs are being selected because they provide a common ground for admin users to work from. By knowing the verb-set it should be much easier for an admin to discover what CmdLets are available. To find out how to export data, just typing “help export”. This will create a list of all installed CmdLets that support exporting data. It also allows a user to find help on the particular export CmdLet. None of this is available if the user is using a function called “export-mydata” which may cause the user to become frustrated. However, if the user is using ExportMyData and knows the basic rules of PowerShell he/she will not expect to find help on the command since it is clear that it must be a function or script.
Of course there is always flexibility in all rules so there are reasons why we might name a function with the ver-noun convention; but that's another, future, issue.
PowerShell CmdLet Functionality
The question of what functionality a PowerShell CmdLet should, at minimum, have, is one that I expect will provoke many discussions. This is not intuitive and can have many approaches and answers. It is also an area that should be considered to some degree before choosing to use a custom CmdLet as a solution.
Issues that are immediately on the table:
Does the proposed CmdLet
- abstract functionality sufficiently beyond what can be done with a simple function?
- support all potential uses in a pipeline.
- understand potential input object candidates
- simplify the development of administrative scripts
- flatten the learning curve for the administrator
These are off the top of my head and are tabled as seeds for future discussion.
PowerShell Required and Recommended Elements
The PowerShell Team has put together a set of lists of required and suggested elements to be supported by all CmdLets. Any design must take these into account before a proposed CmdLet can be completed. How to support these requirements needs to be fully discussed both in the abstract and for the specific CmdLet being considered. .
In the coming months I am hoping to see many blogs tackle this issue. There are many interesting and complex questions that these requirements pose. Let’s find these questions and start listing the possible answers to them.
I am hoping for is something like I have seen from MOW, ThePowerShellGuy, MOW, on his blog, has taken to breaking down each and every piece of the PowerShell environment - in the open and in the raw.
The PowerShell Team Blog has also addressed some of these issues over the last year but they have not done an exhaustive treatment of the subject(s).
The above may, at times, may be a little wordy and, possibly, not ideally worded. I hope that anyone finding this vague, confusing or incorrect will leave a comment or criticism before I attempt the second part of this issue.
This next part may be my undoing as I am going to try and give concrete examples of some of the issues I have presented here. I am hoping that, with these examples, I will be able to clarify for myself and others just what needs to be minimally established for the successful design of a PowerShell CmdLet.