Mengorganisasi kode menjadi fungsi yang dapat dipakai ulang: deklarasi dengan pola Verb-Noun, parameter dengan validasi dan nilai default, advanced function dengan CmdletBinding dan pipeline input, script blocks, cakupan scope, serta praktik terbaik untuk fungsi yang siap dipakai di skrip nyata.

Di episode 6 kalian mengulang proses dengan loop — tapi bagaimana kalau proses itu dibutuhkan di banyak tempat? Menyalin blok kode ke mana-mana adalah resep bencana: satu perbaikan harus diulang di puluhan tempat. Episode 7 menjawabnya dengan functions & script blocks: mengemas logika ke unit bernama yang bisa dipanggil, diberi parameter, dan dipakai ulang.
Bayangkan resep dapur yang ditulis di kartu index. Setiap kali kalian butuh nasi goreng, kalian tidak menulis ulang seluruh resep — kalian mengambil kartunya dan mengikutinya. Fungsi adalah kartu index itu: nama yang memanggil prosedur lengkap.
Deklarasi fungsi dimulai dengan kata kunci function, diikuti nama dan blok kode. Nama mengikuti pola Verb-Noun — kata kerja lalu objek — sehingga penamaannya konsisten seperti cmdlet bawaan.
function Get-UptimeRingkas {
$up = (Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
Write-Output "$($up.Days) hari $($up.Hours) jam"
}Verb yang disarankan tersedia di daftar verba yang disetujui — cek dengan Get-Verb. New-, Get-, Set-, Remove-, Test-, Invoke-, dan Convert- adalah contoh umum. Verb di luar daftar sah secara sintaks, tapi membuat fungsi kalian tidak terdeteksi sebagai perintah "resmi" oleh tooling.
Memanggil fungsi sama seperti memanggil cmdlet — cukup nama dan argumen:
Get-UptimeRingkasSetiap output yang dihasilkan fungsi menjadi nilai kembaliannya. Penting: semua yang ditulis ke pipeline output menjadi bagian dari hasil — Write-Output eksplisit maupun sekadar expression yang dievaluasi. Write-Host berbeda: ia menulis ke aliran informasi untuk ditampilkan, bukan dikembalikan.
function Get-LuasLingkaran {
param($JariJari)
[math]::PI * $JariJari * $JariJari
}
$luas = Get-LuasLingkaran -JariJari 7
Write-Host "Luas: $luas"Blok param di awal fungsi mendeklarasikan parameter. Ada beberapa jenis:
-Nama. Positional — diisi berdasarkan urutan jika dideklarasikan tanpa atribut khusus.function New-UserEntry {
[CmdletBinding()]
param(
[Parameter(Mandatory, Position = 0)]
[ValidatePattern("^[a-z0-9_-]+$")]
[string]$Username,
[ValidateRange(1, 65535)]
[int]$Port = 8080,
[ValidateSet("aktif", "nonaktif")]
[string]$Status = "aktif"
)
Write-Output "Membuat $Username di port $Port status $Status"
}Semua konstruksi atribut parameter di atas ditulis di dalam blok kode. Di luar kode, cukup ingat tiga properti parameter yang paling sering dipakai: Mandatory untuk kewajiban, nilai default untuk keringkasan, dan atribut Validate untuk pertahanan input sejak pintu masuk.
Tip
Validasi di parameter adalah tembok pertahanan pertama. ValidateRange memastikan angka masuk akal, ValidateSet memastikan pilihan salah satu dari daftar, dan ValidatePattern memastikan string memenuhi pola. Lebih baik menolak input buruk di awal daripada menanganinya di tengah logika.
Menambahkan atribut [CmdletBinding()] mengubah fungsi biasa menjadi advanced function — fungsi yang berperilaku seperti cmdlet asli:
[CmdletBinding()]
function Test-KoneksiServer {
param([string]$Hostname)
$ok = Test-NetConnection -ComputerName $Hostname -Port 443 -InformationLevel Quiet
Write-Output $ok
}Keuntungannya langsung terasa: fungsi kini mendukung parameter umum -Verbose, -Debug, -ErrorAction, -Confirm, dan -WhatIf. Perilaku itu didapat tanpa menulis satu baris pun — atribut yang menyatakannya.
Untuk fungsi yang mengubah keadaan, nyatakan dukungan konfirmasi dan simulasi:
[CmdletBinding(SupportsShouldProcess)]
function Remove-DataDir {
param([string]$Path)
if ($PSCmdlet.ShouldProcess($Path, "Hapus folder")) {
Remove-Item $Path -Recurse -Force
}
}Dengan deklarasi ini, pemanggil bisa menjalankan Remove-DataDir -WhatIf untuk simulasi tanpa menjalankan — garis penyelamat di lingkungan produksi. ShouldProcess mengembalikan benar bila aksi diizinkan berjalan, dan salah bila diminta simulasi.
Beberapa fungsi menerima masukan yang saling eksklusif — misalnya menerima path file atau objek file, bukan keduanya sekaligus. Parameter set membaginya menjadi kelompok:
function Get-FileSummary {
[CmdletBinding(DefaultParameterSetName = "ByPath")]
param(
[Parameter(ParameterSetName = "ByPath", Mandatory)]
[string]$Path,
[Parameter(ParameterSetName = "ByItem", Mandatory, ValueFromPipeline)]
[System.IO.FileInfo]$Item
)
if ($PSCmdlet.ParameterSetName -eq "ByPath") {
$Item = Get-Item $Path
}
Write-Output "Ukuran $($Item.Name): $($Item.Length)"
}Setiap parameter milik satu set (ParameterSetName). Pemanggil harus memilih salah satu set — kombinasi antar set akan ditolak dengan pesan yang menjelaskan set mana yang tersedia.
Fungsi bisa menerima objek dari pipeline, bukan hanya argumen langsung. Ada dua deklarasi utama:
ValueFromPipeline — menerima objek itu sendiri dari pipeline.ValueFromPipelineByPropertyName — menerima objek yang propertinya cocok dengan nama parameter.function Get-ProcessInfo {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
[string]$Name
)
process {
$p = Get-Process -Name $Name -ErrorAction SilentlyContinue
if ($p) {
Write-Output "$Name menggunakan $([math]::Round($p.WS / 1MB, 1)) MB"
}
}
}
Get-Process pwsh | Get-ProcessInfo
Get-Process -Name pwsh | Select-Object Name | Get-ProcessInfoBaris pertama mengirim objek Process — parameter $Name mengambil properti Name lewat ValueFromPipelineByPropertyName. Baris kedua menegaskan hal yang sama dari pipeline eksplisit. Keduanya memicu blok process untuk setiap item.
Script block adalah sekumpulan kode yang disimpan sebagai nilai — diperlakukan seperti data yang bisa dipindahkan dan dijalankan. Salah satu penggunaannya: dikirim ke komputer lain lewat Invoke-Command untuk dijalankan di sana.
$block = { Get-Process -Name pwsh }
Invoke-Command -ComputerName server-web -ScriptBlock $blockScript block juga menjadi dasar parameter seperti -ScriptBlock pada ForEach-Object yang kalian pakai di episode 6. Konsepnya sama: kode sebagai nilai, dijalankan nanti atau di tempat lain.
Setiap variabel lahir di scope tertentu — wilayah visibilitasnya. Scope berfungsi seperti ruangan di rumah: variabel di ruang tamu terlihat dari ruang kerja, tapi tidak sebaliknya.
| Scope | Jangkauan |
|---|---|
| Local | Berisi variabel di dalam blok atau fungsi saat ini |
| Script | Seluruh file script yang sedang berjalan |
| Global | Seluruh sesi PowerShell |
| Private | Hanya di scope tempat ia dideklarasikan |
Fungsi melihat variabel dari scope induknya, tetapi menetapkan variabel di dalam fungsi membuat variabel lokal baru — tidak mengubah yang di luar. Untuk mengubah nilai scope luar secara eksplisit, gunakan prefiks cakupan:
$script:hitung = 0
function Get-Naikkan {
$script:hitung++
}
Get-Naikkan
Get-Naikkan
Write-Host "Nilai di scope script: $script:hitung"Tanpa prefiks $script:, fungsi akan membuat $hitung lokal yang hilang saat fungsi selesai — bug klasik yang membingungkan pemula. Aturan praktis: hindari ketergantungan pada variabel global; beri parameter dan terima hasil kembalian.
Prinsip yang menjaga fungsi tetap sehat:
Get-DiskUsage tidak sekaligus mengirim email.Get-Help bekerja.throw untuk kegagalan yang harus menghentikan, dan Write-Error untuk yang bisa dilewati, sesuai materi episode 12.function Get-HealthCheck {
<#
.SYNOPSIS
Memeriksa ketersediaan server.
.PARAMETER Hostname
Nama atau alamat server.
.EXAMPLE
Get-HealthCheck -Hostname web-01
#>
param([string]$Hostname)
Test-NetConnection -ComputerName $Hostname -Port 443 -InformationLevel Quiet
}Setelah definisi di atas, pemanggil bisa menulis Get-Help Get-HealthCheck dan melihat dokumentasi lengkap — dokumentasi yang menyatu dengan kode.
Episode 7 mengubah skrip kalian dari daftar instruksi menjadi kumpulan unit yang bisa dipakai ulang: deklarasi fungsi dengan pola Verb-Noun, nilai kembalian lewat pipeline output, parameter dengan default, mandatory, dan validasi, advanced function dengan CmdletBinding dan dukungan -WhatIf, parameter set untuk input yang saling eksklusif, pipeline input dengan ValueFromPipeline, script block sebagai kode yang bisa dikirim dan dijalankan, scope yang mengatur visibilitas variabel, serta praktik terbaik termasuk comment-based help.
Poin kunci yang dibawa pulang:
Write-Host hanya untuk menampilkan.CmdletBinding memberi perilaku cmdlet penuh — termasuk -WhatIf.Di episode 8 kita membedah jantung PowerShell: pipeline & object manipulation — bagaimana objek mengalir antargaris, disaring dengan Where-Object, dipilih propertinya dengan Select-Object, diurutkan, dikelompokkan, dan diproses paralel. Sampai jumpa di episode 8!