Powershell Funzjonali bil-klassijiet mhuwiex oxymoron, niggarantilha

Ħej Habr! Nippreżenta għall-attenzjoni tiegħek it-traduzzjoni tal-artiklu "PowerShell funzjonali bi Klassijiet.
Inwiegħed li mhux oxymoron"
minn Christopher Kuech.

Paradigmi ta 'programmazzjoni orjentati lejn l-oġġetti u funzjonali jistgħu jidhru f'kontradizzjoni ma' xulxin, iżda t-tnejn huma appoġġjati bl-istess mod f'Powershell. Kważi l-lingwi tal-ipprogrammar kollha, funzjonali jew le, għandhom faċilitajiet għall-irbit estiż tal-isem-valur; Il-klassijiet, bħall-istrutturi u r-rekords, huma biss approċċ wieħed. Jekk nillimitaw l-użu tagħna ta’ Klassijiet għall-irbit ta’ ismijiet u valuri, u nevitaw kunċetti tqal ta’ programmazzjoni orjentati lejn l-oġġetti bħall-wirt, il-polimorfiżmu, jew il-mutabilità, nistgħu nieħdu vantaġġ minnhom mingħajr ma nikkomplikaw il-kodiċi tagħna. Barra minn hekk, billi żżid metodi ta 'konverżjoni tat-tip immutabbli, nistgħu jarrikkixxu l-kodiċi funzjonali tagħna bil-Klassijiet.

Il-maġija tal-kasti

Il-kasti huma waħda mill-aktar karatteristiċi qawwija fil-Powershell. Meta titfa' valur, tkun qed tiddependi fuq il-kapaċitajiet impliċiti ta' inizjalizzazzjoni u validazzjoni li l-ambjent iżid mal-applikazzjoni tiegħek. Pereżempju, sempliċiment ikkastjar string f'[xml] se jmexxiha permezz tal-kodiċi tal-parser u tiġġenera siġra xml kompluta. Nistgħu nużaw Klassijiet fil-kodiċi tagħna għall-istess għan.

Cast hashtables

Jekk ma jkollokx kostruttur, tista' tkompli mingħajr waħda billi tikkastja hashtable għat-tip tal-klassi tiegħek. Tinsiex tuża l-attributi tal-validazzjoni biex tieħu vantaġġ sħiħ minn dan il-mudell. Fl-istess ħin, nistgħu nużaw il-proprjetajiet ittajpjati tal-klassi biex inħaddmu loġika ta 'inizjalizzazzjoni u validazzjoni saħansitra aktar profonda.

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
}

Barra minn hekk, ikkastjar jgħin biex tikseb output nadif. Qabbel l-output tal-array hashtable Cluster mgħoddi lil Format-Table ma 'dak li tikseb jekk l-ewwel titfa' dawn il-hashtables fi klassi. Il-proprjetajiet ta 'klassi huma dejjem elenkati fl-ordni li fiha huma definiti hemmhekk. Tinsiex iżżid il-keyword moħbija qabel dawk il-proprjetajiet kollha li ma tridx li tkun viżibbli fir-riżultati.

Powershell Funzjonali bil-klassijiet mhuwiex oxymoron, niggarantilha

Cast ta 'tifsiriet

Jekk għandek kostruttur b'argument wieħed, l-ikkastjar ta' valur għat-tip ta' klassi tiegħek se jgħaddi l-valur lill-kostruttur tiegħek, fejn tista' tinizjalizza eżempju tal-klassi tiegħek

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"

Mitfugħa mal-linja

Tista 'wkoll tegħleb il-metodu tal-klassi [string] ToString() biex tiddefinixxi l-loġika wara r-rappreżentazzjoni tal-sekwenza tal-oġġett, bħall-użu tal-interpolazzjoni tal-istring.

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 istanzi serjali

Cast jippermetti deserialization sigur. L-eżempji hawn taħt ifallu jekk id-dejta ma tissodisfax l-ispeċifikazzjoni tagħna fil-Cluster

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

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

Kasti fil-kodiċi funzjonali tiegħek

