Π€ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ Powershell с классами β€” Π½Π΅ ΠΎΠΊΡΡŽΠΌΠΎΡ€ΠΎΠ½, я Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΡŽ это

ΠŸΡ€ΠΈΠ²Π΅Ρ‚, Π₯Π°Π±Ρ€! ΠŸΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽ Π²Π°ΡˆΠ΅ΠΌΡƒ вниманию ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄ ΡΡ‚Π°Ρ‚ΡŒΠΈ "Functional PowerShell with Classes.
I promise it’s not an oxymoron"
Π°Π²Ρ‚ΠΎΡ€Π° Christopher Kuech.

ΠžΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎ-ориСнтированная ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Π°Ρ ΠΏΠ°Ρ€Π°Π΄ΠΈΠ³ΠΌΡ‹ программирования ΠΌΠΎΠ³ΡƒΡ‚ ΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ Π½Π΅ Π² Π»Π°Π΄Π°Ρ… Π΄Ρ€ΡƒΠ³ с Π΄Ρ€ΡƒΠ³ΠΎΠΌ, Π½ΠΎ ΠΎΠ±Π΅ Π² Ρ€Π°Π²Π½ΠΎΠΉ ΠΌΠ΅Ρ€Π΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ΡΡ Π² Powershell. ΠŸΡ€Π°ΠΊΡ‚ΠΈΡ‡Π΅ΡΠΊΠΈ всС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹Π΅ языки, Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΈ Π½Π΅Ρ‚, ΠΈΠΌΠ΅ΡŽΡ‚ срСдства Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½Π½ΠΎΠ³ΠΎ связывания ΠΈΠΌΡ‘Π½ ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ; ΠšΠ»Π°ΡΡΡ‹, ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ struct-Π°ΠΌ ΠΈ record-Π°ΠΌ, это всСго лишь ΠΎΠ΄ΠΈΠ½ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄. Если ΠΌΡ‹ ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΠΌ использованиС Классов связываниСм ΠΈΠΌΡ‘Π½ ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ ΠΈ станСм ΠΈΠ·Π±Π΅Π³Π°Ρ‚ΡŒ Ρ‚Π°ΠΊΠΈΡ… "тяТёлых" ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎ-ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ… ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹Ρ… ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΠΉ, ΠΊΠ°ΠΊ наслСдованиС, ΠΏΠΎΠ»ΠΈΠΌΠΎΡ€Ρ„ΠΈΠ·ΠΌ, ΠΈΠ»ΠΈ ΠΈΠ·ΠΌΠ΅Π½ΡΠ΅ΠΌΠΎΡΡ‚ΡŒ (mutability), ΠΌΡ‹ смоТСм ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡ… прСимущСства, Π½Π΅ услоТняя наш ΠΊΠΎΠ΄. Π”Π°Π»Π΅Π΅, добавляя нСизмСняСмыС (immutable) ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ прСобразования Ρ‚ΠΈΠΏΠΎΠ², ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΎΠ±ΠΎΠ³Π°Ρ‚ΠΈΡ‚ΡŒ Классами наш Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠΎΠ΄.

Магия кастов

ΠšΠ°ΡΡ‚Ρ‹ ΠΎΠ΄Π½Π° ΠΈΠ· самых ΠΌΠΎΡ‰Π½Ρ‹Ρ… Ρ„ΠΈΡ‡ Π² Powershell. Когда Π²Ρ‹ ΠΏΠΎΠ΄Π²Π΅Ρ€Π³Π°Π΅Ρ‚Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ касту, Π²Ρ‹ ΠΏΠΎΠ»Π°Π³Π°Π΅Ρ‚Π΅ΡΡŒ Π½Π° Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌΡƒΡŽ срСдой Π² вашС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ нСявных ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΈ Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ. НапримСр, простой каст строки Π² [xml] ΠΏΡ€ΠΎΠ³ΠΎΠ½ΠΈΡ‚ Π΅Ρ‘ Ρ‡Π΅Ρ€Π΅Π· ΠΊΠΎΠ΄ парсСра ΠΈ сгСнСрируСт ΠΏΠΎΠ»Π½ΠΎΠ΅ Π΄Π΅Ρ€Π΅Π²ΠΎ xml. ΠœΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π² своём ΠΊΠΎΠ΄Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠšΠ»Π°ΡΡΡ‹ с Ρ‚ΠΎΠΉ ΠΆΠ΅ Ρ†Π΅Π»ΡŒΡŽ.

ΠšΠ°ΡΡ‚ Ρ…ΡΡˆΡ‚Π°Π±Π»ΠΈΡ†

