Szia Habr! Figyelmébe ajánlom a cikk fordítását
Ígérem, ez nem oximoron"
Az objektumorientált és a funkcionális programozási paradigmák ellentétesnek tűnhetnek egymással, de mindkettőt egyformán támogatja a Powershell. Szinte minden programozási nyelv, akár funkcionális, akár nem, rendelkezik kiterjesztett név-érték kötés lehetőségével; Az osztályok, mint a struktúrák és a rekordok, csak egy megközelítést jelentenek. Ha az osztályok használatát a nevek és értékek összekapcsolására korlátozzuk, és elkerüljük az olyan nehéz objektum-orientált programozási fogalmakat, mint az öröklődés, a polimorfizmus vagy a mutabilitás, akkor a kódunk bonyolítása nélkül kihasználhatjuk ezeket. Továbbá megváltoztathatatlan típuskonverziós módszerek hozzáadásával a funkcionális kódunkat osztályokkal gazdagíthatjuk.
A kasztok varázsa
A kasztok a Powershell egyik legerősebb funkciója. Amikor értéket ad meg, akkor a környezet által az alkalmazáshoz hozzáadott implicit inicializálási és érvényesítési képességekre támaszkodik. Például egy karakterlánc egyszerű öntése [xml]-ben keresztülfut az elemző kódon, és egy teljes xml-fát generál. Ugyanerre a célra használhatjuk a kódunkban található osztályokat.
Cast hashtables
Ha nincs konstruktor, akkor anélkül folytathatja, hogy egy hashtablet önt az osztálytípusra. Ne felejtse el használni az érvényesítési attribútumokat a minta teljes kihasználásához. Ugyanakkor az osztály beírt tulajdonságaival még mélyebb inicializálási és érvényesítési logikát futtathatunk.
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
}
Ezenkívül az öntés segít a tiszta kimenet elérésében. Hasonlítsa össze a Format-Table-nek átadott fürt hashtable tömb kimenetét azzal, amit akkor kap, ha ezeket a hashtable-okat először egy osztályba önti. Egy osztály tulajdonságai mindig abban a sorrendben jelennek meg, ahogy ott meghatározásra kerültek. Ne felejtse el hozzáadni a rejtett kulcsszót mindazon tulajdonságok elé, amelyeket nem szeretne látni az eredmények között.
Jelentések leadása
Ha van egy konstruktorod egy argumentummal, akkor az osztálytípusod értékének megadása átadja az értéket a konstruktorodnak, ahol inicializálhatod az osztályod példányát.
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"
Sorra öntve
A [string] ToString() osztálymetódus felülbírálásával is meghatározhatja az objektum karakterlánc-reprezentációja mögötti logikát, például karakterlánc-interpolációt.
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'"
Sorozatos példányok leadása
A Cast biztonságos deszerializálást tesz lehetővé. Az alábbi példák sikertelenek lesznek, ha az adatok nem felelnek meg a fürtben megadott specifikációnknak
# Валидация сериализованных данных
[Cluster]$cluster = Get-Content "./my-cluster.json" | ConvertFrom-Json
[Cluster[]]$clusters = Import-Csv "./my-clusters.csv"
Castok a funkcionális kódban
A funkcionális programok először adatstruktúrákat definiálnak, majd megváltoztathatatlan adatstruktúrákon át történő átalakítások sorozataként valósítják meg a programot. Az ellentmondásos benyomás ellenére az osztályok valóban segítenek a funkcionális kód írásában a típuskonverziós módszereknek köszönhetően.
Működik a Powershell, amit írok?
Sokan C# vagy hasonló háttérrel rendelkezők írnak Powershell-t, ami hasonló a C#-hoz. Ezzel eltávolodik a funkcionális programozási koncepciók használatától, és valószínűleg előnyös lenne, ha alaposan belemerülne a Powershell objektum-orientált programozásába, vagy többet tanulna a funkcionális programozásról.
Ha nagymértékben támaszkodik a megváltoztathatatlan adatok feldolgozási folyamatokkal (|), Where-Object, ForEach-Object, Select-Object, Group-Object, Sort-Object stb. osztályok funkcionális stílusban.
Az osztályok funkcionális használata
A kasztok, bár alternatív szintaxist használnak, csak egy leképezést jelentenek két tartomány között. A folyamatban a ForEach-Object segítségével leképezhet egy értékek tömbjét.
Az alábbi példában a Node konstruktor minden Datum leadásakor lefut, és ez lehetőséget ad arra, hogy ne írjunk megfelelő mennyiségű kódot. Ennek eredményeként a folyamatunk a deklaratív adatlekérdezésre és -összesítésre összpontosít, míg osztályaink az adatok elemzéséről és érvényesítéséről gondoskodnak.
# Пример комбинирования классов с конвейерами для 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
Csomagolási osztály újrafelhasználásra
Semmi sem olyan jó, mint amilyennek látszik
Sajnos az osztályokat nem lehet modulonként ugyanúgy exportálni, mint függvényeket vagy változókat; de van néhány trükk. Tegyük fel, hogy az osztályai a ./my-classes.ps1 fájlban vannak meghatározva
-
Dotsource-ozhat egy fájlt osztályokkal:. ./my-classes.ps1. Ez végrehajtja a my-classes.ps1 fájlt a jelenlegi hatókörben, és meghatározza az összes osztályt a fájlból.
-
Létrehozhat egy Powershell-modult, amely exportálja az összes egyéni API-t (parancsmagot), és beállíthatja a ScriptsToProcess = "./my-classes.ps1" változót a modul jegyzékében, ugyanazzal az eredménnyel: a ./my-classes.ps1 végrehajtása a környezeted.
Bármelyik opciót is választja, ne feledje, hogy a Powershell típusrendszere nem tudja feloldani a különböző helyekről betöltött azonos nevű típusokat.
Még ha különböző helyekről töltött be két azonos, azonos tulajdonságokkal rendelkező osztályt, fennáll a veszélye, hogy problémákba ütközik.
A továbbjutás
A típusfeloldási problémák elkerülésének legjobb módja, ha soha nem teszik közzé az osztályokat a felhasználók számára. Ahelyett, hogy azt várná a felhasználótól, hogy egy osztály által meghatározott típust importáljon, exportáljon egy függvényt a modulból, amely szükségtelenné teszi az osztály közvetlen elérését. A Cluster esetében exportálhatunk egy New-Cluster függvényt, amely támogatja a felhasználóbarát paraméterkészleteket, és visszaad egy fürtöt.
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
Mit kell még olvasni
Forrás: will.com