Hej Habr! Predstavljam Vašoj pažnji prevod članka
Obećavam da to nije oksimoron"
Objektno orijentisana i funkcionalna programska paradigma mogu izgledati u suprotnosti jedna s drugom, ali obje su podjednako podržane u Powershell-u. Gotovo svi programski jezici, funkcionalni ili ne, imaju mogućnosti za prošireno vezivanje ime-vrijednost; Klase, kao što su strukture i zapisi, su samo jedan pristup. Ako ograničimo našu upotrebu klasa na vezivanje imena i vrijednosti i izbjegnemo teške koncepte objektno orijentisanog programiranja kao što su nasljeđivanje, polimorfizam ili promjenjivost, možemo ih iskoristiti bez kompliciranja našeg koda. Nadalje, dodavanjem nepromjenjivih metoda konverzije tipa, možemo obogatiti naš funkcionalni kod klasama.
Magija kasti
Kaste su jedna od najmoćnijih karakteristika u Powershell-u. Kada dodijelite vrijednost, oslanjate se na implicitne mogućnosti inicijalizacije i validacije koje okruženje dodaje vašoj aplikaciji. Na primjer, jednostavno bacanje stringa u [xml] će ga pokrenuti kroz kod parsera i generirati kompletno xml stablo. U istu svrhu možemo koristiti klase u našem kodu.
Cast hashtables
Ako nemate konstruktor, možete nastaviti bez njega tako što ćete ubaciti hashtable na svoj tip klase. Ne zaboravite da koristite atribute validacije da biste u potpunosti iskoristili ovaj obrazac. U isto vrijeme, možemo koristiti upisana svojstva klase za pokretanje još dublje logike inicijalizacije i validacije.
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
}
Osim toga, livenje pomaže da se dobije čist rezultat. Uporedite izlaz niza hashtable Cluster proslijeđenog u Format-Table sa onim što dobijete ako prvo bacite ove hashtable u klasu. Svojstva klase su uvijek navedena onim redoslijedom kojim su tamo definirana. Nemojte zaboraviti dodati skrivenu ključnu riječ ispred svih onih svojstava koja ne želite da budu vidljiva u rezultatima.
Cast značenja
Ako imate konstruktor s jednim argumentom, prebacivanje vrijednosti na tip vaše klase će proslijediti vrijednost vašem konstruktoru, gdje možete inicijalizirati instancu vaše klase
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"
Baci na liniju
Također možete nadjačati metodu klase [string] ToString() da definirate logiku iza string reprezentacije objekta, kao što je korištenje interpolacije stringova.
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 serijalizirane instance
Cast omogućava sigurnu deserializaciju. Primjeri u nastavku neće uspjeti ako podaci ne zadovoljavaju našu specifikaciju u Clusteru
# Валидация сериализованных данных
[Cluster]$cluster = Get-Content "./my-cluster.json" | ConvertFrom-Json
[Cluster[]]$clusters = Import-Csv "./my-clusters.csv"
Uvodi u vaš funkcionalni kod
Funkcionalni programi prvo definiraju strukture podataka, a zatim implementiraju program kao niz transformacija nad nepromjenjivim strukturama podataka. Uprkos kontradiktornom utisku, klase vam zaista pomažu u pisanju funkcionalnog koda zahvaljujući metodama konverzije tipova.
Je li Powershell koji pišem funkcionalan?
Mnogi ljudi koji dolaze iz C# ili slične pozadine pišu Powershell, što je slično C#. Čineći ovo, udaljavate se od korištenja koncepta funkcionalnog programiranja i vjerojatno biste imali koristi od urona u objektno orijentirano programiranje u Powershell-u ili učenja više o funkcionalnom programiranju.
Ako se u velikoj mjeri oslanjate na transformaciju nepromjenjivih podataka pomoću cjevovoda (|), Where-Object, ForEach-Object, Select-Object, Group-Object, Sort-Object, itd. - imate funkcionalniji stil i imat ćete koristi od korištenja Powershell-a nastava u funkcionalnom stilu.
Funkcionalna upotreba časova
Kaste, iako koriste alternativnu sintaksu, samo su mapiranje između dva domena. U cjevovodu možete mapirati niz vrijednosti pomoću ForEach-Object.
U primjeru ispod, konstruktor čvora se izvršava svaki put kada se datum izbacuje, a to nam daje priliku da ne napišemo priličnu količinu koda. Kao rezultat toga, naš cevovod se fokusira na deklarativno ispitivanje podataka i agregaciju, dok se naše klase brinu za raščlanjivanje i validaciju podataka.
# Пример комбинирования классов с конвейерами для 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
Klasa pakovanja za ponovnu upotrebu
Ništa nije tako dobro kao što se čini
Nažalost, moduli ne mogu eksportovati klase na isti način kao funkcije ili varijable; ali postoje neki trikovi. Recimo da su vaše klase definisane u datoteci ./my-classes.ps1
-
Možete dotsource fajl sa klasama:. ./my-classes.ps1. Ovo će izvršiti my-classes.ps1 u vašem trenutnom opsegu i definirati sve klase iz datoteke tamo.
-
Možete kreirati Powershell modul koji izvozi sve vaše prilagođene API-je (cmdlete) i postaviti varijablu ScriptsToProcess = "./my-classes.ps1" u manifestu vašeg modula, sa istim rezultatom: ./my-classes.ps1 će se izvršiti u vaše okruženje.
Koju god opciju da odaberete, imajte na umu da Powershell-ov sistem tipova ne može riješiti tipove istog imena učitane s različitih mjesta.
Čak i ako ste učitali dvije identične klase sa istim svojstvima sa različitih mjesta, rizikujete da naiđete na probleme.
Put naprijed
Najbolji način da izbjegnete probleme s rezolucijom tipova je da nikada ne izlažete svoje klase korisnicima. Umjesto da očekujete da korisnik uveze tip definiran klasom, izvezite funkciju iz vašeg modula koja eliminira potrebu za direktnim pristupom klasi. Za Cluster, možemo izvesti funkciju New-Cluster koja će podržati skupove parametara prilagođene korisniku i vratiti 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
Šta još čitati
izvor: www.habr.com