Если Ρƒ вас Π½Π΅Ρ‚ конструктора, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Ρ‚ΡŒ ΠΈ дальшС Π±Π΅Π· Π½Π΅Π³ΠΎ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ каст Ρ…ΡΡˆΡ‚Π°Π±Π»ΠΈΡ†Ρ‹ Π² Ρ‚ΠΈΠΏ вашСго класса. НС Π·Π°Π±ΡƒΠ΄ΡŒΡ‚Π΅ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π°ΠΌΠΈ Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π² ΠΏΠΎΠ»Π½ΠΎΠΉ ΠΌΠ΅Ρ€Π΅ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ этим ΠΏΠ°Ρ‚Ρ‚Π΅Ρ€Π½ΠΎΠΌ. Π—Π°ΠΎΠ΄Π½ΠΎ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΈΠΏΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ свойства класса, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Π΅Ρ‰Ρ‘ Π±ΠΎΠ»Π΅Π΅ Π³Π»ΡƒΠ±ΠΎΠΊΡƒΡŽ Π»ΠΎΠ³ΠΈΠΊΡƒ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΈ Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈΠΈ.

class Cluster {
    [ValidatePattern("^[A-z]+$")]
    [string] $Service
    [ValidateSet("TEST", "STAGE", "CANARY", "PROD")]
    [string] $FlightingRing
    [ValidateSet("EastUS", "WestUS", "NorthEurope")]
    [string] $Region
    [ValidateRange(0, 255)]
    [int] $Index
}

[Cluster]@{
    Service       = "MyService"
    FlightingRing = "PROD"
    Region        = "EastUS"
    Index         = 2
}

ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, каст ΠΏΠΎΠΌΠΎΠ³Π°Π΅Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ чистый Π²Ρ‹Π²ΠΎΠ΄. Π‘Ρ€Π°Π²Π½ΠΈΡ‚Π΅ Π²Ρ‹Π²ΠΎΠ΄ массива Ρ…ΡΡˆΡ‚Π°Π±Π»ΠΈΡ† Cluster ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½Ρ‹ΠΉ Π² Format-Table c Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ получится, Ссли ΠΏΡ€Π΅ΠΆΠ΄Π΅ ΠΊΠ°ΡΡ‚ΠΎΠ²Π°Ρ‚ΡŒ эти Ρ…ΡΡˆΡ‚Π°Π±Π»ΠΈΡ†Ρ‹ Π² класс. Бвойства класса всСгда ΠΏΠ΅Ρ€Π΅Ρ‡ΠΈΡΠ»ΡΡŽΡ‚ΡΡ Π² Ρ‚ΠΎΠΌ порядкС, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΠΎΠ½ΠΈ Ρ‚Π°ΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Ρ‹. НС Π·Π°Π±ΡƒΠ΄ΡŒΡ‚Π΅ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ΅ слово hidden ΠΏΠ΅Ρ€Π΅Π΄ всСми Ρ‚Π΅ΠΌΠΈ свойствами, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ Π²ΠΈΠ΄Π½Ρ‹ Π² Π²Ρ‹Π΄Π°Ρ‡Π΅.

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ Powershell с классами — Π½Π΅ ΠΎΠΊΡΡŽΠΌΠΎΡ€ΠΎΠ½, я Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΡŽ это

ΠšΠ°ΡΡ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ

Если Ρƒ вас Π΅ΡΡ‚ΡŒ конструктор с ΠΎΠ΄Π½ΠΈΠΌ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠΌ, каст значСния ΠΊ Π²Π°ΡˆΠ΅ΠΌΡƒ Ρ‚ΠΈΠΏΡƒ класса пСрСдаст Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ этому Π²Π°ΡˆΠ΅ΠΌΡƒ конструктору, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ инстанс вашСго класса

class Cluster {
    [ValidatePattern("^[A-z]+$")]
    [string] $Service
    [ValidateSet("TEST", "STAGE", "CANARY", "PROD")]
    [string] $FlightingRing
    [ValidateSet("EastUS", "WestUS", "NorthEurope")]
    [string] $Region
    [ValidateRange(0, 255)]
    [int] $Index

    Cluster([string] $id) {
        $this.Service, $this.FlightingRing, $this.Region, $this.Index = $id -split "-"
    }
}

[Cluster]"MyService-PROD-EastUS-2"

ΠšΠ°ΡΡ‚ ΠΊ строкС

Π’Π°ΠΊΠΆΠ΅ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄ класса [string] ToString(), Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ Π»ΠΎΠ³ΠΈΠΊΡƒ строкового прСдставлСния ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΠΎΠ»ΡΡ†ΠΈΡŽ строк.

