Functional Powershell með classum er ekki oxymoron, ég ábyrgist það

Hæ Habr! Ég kynni þér þýðingu greinarinnar „Virka PowerShell með flokkum.
Ég lofa að það er ekki oxymoron“
eftir Christopher Kuech

Hlutbundin og hagnýt forritunarhugmynd kann að virðast vera á skjön við hvort annað, en báðar eru jafn studdar í Powershell. Næstum öll forritunarmál, hvort sem þau eru virk eða ekki, hafa aðstöðu fyrir aukna nafngildisbindingu; Flokkar, eins og skipulag og skrár, eru aðeins ein nálgun. Ef við takmörkum notkun okkar á flokkum við bindingu nafna og gilda og forðumst þung hlutbundin forritunarhugtök eins og erfðir, fjölbreytni eða breytileiki, getum við nýtt okkur kosti þeirra án þess að flækja kóðann okkar. Ennfremur, með því að bæta við óbreytanlegum tegundumbreytingaraðferðum, getum við auðgað virkan kóða okkar með flokkum.

Galdurinn af stéttum

Kastar eru einn af öflugustu eiginleikum Powershell. Þegar þú setur gildi ertu að treysta á óbeina frumstillingar- og staðfestingargetu sem umhverfið bætir við umsókn þína. Til dæmis, einfaldlega að varpa streng í [xml] mun keyra hann í gegnum flokkunarkóðann og búa til heill XML-tré. Við getum notað Classes í kóðanum okkar í sama tilgangi.

Cast hashtöflur

Ef þú ert ekki með smið geturðu haldið áfram án þess með því að steypa hashtable í bekkjartegundina þína. Ekki gleyma að nota löggildingareiginleikana til að nýta þetta mynstur til fulls. Á sama tíma getum við notað vélritaða eiginleika flokksins til að keyra enn dýpri frumstillingar- og staðfestingarrökfræði.

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
}

Að auki hjálpar steypa til að fá hreint framtak. Berðu saman úttak Cluster hashable fylkisins sem er sent til Format-Table við það sem þú færð ef þú kastar þessum hashtables fyrst í flokk. Eiginleikar flokks eru alltaf taldir upp í þeirri röð sem þeir eru skilgreindir þar. Ekki gleyma að bæta falið leitarorði á undan öllum þeim eiginleikum sem þú vilt ekki að sjáist í niðurstöðunum.

Functional Powershell með classum er ekki oxymoron, ég ábyrgist það

Kast af merkingum

Ef þú ert með smið með einni röksemdafærslu, mun það að varpa gildi í bekkjargerðina þína senda gildið til smiðsins, þar sem þú getur frumstillt tilvik af bekknum þínum

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"

Kastið í línu

Þú getur líka hnekið [string] ToString() flokksaðferðinni til að skilgreina rökfræðina á bak við strengjaframsetningu hlutarins, eins og að nota strengjaskil.

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'"

Cast serialized tilvik

Cast gerir örugga deserialization. Dæmin hér að neðan munu mistakast ef gögnin uppfylla ekki forskrift okkar í Cluster

# Валидация сериализованных данных

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

Kastar inn virka kóðann þinn

Hagnýt forrit skilgreina fyrst gagnaskipulag, útfæra síðan forritið sem röð umbreytinga yfir óbreytanleg gagnaskipulag. Þrátt fyrir misvísandi áhrif, hjálpa flokkar þér virkilega að skrifa hagnýtan kóða þökk sé tegundumbreytingaraðferðum.

Er Powershell sem ég er að skrifa virkt?

Margir sem koma frá C# eða svipuðum bakgrunni eru að skrifa Powershell, sem er svipað og C#. Með því að gera þetta ertu að hverfa frá því að nota hagnýt forritunarhugtök og gætir líklega haft gott af því að kafa mikið í hlutbundna forritun í Powershell eða læra meira um hagnýta forritun.

Ef þú treystir þér mikið á að umbreyta óbreytanlegum gögnum með leiðslum (|), Where-Object, ForEach-Object, Select-Object, Group-Object, Sort-Object o.s.frv. - þú ert með virkari stíl og þú munt njóta góðs af því að nota Powershell bekk í hagnýtum stíl.

Hagnýt notkun flokka

Kastar, þó þeir noti aðra setningafræði, eru bara kortlagning á milli tveggja léna. Í leiðslunni geturðu kortlagt fjölda gilda með því að nota ForEach-Object.

Í dæminu hér að neðan er Node smiðurinn keyrður í hvert skipti sem Datum er varpað, og það gefur okkur tækifæri til að skrifa ekki heilmikið af kóða. Fyrir vikið beinist leiðsla okkar að yfirlýsandi gagnafyrirspurn og samansöfnun, á meðan flokkarnir okkar sjá um þáttun og staðfestingu gagna.

# Пример комбинирования классов с конвейерами для 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

Pökkunarflokkur til endurnotkunar

Ekkert er eins gott og það sýnist

Því miður er ekki hægt að flytja flokka út með einingum á sama hátt og aðgerðir eða breytur; en það eru nokkur brögð. Segjum að flokkarnir þínir séu skilgreindir í skránni ./my-classes.ps1

  • Þú getur punktað skrá með flokkum:. ./my-classes.ps1. Þetta mun keyra my-classes.ps1 í núverandi umfangi þínu og skilgreina alla flokka úr skránni þar.

  • Þú getur búið til Powershell einingu sem flytur út öll sérsniðnu API (cmdlets) og stillt ScriptsToProcess = "./my-classes.ps1" breytuna í einingaskránni þinni, með sömu niðurstöðu: ./my-classes.ps1 mun keyra í umhverfi þínu.

Hvort sem þú velur, mundu að tegundakerfi Powershell getur ekki leyst gerðir með sama nafni sem eru hlaðnar frá mismunandi stöðum.
Jafnvel þó þú hafir hlaðið tvo eins flokka með sömu eiginleika frá mismunandi stöðum, þá er hætta á að þú lendir í vandræðum.

Leiðin áfram

Besta leiðin til að forðast tegundarupplausnarvandamál er að afhjúpa aldrei bekkina þína fyrir notendum. Í stað þess að búast við því að notandinn flytji inn flokkaskilgreinda tegund, flyttu út fall úr einingunni þinni sem útilokar þörfina á að fá aðgang að bekknum beint. Fyrir Cluster getum við flutt út New-Cluster aðgerð sem mun styðja notendavæn færibreytusett og skila 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

Hvað annað að lesa

Um flokka
Varnar PowerShell
Virk forritun í PowerShell

Heimild: www.habr.com

Bæta við athugasemd