Halo, Habr! Saya hadir untuk Anda terjemahan artikel "PowerShell Fungsional dengan Kelas.
Saya berjanji ini bukan oxymoron " oleh Christopher Kuech.
Paradigma pemrograman berorientasi objek dan fungsional mungkin tampak bertentangan satu sama lain, tetapi keduanya sama-sama didukung di Powershell. Hampir semua bahasa pemrograman, fungsional dan tidak, memiliki sarana pengikatan nama dan nilai yang diperluas; Kelas, seperti struct dan catatan, hanyalah satu pendekatan. Jika kita membatasi penggunaan Kelas pada nama dan nilai dan menghindari konsep pemrograman berorientasi objek "berat" seperti pewarisan, polimorfisme, atau mutabilitas, kita dapat memanfaatkannya tanpa menyulitkan kode kita. Lebih lanjut, dengan menambahkan metode konversi tipe yang tidak dapat diubah, kita dapat memperkaya kode fungsional kita dengan Kelas.
Sihir kasta
Kasta adalah salah satu fitur paling kuat di Powershell. Ketika Anda memberikan nilai, Anda mengandalkan lingkungan yang ditambahkan ke aplikasi Anda untuk inisialisasi dan validasi implisit. Sebagai contoh, cast sederhana string dalam [xml] akan menjalankannya melalui kode parser dan menghasilkan pohon xml lengkap. Kita dapat menggunakan Kelas dalam kode kita untuk tujuan yang sama.
Hashtable khusus
Jika Anda tidak memiliki konstruktor, Anda dapat melanjutkan tanpa menggunakan tabel hash dengan tipe kelas Anda. Ingatlah untuk menggunakan atribut validasi untuk mengambil keuntungan penuh dari pola ini. Pada saat yang sama, kita dapat menggunakan properti yang diketik dari kelas untuk memicu inisialisasi dan logika validasi yang lebih dalam.
class Cluster { [ValidatePattern("^[Az]+$")] [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 }
Selain itu, para pemain membantu untuk mendapatkan kesimpulan yang bersih. Bandingkan output dari array tabel hash Cluster diteruskan ke Format-Tabel dengan apa yang terjadi jika Anda pertama kali melemparkan tabel hash ini ke dalam kelas. Properti kelas selalu terdaftar dalam urutan yang didefinisikan di sana. Jangan lupa untuk menambahkan kata kunci tersembunyi di depan semua properti yang seharusnya tidak terlihat di output.

Nilai khusus
Jika Anda memiliki konstruktor dengan satu argumen, melemparkan nilai ke tipe kelas Anda akan meneruskan nilai ke konstruktor ini, di mana Anda dapat menginisialisasi instance kelas Anda
class Cluster { [ValidatePattern("^[Az]+$")] [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"
Jalur khusus
Anda juga dapat mengganti metode kelas [string] ToString () untuk menentukan logika representasi string objek, misalnya, menggunakan string interpolasi.
class Cluster { [ValidatePattern("^[Az]+$")] [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'"
Contoh Serial Kustom
Pemain memungkinkan deserialisasi yang aman. Contoh di bawah ini akan gagal jika data tidak memenuhi spesifikasi kami di Cluster
Castes dalam kode fungsi Anda
Program fungsional pertama-tama mendefinisikan struktur data, kemudian mengimplementasikan program sebagai urutan transformasi terhadap struktur data yang tidak berubah. Terlepas dari kesan yang bertentangan, kelas sangat membantu menulis kode fungsional berkat metode konversi jenis.
Apakah Powershell fungsional yang saya tulis?
Banyak orang yang berasal dari C # atau dengan masa lalu yang sama menulis Powershell, yang mirip dengan C #. Dengan melakukan itu, Anda enggan menggunakan konsep pemrograman fungsional dan cenderung mendapat manfaat karena tenggelam dalam pemrograman berorientasi objek di Powershell atau pemahaman yang lebih baik tentang pemrograman fungsional.
Jika Anda sangat bergantung pada transformasi data yang tidak dapat diubah menggunakan jalur pipa (|), Where-Object, ForEach-Object, Select-Object, Group-Object, Sort-Object, dll., Anda memiliki gaya yang lebih fungsional, dan menggunakan Kelas Powershell dalam gaya fungsional.
Penggunaan kelas secara fungsional
Kasta, meskipun menggunakan sintaks alternatif, hanya memetakan antara dua domain. Di pipeline, Anda bisa memetakan array nilai menggunakan ForEach-Object.
Dalam contoh di bawah ini, konstruktor Node dieksekusi setiap kali dilemparkan ke Datum, dan ini memungkinkan kita untuk tidak menulis kode dalam jumlah yang wajar. Akibatnya, pipeline kami berfokus pada kueri dan agregasi data deklaratif, sementara kelas kami menangani penguraian dan validasi data.
Gunakan kembali kemasan kelas
Tidak ada yang sebagus kedengarannya
Sayangnya, kelas tidak dapat diekspor oleh modul dengan cara yang sama seperti fungsi atau variabel; tetapi ada beberapa trik. Katakanlah kelas Anda didefinisikan dalam file ./my-classes.ps1
Anda dapat membuat file dosor dengan kelas:. ./my-classes.ps1. Ini akan menjalankan my-class.ps1 di ruang lingkup Anda saat ini dan menentukan di sana semua kelas dari file tersebut.
Anda dapat membuat modul Powershell yang mengekspor semua API pengguna Anda (cmdlets) dan mengatur variabel ScriptsToProcess = "./my-classes.ps1" di manifes modul Anda, dengan hasil yang sama: ./my-classes.ps1 akan dijalankan di lingkungan Anda .
Opsi mana pun yang Anda pilih, ingat bahwa sistem tipe Powershell tidak dapat menyelesaikan tipe nama yang sama yang diambil dari tempat yang berbeda.
Bahkan jika Anda mengunduh dua kelas yang identik dengan properti yang sama dari tempat yang berbeda, Anda berisiko mengalami masalah.
Maju terus
Cara terbaik untuk menghindari masalah resolusi tipe adalah tidak pernah mengekspos kelas Anda kepada pengguna. Alih-alih mengharapkan pengguna untuk mengimpor jenis yang ditentukan di kelas, ekspor dari modul Anda fungsi yang menghilangkan kebutuhan untuk langsung mengakses kelas. Untuk Cluster, kita dapat mengekspor fungsi Cluster Baru, yang akan mendukung set parameter yang mudah digunakan dan mengembalikan Cluster.
class Cluster { [ValidatePattern("^[Az]+$")] [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 lagi yang harus dibaca
Tentang Kelas
PowerShell Bertahan
Pemrograman Fungsional di PowerShell