Hello, Habr! Saya membentangkan kepada anda terjemahan artikel oleh Christopher Kuech.
Paradigma pengaturcaraan berorientasikan objek dan berfungsi mungkin kelihatan bertentangan antara satu sama lain, tetapi kedua-duanya disokong sama dalam PowerShell. Hampir semua bahasa pengaturcaraan, berfungsi atau tidak, menawarkan pengikatan nilai nama yang meluas; kelas, seperti struct dan rekod, hanyalah satu pendekatan. Dengan mengehadkan penggunaan kelas kami kepada pengikatan nilai nama dan mengelakkan konsep pengaturcaraan berorientasikan objek berat seperti pewarisan, polimorfisme atau kebolehubahan, kami boleh memanfaatkan faedahnya tanpa merumitkan kod kami. Tambahan pula, dengan menambahkan kaedah penukaran jenis tidak berubah, kami boleh memperkayakan kod fungsi kami dengan kelas.
Sihir kasta
Cast ialah salah satu ciri yang paling berkuasa dalam PowerShell. Apabila anda menghantar nilai, anda bergantung pada keupayaan permulaan dan pengesahan tersirat yang ditambahkan oleh persekitaran pada aplikasi anda. Contohnya, hanya menghantar rentetan ke [xml] akan menjalankannya melalui kod penghurai dan menjana pepohon XML penuh. Kami boleh menggunakan Kelas dalam kod kami untuk tujuan yang sama.
Hantar jadual hash
Jika anda tidak mempunyai pembina, anda boleh meneruskan tanpa pembina dengan menghantar jadual hash ke jenis kelas anda. Jangan lupa untuk menggunakan atribut pengesahan untuk memanfaatkan sepenuhnya corak ini. Kami juga boleh menggunakan sifat kelas ditaip untuk melaksanakan logik permulaan dan pengesahan yang lebih mendalam.
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
}Tambahan pula, tuangan membantu menghasilkan keluaran yang lebih bersih. Bandingkan output tatasusunan Cluster bagi jadual cincang yang dihantar ke Jadual-Format dengan apa yang anda dapat jika anda mula-mula menghantar jadual cincang ini ke kelas. Sifat kelas sentiasa disenaraikan dalam susunan yang ditakrifkan. Jangan lupa untuk menambah kata kunci tersembunyi sebelum sebarang sifat yang anda tidak mahu kelihatan dalam output.

Kasta Nilai
Jika anda mempunyai pembina hujah tunggal, menghantar nilai kepada jenis kelas anda akan memberikan nilai kepada pembina anda, di mana anda boleh memulakan contoh kelas anda.
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"Hantar ke baris
Anda juga boleh mengatasi kaedah ToString() kelas [rentetan] untuk menentukan logik bagi mewakili objek dalam rentetan, seperti menggunakan interpolasi rentetan.
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'"Menghantar contoh bersiri
Cast membenarkan penyahserikan yang selamat. Contoh di bawah akan gagal jika data tidak memenuhi spesifikasi Kluster kami.
# Валидация сериализованных данных
[Cluster]$cluster = Get-Content "./my-cluster.json" | ConvertFrom-Json
[Cluster[]]$clusters = Import-Csv "./my-clusters.csv"Hantar dalam kod fungsi anda
Program fungsional mula-mula mentakrifkan struktur data, kemudian melaksanakan program sebagai urutan transformasi pada struktur data yang tidak boleh diubah. Walaupun tanggapan berlawanan dengan intuisi, kelas sebenarnya membantu menulis kod berfungsi berkat kaedah penukaran jenisnya.
Adakah saya menulis Powershell yang berfungsi?
Ramai orang yang datang dari C# atau latar belakang yang serupa menulis PowerShell, yang serupa dengan C#. Dengan berbuat demikian, anda melupakan konsep pengaturcaraan berfungsi dan mungkin akan mendapat manfaat daripada mendalami pengaturcaraan berorientasikan objek dalam PowerShell atau mempelajari lebih lanjut tentang pengaturcaraan berfungsi.
Jika anda sangat bergantung pada mengubah data tidak berubah menggunakan paip (|), Where-Object, ForEach-Object, Select-Object, Group-Object, Sort-Object, dsb., anda mempunyai gaya yang lebih berfungsi dan akan mendapat manfaat daripada menggunakan kelas Powershell gaya berfungsi.
Penggunaan kelas secara fungsional
Cast, walaupun mereka menggunakan sintaks alternatif, hanyalah pemetaan antara dua domain. Dalam saluran paip, anda boleh memetakan tatasusunan nilai menggunakan ForEach-Object.
Dalam contoh di bawah, pembina Nod dilaksanakan setiap kali Datum dibuang, menghapuskan sejumlah besar kod. Akibatnya, saluran paip kami menumpukan pada pertanyaan dan pengagregatan data deklaratif, manakala kelas kami mengendalikan penghuraian dan pengesahan 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 -UniquePembungkusan yang boleh dikitar semula
Tidak ada yang sebaik yang kelihatan
Malangnya, kelas tidak boleh dieksport oleh modul dengan cara yang sama seperti fungsi atau pembolehubah, tetapi terdapat beberapa helah. Katakan kelas anda ditakrifkan dalam fail ./my-classes.ps1
Anda boleh dotsource fail kelas: ./my-classes.ps1. Ini akan melaksanakan my-classes.ps1 dalam skop semasa anda dan mentakrifkan semua kelas daripada fail di sana.
Anda boleh mencipta modul Powershell yang mengeksport semua API tersuai anda (cmdlet) dan menetapkan pembolehubah ScriptsToProcess = "./my-classes.ps1" dalam manifes modul anda, dengan hasil yang sama: ./my-classes.ps1 akan dilaksanakan dalam persekitaran anda.
Mana-mana pilihan yang anda pilih, ingat bahawa sistem jenis PowerShell tidak boleh menyelesaikan jenis dengan nama yang sama dimuatkan dari lokasi berbeza.
Walaupun anda memuatkan dua kelas yang sama dengan sifat yang sama dari tempat yang berbeza, anda berisiko menghadapi masalah.
Jalan kehadapan
Cara terbaik untuk mengelakkan isu resolusi jenis adalah dengan tidak sekali-kali mendedahkan kelas anda kepada pengguna. Daripada mengharapkan pengguna mengimport jenis yang ditakrifkan dalam kelas, eksport fungsi daripada modul anda yang menghapuskan keperluan untuk mengakses kelas secara langsung. Untuk Kluster, kami boleh mengeksport fungsi Kluster Baharu yang menyokong set parameter mesra pengguna dan mengembalikan Kluster.
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-ClusterApa lagi yang perlu dibaca
Sumber: www.habr.com