class Cluster {
    [ValidatePattern("^[A-z]+$")]
    [string] $Service
    [ValidateSet("TEST", "STAGE", "CANARY", "PROD")]
    [string] $FlightingRing
    [ValidateSet("EastUS", "WestUS", "NorthEurope")]
    [string] $Region
    [ValidateRange(0, 255)]
    [int] $Index

    [string] ToString() {
        return $this.Service, $this.FlightingRing, $this.Region, $this.Index -join "-"
    }
}

$cluster = [Cluster]@{
    Service       = "MyService"
    FlightingRing = "PROD"
    Region        = "EastUS"
    Index         = 2
}

Write-Host "We just created a model for '$cluster'"

ΠšΠ°ΡΡ‚ сСриализованных инстансов

ΠšΠ°ΡΡ‚ позволяСт Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΡƒΡŽ Π΄Π΅ΡΠ΅Ρ€ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ. ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Π½ΠΈΠΆΠ΅ Π·Π°Π²Π΅Ρ€ΡˆΠ°Ρ‚ΡΡ ошибкой, Ссли Π΄Π°Π½Π½Ρ‹Π΅ Π½Π΅ ΠΎΡ‚Π²Π΅Ρ‡Π°ΡŽΡ‚ нашСй спСцификации Π² Cluster

# Валидация сСриализованных Π΄Π°Π½Π½Ρ‹Ρ…

[Cluster]$cluster = Get-Content "./my-cluster.json" | ConvertFrom-Json
[Cluster[]]$clusters = Import-Csv "./my-clusters.csv"

ΠšΠ°ΡΡ‚Ρ‹ Π² вашСм Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΠΌ ΠΊΠΎΠ΄Π΅

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ сначала ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‚ структуры Π΄Π°Π½Π½Ρ‹Ρ…, Π·Π°Ρ‚Π΅ΠΌ ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½Ρ‚ΠΈΡ€ΡƒΡŽΡ‚ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ ΠΊΠ°ΠΊ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ трансформаций Π½Π°Π΄ нСизмСняСмыми структурами Π΄Π°Π½Π½Ρ‹Ρ…. НСсмотря Π½Π° ΠΏΡ€ΠΎΡ‚ΠΈΠ²ΠΎΡ€Π΅Ρ‡ΠΈΠ²ΠΎΠ΅ Π²ΠΏΠ΅Ρ‡Π°Ρ‚Π»Π΅Π½ΠΈΠ΅, классы Ρ€Π΅Π°Π»ΡŒΠ½ΠΎ ΠΏΠΎΠΌΠΎΠ³Π°ΡŽΡ‚ ΠΏΠΈΡΠ°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠΎΠ΄, благодаря ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌ ΠΊΠΎΠ½Π²Π΅Ρ€Ρ‚Π°Ρ†ΠΈΠΈ Ρ‚ΠΈΠΏΠΎΠ².

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ Π»ΠΈ Powershell я ΠΏΠΈΡˆΡƒ?

Много людСй ΠΏΡ€ΠΈΡˆΠ΅Π΄ΡˆΠΈΡ… ΠΈΠ· C# ΠΈΠ»ΠΈ с ΠΏΠΎΠ΄ΠΎΠ±Π½Ρ‹ΠΌ ΠΏΡ€ΠΎΡˆΠ»Ρ‹ΠΌ ΠΏΠΈΡˆΡƒΡ‚ Powershell, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠΎΡ…ΠΎΠΆ Π½Π° Π‘#. ΠŸΠΎΡΡ‚ΡƒΠΏΠ°Ρ Ρ‚Π°ΠΊ, Π²Ρ‹ ΠΎΡ‚ΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚Π΅ΡΡŒ ΠΎΡ‚ использования ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ программирования ΠΈ, вСроятно, ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ ΠΏΠΎΠ»ΡŒΠ·Ρƒ усилСнно ΠΏΠΎΠ³Ρ€ΡƒΠ·ΠΈΠ²ΡˆΠΈΡΡŒ Π² ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎ-ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π² Powershell ΠΈΠ»ΠΈ Π»ΡƒΡ‡ΡˆΠ΅ ΠΈΠ·ΡƒΡ‡ΠΈΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅.

