Hej Habr! Predstavljam vam prevod članka
Obljubim, da ni oksimoron"
Paradigme objektno usmerjenega in funkcionalnega programiranja se morda zdijo v nasprotju, vendar sta obe enako podprti v Powershell. Skoraj vsi programski jeziki, funkcionalni ali ne, imajo možnosti za razširjeno vezavo imena in vrednosti; Razredi, tako kot strukture in zapisi, so samo en pristop. Če omejimo našo uporabo razredov na vezavo imen in vrednosti ter se izognemo težkim konceptom objektno usmerjenega programiranja, kot so dedovanje, polimorfizem ali spremenljivost, lahko izkoristimo njihove prednosti, ne da bi komplicirali kodo. Poleg tega lahko z dodajanjem metod pretvorbe nespremenljivih tipov našo funkcionalno kodo obogatimo z razredi.
Čarovnija kast
Kaste so ena najmočnejših funkcij v programu Powershell. Ko dodelite vrednost, se zanašate na implicitne zmožnosti inicializacije in preverjanja, ki jih okolje doda vaši aplikaciji. Na primer, preprosto prevajanje niza v [xml] ga bo pognalo skozi kodo razčlenjevalnika in ustvarilo celotno drevo xml. Za isti namen lahko uporabimo razrede v naši kodi.
Cast hashtables
Če nimate konstruktorja, lahko nadaljujete brez njega, tako da razpršilno tabelo preoblikujete v svoj tip razreda. Ne pozabite uporabiti atributov preverjanja, da boste v celoti izkoristili ta vzorec. Istočasno lahko uporabimo tipizirane lastnosti razreda za izvajanje še globlje inicializacijske in validacijske logike.
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
}
Poleg tega ulivanje pomaga dobiti čist rezultat. Primerjajte izhod matrike zgoščevalnih tabel Cluster, posredovane Format-Table, s tistim, kar dobite, če te zgoščevalne tabele najprej pretvorite v razred. Lastnosti razreda so vedno navedene v vrstnem redu, v katerem so tam definirane. Ne pozabite dodati skrite ključne besede pred vsemi tistimi lastnostmi, za katere ne želite, da so vidne v rezultatih.
Zasedba pomenov
Če imate konstruktor z enim argumentom, bo pretvorba vrednosti v vaš tip razreda posredovala vrednost vašemu konstruktorju, kjer lahko inicializirate primerek svojega razreda
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 to line
Metodo razreda [string] ToString() lahko tudi preglasite, da definirate logiko v ozadju predstavitve niza objekta, na primer z uporabo interpolacije niza.
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 serializirani primerki
Cast omogoča varno deserializacijo. Spodnji primeri ne bodo uspešni, če podatki ne ustrezajo našim specifikacijam v Clusterju
# Валидация сериализованных данных
[Cluster]$cluster = Get-Content "./my-cluster.json" | ConvertFrom-Json
[Cluster[]]$clusters = Import-Csv "./my-clusters.csv"
Kaste v vaši funkcijski kodi
Funkcionalni programi najprej definirajo podatkovne strukture, nato implementirajo program kot zaporedje transformacij nad nespremenljivimi podatkovnimi strukturami. Kljub protislovnemu vtisu vam razredi resnično pomagajo pri pisanju funkcionalne kode zahvaljujoč metodam pretvorbe tipov.
Ali Powershell, ki ga pišem, deluje?
Veliko ljudi, ki prihajajo iz C# ali podobnih okolij, pišejo Powershell, ki je podoben C#. S tem se oddaljujete od uporabe konceptov funkcionalnega programiranja in bi vam verjetno koristilo, če bi se močno poglobili v objektno usmerjeno programiranje v Powershellu ali izvedeli več o funkcionalnem programiranju.
Če se močno zanašate na preoblikovanje nespremenljivih podatkov z uporabo cevovodov (|), Where-Object, ForEach-Object, Select-Object, Group-Object, Sort-Object itd. - imate bolj funkcionalen slog in uporaba Powershell vam bo koristila razrede v funkcionalnem slogu.
Funkcionalna uporaba razredov
Kaste so, čeprav uporabljajo alternativno sintakso, le preslikava med dvema domenama. V cevovodu lahko preslikate niz vrednosti z uporabo ForEach-Object.
V spodnjem primeru se konstruktor vozlišča izvede vsakič, ko je Datum pretvorjen, kar nam daje možnost, da ne napišemo dovolj kode. Posledično se naš cevovod osredotoča na deklarativno poizvedovanje in združevanje podatkov, medtem ko naši razredi skrbijo za razčlenjevanje in preverjanje podatkov.
# Пример комбинирования классов с конвейерами для 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
Razred embalaže za ponovno uporabo
Nič ni tako dobro, kot se zdi
Na žalost razredov ni mogoče izvoziti po modulih na enak način kot funkcij ali spremenljivk; vendar obstaja nekaj trikov. Recimo, da so vaši razredi definirani v datoteki ./my-classes.ps1
-
Lahko dotsource datoteko z razredi:. ./my-classes.ps1. To bo izvedlo my-classes.ps1 v vašem trenutnem obsegu in tam definiralo vse razrede iz datoteke.
-
Ustvarite lahko modul Powershell, ki izvozi vse vaše API-je po meri (cmdlets) in nastavite spremenljivko ScriptsToProcess = "./my-classes.ps1" v manifestu modula z enakim rezultatom: ./my-classes.ps1 se bo izvedel v tvoje okolje.
Ne glede na to, katero možnost izberete, ne pozabite, da tipski sistem Powershell ne more razrešiti tipov z istim imenom, naloženih z različnih mest.
Tudi če ste naložili dva enaka razreda z enakimi lastnostmi z različnih mest, tvegate težave.
Pot naprej
Najboljši način, da se izognete težavam z razreševanjem tipov, je, da svojih razredov nikoli ne izpostavite uporabnikom. Namesto da pričakujete, da bo uporabnik uvozil razredno definiran tip, izvozite funkcijo iz svojega modula, ki odpravlja potrebo po neposrednem dostopu do razreda. Za gručo lahko izvozimo funkcijo New-Cluster, ki bo podpirala uporabniku prijazne nize parametrov in vrnila gručo.
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
Kaj še brati
Vir: www.habr.com