Programmi funzjonali l-ewwel jiddefinixxu strutturi tad-data, imbagħad jimplimentaw il-programm bħala sekwenza ta 'trasformazzjonijiet fuq strutturi ta' data immutabbli. Minkejja l-impressjoni kontradittorja, il-klassijiet verament jgħinuk tikteb kodiċi funzjonali grazzi għall-metodi ta 'konverżjoni tat-tip.

Il-Powershell li qed nikteb huwa funzjonali?

Ħafna nies li ġejjin minn C# jew sfondi simili qed jiktbu Powershell, li huwa simili għal C#. Billi tagħmel dan, tkun qed titbiegħed mill-użu ta 'kunċetti ta' programmazzjoni funzjonali u x'aktarx tibbenefika milli tgħaddas bil-kbir fl-ipprogrammar orjentat lejn l-oġġetti fil-Powershell jew titgħallem aktar dwar l-ipprogrammar funzjonali.

Jekk tiddependi ħafna fuq it-trasformazzjoni ta' data immutabbli billi tuża pipelines (|), Where-Object, ForEach-Object, Select-Object, Group-Object, Sort-Object, eċċ. - għandek stil aktar funzjonali u int tibbenefika mill-użu ta' Powershell klassijiet fi stil funzjonali.

Użu funzjonali tal-klassijiet

Il-kasti, għalkemm jużaw sintassi alternattiva, huma biss mapping bejn żewġ oqsma. Fil-pipeline, tista 'mappa firxa ta' valuri billi tuża ForEach-Object.

Fl-eżempju hawn taħt, il-kostruttur Node jiġi esegwit kull darba li Datum jiġi mitfugħ, u dan jagħtina l-opportunità li ma niktbux ammont ġust ta 'kodiċi. Bħala riżultat, il-pipeline tagħna jiffoka fuq l-interrogazzjoni u l-aggregazzjoni tad-dejta dikjarattiva, filwaqt li l-klassijiet tagħna jieħdu ħsieb l-analiżi u l-validazzjoni tad-dejta.

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

Klassi ta' ppakkjar għall-użu mill-ġdid

Xejn mhu tajjeb daqs kemm jidher

Sfortunatament, il-klassijiet ma jistgħux jiġu esportati minn moduli bl-istess mod bħal funzjonijiet jew varjabbli; imma hemm xi tricks. Ejja ngħidu li l-klassijiet tiegħek huma definiti fil-fajl ./my-classes.ps1

  • Tista' tagħmel dotsource fajl bi klassijiet:. ./my-classes.ps1. Dan se jesegwixxi my-classes.ps1 fl-ambitu attwali tiegħek u jiddefinixxi l-klassijiet kollha mill-fajl hemmhekk.

  • Tista' toħloq modulu Powershell li jesporta l-APIs tad-dwana kollha tiegħek (cmdlets) u ssettja l-varjabbli ScriptsToProcess = "./my-classes.ps1" fil-manifest tal-modulu tiegħek, bl-istess riżultat: ./my-classes.ps1 se jesegwixxi f' l-ambjent tiegħek.

Tkun xi tkun l-għażla li tagħżel, żomm f'moħħok li s-sistema tat-tip Powershell ma tistax issolvi tipi tal-istess isem mgħobbija minn postijiet differenti.
Anke jekk tgħabba żewġ klassijiet identiċi bl-istess proprjetajiet minn postijiet differenti, tirriskja li tiffaċċja problemi.

It-triq 'il quddiem

L-aħjar mod biex tevita problemi ta' riżoluzzjoni tat-tip huwa li qatt ma tesponi l-klassijiet tiegħek lill-utenti. Minflok ma tistenna li l-utent jimporta tip definit mill-klassi, esporta funzjoni mill-modulu tiegħek li telimina l-ħtieġa li taċċessa l-klassi direttament. Għal Cluster, nistgħu nesportaw funzjoni New-Cluster li se tappoġġja settijiet ta 'parametri faċli għall-utent u tirritorna 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

X'iktar li taqra

Dwar Klassijiet
PowerShell difensiv
Programmazzjoni Funzjonali fil-PowerShell

Sors: www.habr.com

Żid kumment