Powershell Fungsional karo kelas ora oxymoron, Aku njamin iku

Hey Habr! Aku menehi perhatian marang terjemahan artikel kasebut "PowerShell Fungsional karo Kelas.
Aku janji iku dudu oxymoron"
dening Christopher Kuech.

Paradigma pemrograman berorientasi obyek lan fungsional bisa uga beda-beda, nanging loro-lorone didhukung ing Powershell. Meh kabeh basa pamrograman, fungsional utawa ora, nduweni fasilitas kanggo ngiket nilai jeneng sing luwih dawa; Kelas, kaya struktur lan cathetan, mung siji pendekatan. Yen kita mbatesi panggunaan Kelas kanggo ngiket jeneng lan nilai, lan ngindhari konsep pemrograman berorientasi obyek sing abot kaya warisan, polimorfisme, utawa mutasi, kita bisa njupuk kauntungan kasebut tanpa nggawe rumit kode kita. Kajaba iku, kanthi nambahake metode konversi jinis sing ora bisa diganti, kita bisa nambah kode fungsional karo Kelas.

Piandel saka kasta

Kasta minangka salah sawijining fitur paling kuat ing Powershell. Nalika menehi nilai, sampeyan ngandelake kemampuan inisialisasi lan validasi implisit sing ditambahake lingkungan menyang aplikasi sampeyan. Contone, mung casting string ing [xml] bakal mbukak liwat kode parser lan ngasilake wit xml lengkap. Kita bisa nggunakake Kelas ing kode kanggo tujuan sing padha.

Cast hashtables

Yen sampeyan ora duwe konstruktor, sampeyan bisa nerusake tanpa siji dening casting hashtable kanggo jinis kelas. Aja lali nggunakake atribut validasi kanggo entuk manfaat saka pola iki. Ing wektu sing padha, kita bisa nggunakake properti sing diketik kelas kanggo mbukak logika wiwitan lan validasi sing luwih jero.

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
}

Kajaba iku, casting mbantu kanggo njaluk output resik. Bandhingake output array hashtable Cluster sing diterusake menyang Format-Tabel karo apa sing sampeyan entuk yen sampeyan pisanan nglebokake tabel hash iki menyang kelas. Properti kelas tansah kadhaptar ing urutan sing ditetepake ana. Aja lali nambah tembung kunci sing didhelikake sadurunge kabeh properti sing sampeyan ora pengin katon ing asil.

Powershell Fungsional karo kelas ora oxymoron, Aku njamin iku

Cast saka makna

Yen sampeyan duwe konstruktor kanthi siji argumen, menehi nilai menyang jinis kelas sampeyan bakal menehi nilai kasebut menyang konstruktor sampeyan, ing ngendi sampeyan bisa miwiti conto kelas sampeyan.

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"

Cast menyang baris

Sampeyan uga bisa ngilangi metode kelas [string] ToString () kanggo nemtokake logika ing mburi perwakilan senar obyek, kayata nggunakake interpolasi senar.

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 kedadean serialized

Cast ngidini deserialization aman. Conto ing ngisor iki bakal gagal yen data ora cocog karo spesifikasi ing Cluster

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

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

Castes ing kode fungsi Panjenengan

Program fungsional pisanan nemtokake struktur data, banjur ngetrapake program kasebut minangka urutan transformasi liwat struktur data sing ora bisa diganti. Sanajan kesan sing kontradiktif, kelas pancen mbantu sampeyan nulis kode fungsional amarga metode konversi jinis.

Apa Powershell sing daktulis fungsional?

Akeh wong sing teka saka C # utawa latar mburi sing padha nulis Powershell, sing padha karo C #. Kanthi nindakake iki, sampeyan ora nggunakake konsep pemrograman fungsional lan bakal entuk manfaat saka nyilem akeh program berorientasi obyek ing Powershell utawa sinau luwih akeh babagan pemrograman fungsional.

Yen sampeyan gumantung banget kanggo ngowahi data sing ora bisa diganti nggunakake pipelines (|), Where-Object, ForEach-Object, Select-Object, Group-Object, Sort-Object, etc. - sampeyan duwe gaya sing luwih fungsional lan sampeyan bakal entuk manfaat saka nggunakake Powershell kelas ing gaya fungsional.

Panggunaan fungsional kelas

Kasta, sanajan nggunakake sintaksis alternatif, mung minangka pemetaan antarane rong domain. Ing pipeline, sampeyan bisa map array saka nilai nggunakake ForEach-Object.

Ing conto ing ngisor iki, konstruktor Node dieksekusi saben Datum dibuwang, lan iki menehi kesempatan kanggo ora nulis kode sing cukup. AkibatΓ©, pipeline kita fokus ing pitakon data deklaratif lan agregasi, dene kelas kita ngurus parsing lan validasi data.

# ΠŸΡ€ΠΈΠΌΠ΅Ρ€ комбинирования классов с ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ€Π°ΠΌΠΈ для 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

Kelas kemasan kanggo digunakake maneh

Ora ana sing apik kaya sing katon

Sayange, kelas ora bisa diekspor dening modul kanthi cara sing padha karo fungsi utawa variabel; nanging ana sawetara trik. Ayo dadi ngomong kelas sampeyan ditetepake ing file ./my-classes.ps1

  • Sampeyan bisa dotsource file karo kelas:. ./kelasku.ps1. Iki bakal nglakokakΓ© my-classes.ps1 ing orane katrangan saiki lan nemtokake kabeh kelas saka file ana.

  • Sampeyan bisa nggawe modul Powershell sing ngekspor kabeh API khusus (cmdlets) lan nyetel ScriptsToProcess = "./my-classes.ps1" variabel ing manifes modul, kanthi asil sing padha: ./my-classes.ps1 bakal dieksekusi ing lingkungan sampeyan.

Apa wae pilihan sing sampeyan pilih, elinga yen sistem jinis Powershell ora bisa ngrampungake jinis kanthi jeneng sing padha sing dimuat saka macem-macem papan.
Sanajan sampeyan ngemot rong kelas sing padha karo properti sing padha saka macem-macem papan, sampeyan bakal ngalami masalah.

Cara maju

Cara paling apik kanggo ngindhari masalah resolusi jinis yaiku aja mbukak kelas sampeyan menyang pangguna. Tinimbang panganggo kanggo ngimpor jinis ditetepake kelas, ngekspor fungsi saka modul sing ngilangake perlu kanggo ngakses kelas langsung. Kanggo Cluster, kita bisa ngekspor fungsi New-Cluster sing bakal ndhukung set parameter sing ramah pangguna lan ngasilake 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

Apa maneh kanggo maca

Babagan Kelas
Defensive PowerShell
Pemrograman Fungsional ing PowerShell

Source: www.habr.com

Add a comment