Best Practices for Script Design A PowerShell.org TechSession

Preview:

Citation preview

Best Practices forScript Design

A PowerShell.org TechSession

Remember

Find the latest TechSessions at http://powershell.org/wp/techsession-webinars/.

Advanced registration is required to attend the live events, where you can participate in Q&A

Recordings posted to YouTube, usually in 48 hours.

Today

We’ll be looking at best practices for designing scripts that best leverage PowerShell’s native patterns and capabilities.

Please submit questions to the Q&A panel as we go – I’ll address them as you submit them.

Basic Information

Level: 200-300Best practices and patterns for using complex technologies

Pre-requisites:Solid experience with Windows PowerShell scripting/programming

Scripting Goals

Ease testing and debugging

Maximize reuse

Minimize programming effort

Conform to existing shell usage patterns

Get the job done!

Tools vs. Controllers

TOOLS Do one thing and one thing only

Not tied to a specific context

Accept input only via parameters; output only via pipeline

Cmdlet-style naming

Advanced functions contained in a script module

CONTROLLERS Coordinate multiple tools to

complete a process

Tied to a specific process

May read data from files, params, databases, etc.

May not use cmdlet-style naming

Monolithic script with minimal functionality; mostly logic

Tools

Create information for use by other toolsGet-, Import-, ConvertFrom-, etc.

Process information and take actionGet-, Set-, New-, Remove-, etc.

Put raw data into a particular formExport-, ConvertTo-, Format-, Out-

Poor

Function Get-Something { [CmdletBinding()] Param( [string[]]$ComputerName, [string]$FileName ) if ($PSBoundParameters.ContainsKey('Filename')) { $ComputerName = Get-Content $FileName }}

Improved

Function Get-Something { [CmdletBinding()] Param( [Parameter(ValueFromPipeline)] [string[]]$ComputerName )}

Get-Content computers.txt | Get-Something

Get-ADComputer –filter * |Select –Expand Name |Get-Something

Poor

... $objects += $object $objects | Format-Table}

Improved

... Write-Output $object}

Do-Whatever | Format-Table

General Guidelines

If information could ever possibly come from more than one source, make dedicated tools to get it, and feed it to other tools via the pipeline or parameters.

If a tool does formatting, puts data someplace (e.g., a database), etc., then that is all the tool should do.

General Guidelines

If a tool is making any kind of change, then that is all it should do.

It should never also worry about where input came from or where output is going.

Remember: If a tool makes changes, it should support –confirm and –whatif; those can only affect one operational within the tool, so the tool should only do that one thing.

Possible Red Flags

One parameter set accepts information (like a computer name), while another accepts a source for that information (like a filename)

Any use of Get-Content

Any use of Format-, Export-, Out-, or ConvertTo- in a tool that also does other work

Controllers

Do very little work. Instead, they implement a lot of logic to decide what work to do – and call commands (tools) to do that work.

Responsible for the entire cycle of input/work/output.

Automate a process, produce a report, display a menu, etc.

These control one or more tools to do something useful. Tools may not do a completely useful thing by themselves; the controllers make that happen.

Tools vs. Controllers (Redux)

New-ADUserDoes one thing

Doesn't complete an entire process (e.g., for a new employee)

Has no idea where new user info is coming from

ProvisionEmployee.ps1

Does many things (user account, home dir, add to groups, etc.)

Has a specific source for new user info (perhaps an HR database or spreadsheet)

Uses New-ADUser internally

Goal: Testing and Debugging

Tools can be tested independently, using the same input (via parameters) a controller might use

Makes debugging simpler and more contained

Controllers do nothing, so it's easier to test their logic – especially if you've properly implemented –whatif in your tools.

Goal: Reusability

Because tools aren't tied to a specific context or use case, they're easier to reuse

Because controllers contain little to no functionality, they don't need to offer reusability

Goal: Minimize and Conform

Tools work consistently with existing shell patterns (e.g., the same as cmdlets, when you do it right)

Controllers become the traditional "glue" script that pulls tools together

Controllers can be written more quickly because they don't do complex work; they're only coordinating pre-tested, pre-existing tools

Let's See an Example

Let’s Take Some Questions

I know you’ve got ‘em… ask away.

Thank You!

Find the latest TechSessions at http://powershell.org/wp/techsession-webinars/.

Advanced registration is required to attend the live events, where you can participate in Q&A

Recordings posted to YouTube, usually in 48 hours.

Ask follow-up questions in the Forums on PowerShell.org.

Recommended