Если Π²Ρ‹ Π³Π»ΡƒΠ±ΠΎΠΊΠΎ ΠΏΠΎΠ»Π°Π³Π°Π΅Ρ‚Π΅ΡΡŒ Π½Π° Ρ‚Ρ€Π°Π½ΡΡ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΈΠΌΠΌΡƒΡ‚Π°Π±Π΅Π»ΡŒΠ½Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ…, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Ρ‹ (|), Where-Object, ForEach-Object, Select-Object, Group-Object, Sort-Object ΠΈ Ρ‚. Π΄. β€” Ρƒ вас Π±ΠΎΠ»Π΅Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ ΡΡ‚ΠΈΠ»ΡŒ, ΠΈ Π²Π°ΠΌ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ использованиС классов Powershell Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΠΌ стилС.

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΠ΅ использованиС классов

ΠšΠ°ΡΡ‚Ρ‹, хотя ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π½Ρ‹ΠΉ синтаксис, всСго лишь ΠΌΠ°ΠΏΠΏΠΈΠ½Π³ ΠΌΠ΅ΠΆΠ΄Ρƒ двумя Π΄ΠΎΠΌΠ΅Π½Π°ΠΌΠΈ. Π’ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π΅ ΠΌΠΎΠΆΠ½ΠΎ ΡΠΌΠ°ΠΏΠΈΡ‚ΡŒ массив Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ForEach-Object.

Π’ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ Π½ΠΈΠΆΠ΅ конструктор Node исполняСтся ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π· ΠΊΠΎΠ³Π΄Π° происходит каст ΠΊ Datum, ΠΈ это Π΄Π°Ρ‘Ρ‚ Π½Π°ΠΌ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π½Π΅ ΠΏΠΈΡΠ°Ρ‚ΡŒ изрядноС количСство ΠΊΠΎΠ΄Π°. Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ наш ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€ фокусируСтся Π½Π° Π΄Π΅ΠΊΠ»Π°Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΎΠΌ запросС Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ Π°Π³Ρ€Π΅Π³Π°Ρ†ΠΈΠΈ, Π² Ρ‚ΠΎ врСмя ΠΊΠ°ΠΊ наши классы Π±Π΅Ρ€ΡƒΡ‚ Π½Π° сСбя парсинг Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΡŽ.

# ΠŸΡ€ΠΈΠΌΠ΅Ρ€ комбинирования классов с ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π°ΠΌΠΈ для separation of concerns Π² ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π°Ρ…

class Node {
    [ValidateLength(3, 7)]
    [string] $Name
    [ValidateSet("INT", "PPE", "PROD")]
    [string] $FlightingRing
    [ValidateSet("EastUS", "WestUS", "NorthEurope", "WestEurope")]
    [string] $Region
    Node([string] $Name) {
        $Name -match "([a-z]+)(INT|PPE|PROD)([a-z]+)"
        $_, $this.Service, $this.FlightingRing, $this.Region = $Matches
        $this.Name = $Name
    }
}

class Datum {
    [string] $Name
    [int] $Value
    [Node] $Computer
    [int] Severity() {
        $this.Name -match "[0-9]+$"
        return $Matches[0]
    }
}

Write-Host "Urgent Security Audit Issues:"
Import-Csv "./audit-results.csv" `
    | ForEach-Object {[Datum]$_} `
    | Where-Object Value -gt 0 `
    | Group-Object {$_.Severity()} `
    | Where-Object Name -lt 2 `
    | ForEach-Object Group `
    | ForEach-Object Computer `
    | Where-Object FlightingRing -eq "PROD" `
    | Sort-Object Name, Region -Unique

Π£ΠΏΠ°ΠΊΠΎΠ²ΠΊΠ° класса для ΠΏΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½ΠΈΡ

Ничто Π½Π΅ ΡΡ‚ΠΎΠ»ΡŒ ΡƒΠΆ Ρ…ΠΎΡ€ΠΎΡˆΠΎ, ΠΊΠ°ΠΊ каТСтся

К соТалСнию, классы Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ экспортированы модулями Ρ‚Π΅ΠΌ ΠΆΠ΅ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, ΠΊΠ°ΠΊ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈΠ»ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅; Π½ΠΎ хитрости ΠΊΠΎΠ΅-ΠΊΠ°ΠΊΠΈΠ΅ Π΅ΡΡ‚ΡŒ. Допустим, ваши классы ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Ρ‹ Π² Ρ„Π°ΠΉΠ»Π΅ ./my-classes.ps1

  • Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ дотсорсинг Ρ„Π°ΠΉΠ»Π° с классами:. ./my-classes.ps1. Π­Ρ‚ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ my-classes.ps1 Π² вашСй Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ области видимости ΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ Ρ‚Π°ΠΌ всС классы ΠΈΠ· Ρ„Π°ΠΉΠ»Π°.

  • Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ Powershell, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ экспортируСт всС ваши ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠ΅ API (ΠΊΠΎΠΌΠ°Π½Π΄Π»Π΅Ρ‚Ρ‹) ΠΈ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ ScriptsToProcess = "./my-classes.ps1" Π² манифСстС вашСго модуля, с Ρ‚Π΅ΠΌ ΠΆΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ: ./my-classes.ps1 выполнится Π² вашСм ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠΈ.

