Contents of this directory is archived and no longer updated.

Наконец-то я смог выкроить время на то, чтобы написать что-нибудь ещё полезного в бложек. В последнее время я занимался весьма интересными вопросами, результатами которых я, может, как-нибудь поделюсь здесь. А может быть и не поделюсь :-)

Сегодня я постараюсь продолжить тему гайдлайнов PowerShell. Сегодня хочу поговорить о форматировании кода и проблемах именования переменных.

Форматирование

Неотформатированный код можно смело кидать в ресуклер, даже не вникая в него. Можете соглашаться, а можете и нет, но суть от этого не меняется. В принципе, PowerShell не имеет своих стандартов форматирования кода, но их можно унаследовать из IDE, как Visual Stidio. В основном это относится к разбивке сложных выражений на несколько строк и отступе от левого края. Разбивка сложных выражений проводится по таким символам, как: круглая скобка — (, квадратная скобка — [ (хотя, чаще она используется как метасимвол регулярных выражений) или фигурная скобка — {. Любые открывющиеся скобки в PowerShell являются признаком начала какой-то вложенной конструкции. И эти конструкции, если они достаточно длинные, следует располагать на новой строке. Открывающаяся скобка должна быть последним символом в текущей строке (или быть единственным символом в строке), а закрывающая скобка должна быть на отдельной строке. При этом весь код внутри конструкции должен быть отбит дополнительным табом от основного кода (т.е. не быть на одном уровне).

Заметка: олдфаги наверняка помнять 80 column rule, которое означает, что любая строка кода не должна быть длиннее 80 символов (классический размер консоли — 80 столбцов на 25 строк), а если она пытается быть длиннее — её надо разбивать на несколько строк. Плюс, это добавляет читабельности коду, потому что читать по вертикали проще, чем по горизонтали. Но это не значит, что надо строго придерживаться этого правила. Лично я считаю, что это правило можно расширить, но без фанатизма. Скажем, мне 100-110 символов кажется вполне разумным пределом.

Чувствую, что написал чушь, но ничего лучше не придумал, поэтому предлагаю пример, как делать не следует:

param ([Parameter(Mandatory = $true, Position = 0)][string]$Path,[Parameter(Mandatory = $true, Position = 1)][string]$XML)

Вот так — тоже плохо:

param ([Parameter(Mandatory = $true, Position = 0)][string]$Path,
[Parameter(Mandatory = $true, Position = 1)][string]$XML)

А хорошо будет вот так:

param (
    [Parameter(Mandatory = $true, Position = 0)]
    [string]$Path,
    [Parameter(Mandatory = $true, Position = 1)]
    [string]$XML
)

или вот так:

param 
(
    [Parameter(Mandatory = $true, Position = 0)]
    [string]$Path,
    [Parameter(Mandatory = $true, Position = 1)]
    [string]$XML
)

Как вы видите, скобки находятся на одном вертикальном уровне с основной командой, а весь вложенный код размещается на отдельных строках. В конкретном примере (param()), параметры аргументов должны располагаться на отдельной строке:

param 
(
    [ValidateSet("Bad", "Locked", "Missed", "New", "Ok", "Total", "Unknown")]
    [ValidateCount(1,7)]
    [String[]]$Show
)

Это значительно улучшает читабельность кода. Это несложное правило форматирования относится и к остальным подобным конструкциям. Например, вот кусочек кода, который что-то проверяет по условию IF и что-то делает:

if (Test-Path -LiteralPath $path) {Set-Location -LiteralPath $path
if ($pwd.Provider.Name -ne "FileSystem") {Set-Location $oldpath; throw "Specified path is not filesystem path. Try again!"}}
else {throw "Specified path not found. Try again!"}

Здесь мы видим небольшую кашицу, где не очень понятно где начинается конструкция, а где заканчивается. Если немного раскидать код, можно получить такое форматирование:

if (Test-Path -LiteralPath $path) {
    Set-Location -LiteralPath $path
    if ($pwd.Provider.Name -ne "FileSystem") {
        Set-Location $oldpath
        throw "Specified path is not filesystem path. Try again!"
    }
} else {
    throw "Specified path not found. Try again!"
}

или Visual Studio-стайл:

if (Test-Path -LiteralPath $path) 
{
    Set-Location -LiteralPath $path
    if ($pwd.Provider.Name -ne "FileSystem") 
    {
        Set-Location $oldpath
        throw "Specified path is not filesystem path. Try again!"
    }
} 
else
{
    throw "Specified path not found. Try again!"
}

В обоих последних примерах можно уже точно сказать что к чему относится. Или вызов методов .NET:

[Security.Cryptography.X509Certificates.X509Certificate2UI]::SelectFromCollection(
    $certs,
    "Select a certificate",
    "Select a certificate or certificates from the list",
    "MultiSelection"
)

красиво и понятно. В отдельных случаях можно и не разбивать простые конструкции на несколько строк:

if ($a % 2) {$true} else {$false}

Для пользователей PowerShell Plus, в редакторе доступна встроенный автоформат кода. Т.е. набираете код так, как вам нравится, а потом автоформат форматирует как нужно.

Если у вас есть ещё какие-то соображения относительно форматирования, я не прочь их прочитать в комментариях. Так же, можете помочь с какими-то формулировками, потому что мои мне кажутся не самыми лучшими.

Именование переменных

Через мои руки прошло не мало сторонних скриптов и заметил несколько особенностей в именовании переменных. Если быть точнее, то всего 2.

  • Префиксы

Очень много скриптов было портировано с VBS и переменные тоже унаследовали вбсную аттрибутику — префикс, означающий тип данных. Например, $strPath или $colServers или что-то типа $objWMI. Я не говорю, что так делать плохо, но с другой стороны я не рекомендую так делать, ибо незачем. В PowerShell переменные могут хранить любой тип данных. Причём, типы в переменной могут меняться. Если вы хотите ограничить переменную каким-то определённым типом — ограничивайте так:

[string]$Path, [String[]]$Servers, [int]$Numbers

никаких префиксов не надо и вы видите, какой тип данных хранится в переменных.

  • Однобуквенные переменные

Начинающие и/или просто малоопытные администраторы начинают с самых простых скриптов и зачастую экономят на названиях перменных. Например:

$a = C:\
$b = dir $a\*.mp3
$c = d:\
copy $b -D $c

Названия переменных должны отражать свою суть, т.е. что в переменной хранится. Не бойтесь использовать даже длинные переменные (в пределах разумного, естественно). Например, переменная, содержащая файлы, которые надо куда-то добавить, может называться $FilesToBeAdded. Всё очень просто :-)


Share this article:

Comments:

artem

Не помню, кидал ли я тебе эту ссылку, но если нет — настоятельно рекомендую прочитать. Особенно в контексте сегодняшнего поста. http://www.joelonsoftware.com/articles/Wrong.html В частности, она объясняет, откуда взялась мода на $strPath или $colServers, и почему это негодно (хинт: не потому, что переменная может иметь любой тип).

Vadims Podāns

неа, не давал. Почитал, открыл для себя много нового :)

Oleg Krylov

http://www.amazon.com/gp/search?index=books&linkCode=qs&keywords=1430209879 Почитай еще - откроешь еще больше :) P.S. Ну вот откуда Патриарше всё-всё знает, а?

Pavel Nagaev

Блин, наконец-то дождался. В общем-то все понятно, про переменные. Мне удобно все же добавлять префикс, чтобы было понятно, что это мои переменные, а не какие-нибудь системные. VS Style нравится больше.

Comments are closed.