Какой Π±Ρ‹ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ Π²Ρ‹ Π½ΠΈ Π²Ρ‹Π±Ρ€Π°Π»ΠΈ, Π½Π΅ Π·Π°Π±Ρ‹Π²Π°ΠΉΡ‚Π΅, Ρ‡Ρ‚ΠΎ систСма Ρ‚ΠΈΠΏΠΎΠ² Powershell Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Ρ€Π°Π·Ρ€ΡƒΠ»ΠΈΡ‚ΡŒ ΠΎΠ΄Π½ΠΎΠΈΠΌΡ‘Π½Π½Ρ‹Π΅ Ρ‚ΠΈΠΏΡ‹, Π·Π°Π³Ρ€ΡƒΠΆΠ΅Π½Π½Ρ‹Π΅ ΠΈΠ· Ρ€Π°Π·Π½Ρ‹Ρ… мСст.
Π”Π°ΠΆΠ΅ Ссли Π²Ρ‹ Π·Π°Π³Ρ€ΡƒΠ·ΠΈΠ»ΠΈ ΠΈΠ· Ρ€Π°Π·Π½Ρ‹Ρ… мСст Π΄Π²Π° ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ‡Π½Ρ‹Ρ… класса с ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹ΠΌΠΈ свойствами, Π²Ρ‹ рискуСтС Π½Π°Ρ€Π²Π°Ρ‚ΡŒΡΡ Π½Π° ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹.

ΠŸΡƒΡ‚ΡŒ Π²ΠΏΠ΅Ρ€Π΅Π΄

Π›ΡƒΡ‡ΡˆΠΈΠΉ способ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ с Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ΠΌ Ρ‚ΠΈΠΏΠΎΠ² β€” Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ Π²Ρ‹ΡΡ‚Π°Π²Π»ΡΡ‚ΡŒ для ΡŽΠ·Π΅Ρ€ΠΎΠ² ваши классы. ВмСсто Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠΆΠΈΠ΄Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΡŽΠ·Π΅Ρ€ ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½Π½Ρ‹ΠΉ Π² классС Ρ‚ΠΈΠΏ, экспортируйтС ΠΈΠ· вашСго модуля Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, которая освобоТдаСт ΠΎΡ‚ нСобходимости Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ ΠΎΠ±Ρ€Π°Ρ‰Π°Ρ‚ΡŒΡΡ ΠΊ классу. ΠŸΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΊ Cluster, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΡΠΊΡΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ New-Cluster, которая ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΡ‚ друТСствСнныС ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŽ Π½Π°Π±ΠΎΡ€Ρ‹ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² ΠΈ Π²Π΅Ρ€Π½Ρ‘Ρ‚ Cluster.

class Cluster {
    [ValidatePattern("^[A-z]+$")]
    [string] $Service
    [ValidateSet("TEST", "STAGE", "CANARY", "PROD")]
    [string] $FlightingRing
    [ValidateSet("EastUS", "WestUS", "NorthEurope")]
    [string] $Region
    [ValidateRange(0, 255)]
    [int] $Index
}

function New-Cluster {
    [OutputType([Cluster])]
    Param(
        [Parameter(Mandatory, ParameterSetName = "Id", Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string] $Id,
        [Parameter(Mandatory, ParameterSetName = "Components")]
        [string] $Service,
        [Parameter(Mandatory, ParameterSetName = "Components")]
        [string] $FlightingRing,
        [Parameter(Mandatory, ParameterSetName = "Components")]
        [string] $Region,
        [Parameter(Mandatory, ParameterSetName = "Components")]
        [int] $Index
    )

    if ($Id) {
        $Service, $FlightingRing, $Region, $Index = $Id -split "-"
    }

    [Cluster]@{
        Service       = $Service
        FlightingRing = $FlightingRing
        Region        = $Region
        Index         = $Index
    }
}

Export-ModuleMember New-Cluster

Π§Ρ‚ΠΎ Π΅Ρ‰Ρ‘ ΠΏΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ

About Classes
Defensive PowerShell
Functional Programming in PowerShell

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com