7 Bentuk Fungsi yang Membuat Kode JavaScript dan TypeScript Lebih Mudah Dibaca, Digunakan, dan Dipercaya
Dalam dunia pengembangan perangkat lunak, kode yang bersih dan mudah dipahami adalah kunci untuk pemeliharaan, kolaborasi, dan keandalan. JavaScript dan TypeScript, sebagai bahasa yang sangat populer, menawarkan berbagai cara untuk menulis fungsi. Namun, tidak semua pendekatan sama efektifnya. Artikel ini akan membahas 7 bentuk fungsi yang dapat secara signifikan meningkatkan keterbacaan, kegunaan, dan kepercayaan pada kode Anda. Kita akan menyelami setiap bentuk, memberikan contoh kode praktis, dan menjelaskan manfaatnya masing-masing. Mari kita mulai perjalanan untuk menulis kode yang lebih baik!
Mengapa Bentuk Fungsi Penting?
Sebelum kita masuk ke detail, mari kita pahami mengapa bentuk fungsi itu penting:
- Keterbacaan: Bentuk fungsi yang jelas dan konsisten membuat kode lebih mudah dibaca dan dipahami oleh pengembang lain (dan diri Anda sendiri di masa depan).
- Kegunaan: Bentuk yang baik mempromosikan penggunaan kembali kode dan mengurangi redundansi.
- Kepercayaan: Bentuk yang terstruktur dengan baik memfasilitasi pengujian dan mengurangi risiko bug.
- Pemeliharaan: Kode yang ditulis dengan bentuk fungsi yang baik lebih mudah dimodifikasi dan dipelihara seiring waktu.
Kerangka Artikel
- Pengantar: Mengapa Bentuk Fungsi Penting?
- Menjelaskan pentingnya bentuk fungsi dalam keterbacaan, kegunaan, kepercayaan, dan pemeliharaan kode.
- Memberikan gambaran umum tentang 7 bentuk fungsi yang akan dibahas.
- 1. Fungsi Murni (Pure Functions): Predictability dan Testability
- Definisi fungsi murni.
- Karakteristik: Tidak ada efek samping, deterministik (output selalu sama untuk input yang sama).
- Contoh kode JavaScript dan TypeScript.
- Manfaat: Mudah diuji, mudah untuk reasoning, dan dapat dioptimalkan oleh kompiler.
- Kapan menggunakan fungsi murni.
- 2. Fungsi Komposisi (Function Composition): Building Blocks untuk Logic Kompleks
- Definisi komposisi fungsi.
- Bagaimana menggabungkan beberapa fungsi untuk membuat fungsi yang lebih kompleks.
- Contoh kode JavaScript dan TypeScript.
- Manfaat: Meningkatkan reuse kode, meningkatkan readability, dan memecah logic kompleks menjadi bagian yang lebih kecil.
- Kapan menggunakan komposisi fungsi.
- 3. Currying: Spesialisasi Fungsi Secara Bertahap
- Definisi currying.
- Bagaimana mengubah fungsi yang menerima banyak argumen menjadi urutan fungsi yang masing-masing menerima satu argumen.
- Contoh kode JavaScript dan TypeScript.
- Manfaat: Fleksibilitas, reusable, dan memungkinkan spesialisasi fungsi secara bertahap.
- Kapan menggunakan currying.
- 4. Fungsi Higher-Order (Higher-Order Functions): Abstraksi dan Kontrol Aliran
- Definisi fungsi higher-order.
- Fungsi yang menerima fungsi lain sebagai argumen atau mengembalikan fungsi sebagai hasilnya.
- Contoh kode JavaScript dan TypeScript (misalnya,
map
,filter
,reduce
). - Manfaat: Abstraksi, reusable, dan memungkinkan kontrol aliran yang lebih fleksibel.
- Kapan menggunakan fungsi higher-order.
- 5. Immediately Invoked Function Expressions (IIFEs): Enkapsulasi dan Isolasi Scope
- Definisi IIFE.
- Mengapa menggunakan IIFE untuk enkapsulasi dan isolasi scope.
- Contoh kode JavaScript dan TypeScript.
- Manfaat: Mencegah polusi namespace global, enkapsulasi kode, dan kontrol scope.
- Kapan menggunakan IIFE.
- 6. Fungsi Generator (Generator Functions): Iterasi yang Efisien dan Keadaan yang Dipertahankan
- Definisi fungsi generator.
- Bagaimana menggunakan
yield
untuk menghasilkan nilai satu per satu. - Contoh kode JavaScript dan TypeScript.
- Manfaat: Iterasi yang efisien, keadaan yang dipertahankan, dan memungkinkan asynchronous programming yang lebih mudah dibaca.
- Kapan menggunakan fungsi generator.
- 7. Fungsi Rekursif (Recursive Functions): Memecahkan Masalah dengan Mengulangi Diri Sendiri
- Definisi fungsi rekursif.
- Bagaimana memecahkan masalah dengan memanggil fungsi itu sendiri.
- Contoh kode JavaScript dan TypeScript.
- Manfaat: Elegansi, memecahkan masalah yang kompleks menjadi lebih kecil, dan sesuai untuk masalah yang secara alami rekursif.
- Kapan menggunakan fungsi rekursif.
- Kesimpulan: Menerapkan Bentuk Fungsi Terbaik dalam Praktik
- Ringkasan 7 bentuk fungsi yang dibahas.
- Tips untuk menerapkan bentuk fungsi terbaik dalam proyek Anda.
- Mendorong pembaca untuk bereksperimen dan menemukan bentuk fungsi yang paling sesuai dengan kebutuhan mereka.
1. Fungsi Murni (Pure Functions): Predictability dan Testability
Fungsi murni adalah landasan pemrograman fungsional. Mereka sangat berguna karena perilaku mereka sangat mudah diprediksi. Ini mempermudah pengujian, debugging, dan reasoning tentang kode.
Definisi: Fungsi murni adalah fungsi yang, diberikan input yang sama, selalu menghasilkan output yang sama, dan tidak memiliki efek samping.
Karakteristik:
- Deterministik: Output hanya bergantung pada input.
- Tidak ada efek samping: Tidak mengubah status di luar scope fungsi. Ini berarti tidak ada modifikasi variabel global, tidak ada perubahan properti objek eksternal, dan tidak ada operasi I/O (seperti menulis ke konsol atau membuat permintaan jaringan).
Contoh JavaScript:
“`javascript
function tambah(a, b) {
return a + b;
}
console.log(tambah(2, 3)); // Output: 5
console.log(tambah(2, 3)); // Output: 5 (selalu sama)
“`
Dalam contoh ini, fungsi tambah
selalu mengembalikan jumlah dari dua argumennya. Ini tidak memodifikasi apa pun di luar scope fungsinya. Oleh karena itu, ini adalah fungsi murni.
Contoh JavaScript (Bukan Fungsi Murni):
“`javascript
let total = 0;
function tambahKeTotal(angka) {
total += angka;
return total;
}
console.log(tambahKeTotal(5)); // Output: 5
console.log(tambahKeTotal(5)); // Output: 10 (berbeda setiap kali dipanggil)
“`
Dalam contoh ini, fungsi tambahKeTotal
memodifikasi variabel global total
. Ini adalah efek samping, yang membuat fungsi ini bukan fungsi murni.
Contoh TypeScript:
“`typescript
function kali(a: number, b: number): number {
return a * b;
}
console.log(kali(4, 5)); // Output: 20
console.log(kali(4, 5)); // Output: 20 (selalu sama)
“`
Contoh TypeScript ini mirip dengan contoh JavaScript, hanya saja menggunakan type annotations untuk kejelasan.
Manfaat:
- Mudah Diuji: Karena output selalu sama untuk input yang sama, pengujian menjadi sangat sederhana. Anda cukup memberikan input dan memverifikasi output.
- Mudah untuk Reasoning: Anda dapat yakin bahwa fungsi murni hanya bergantung pada inputnya, sehingga mempermudah reasoning tentang kode dan menemukan bug.
- Dapat Dioptimalkan: Kompiler dan runtime dapat mengoptimalkan fungsi murni dengan cara yang tidak mungkin dilakukan dengan fungsi yang memiliki efek samping (misalnya, memoization).
Kapan Menggunakan Fungsi Murni:
- Saat Anda perlu melakukan perhitungan atau transformasi data tanpa mengubah state eksternal.
- Saat Anda ingin membuat kode yang mudah diuji dan reasoning.
- Saat Anda ingin memanfaatkan optimasi yang mungkin ditawarkan oleh kompiler atau runtime.
2. Fungsi Komposisi (Function Composition): Building Blocks untuk Logic Kompleks
Komposisi fungsi adalah teknik untuk menggabungkan beberapa fungsi untuk membuat fungsi yang lebih kompleks. Ini seperti membangun struktur yang kompleks dari blok bangunan yang lebih kecil.
Definisi: Komposisi fungsi adalah proses menggabungkan dua atau lebih fungsi untuk menghasilkan fungsi baru. Output dari satu fungsi menjadi input ke fungsi berikutnya.
Bagaimana Menggabungkan Fungsi:
Secara konseptual, komposisi fungsi dapat digambarkan sebagai:
f(g(x))
Di mana:
x
adalah input awal.g
adalah fungsi pertama yang diterapkan kex
.f
adalah fungsi kedua yang diterapkan ke hasil darig(x)
.
Contoh JavaScript:
“`javascript
function tambahSatu(x) {
return x + 1;
}
function kaliDua(x) {
return x * 2;
}
// Komposisi fungsi: (x + 1) * 2
function komposisi(x) {
return kaliDua(tambahSatu(x));
}
console.log(komposisi(3)); // Output: 8 ((3 + 1) * 2)
“`
Dalam contoh ini, kita memiliki dua fungsi: tambahSatu
dan kaliDua
. Fungsi komposisi
menggabungkan kedua fungsi tersebut, pertama menambahkan 1 ke input, lalu mengalikan hasilnya dengan 2.
Contoh JavaScript (Menggunakan Library):
Library seperti Lodash atau Ramda menyediakan fungsi pembantu untuk komposisi fungsi yang lebih elegan:
“`javascript
import { flow } from ‘lodash’; // Atau import dari Ramda
const tambahSatu = x => x + 1;
const kaliDua = x => x * 2;
const komposisi = flow([tambahSatu, kaliDua]);
console.log(komposisi(3)); // Output: 8
“`
Contoh TypeScript:
“`typescript
function tambahSatu(x: number): number {
return x + 1;
}
function kaliDua(x: number): number {
return x * 2;
}
// Komposisi fungsi: (x + 1) * 2
function komposisi(x: number): number {
return kaliDua(tambahSatu(x));
}
console.log(komposisi(3)); // Output: 8
“`
Manfaat:
- Reuse Kode: Anda dapat menggunakan kembali fungsi yang ada untuk membangun fungsi yang lebih kompleks.
- Readability: Memecah logic yang kompleks menjadi bagian yang lebih kecil dan mudah dipahami.
- Modularitas: Memungkinkan Anda untuk membuat kode yang lebih modular dan mudah dipelihara.
Kapan Menggunakan Komposisi Fungsi:
- Saat Anda memiliki logic yang kompleks yang dapat dipecah menjadi langkah-langkah yang lebih kecil.
- Saat Anda ingin menggunakan kembali fungsi yang ada.
- Saat Anda ingin membuat kode yang lebih modular dan mudah dipelihara.
3. Currying: Spesialisasi Fungsi Secara Bertahap
Currying adalah teknik mengubah fungsi yang menerima banyak argumen menjadi urutan fungsi yang masing-masing menerima satu argumen. Ini memungkinkan Anda untuk menerapkan argumen secara bertahap dan membuat fungsi yang lebih khusus.
Definisi: Currying adalah transformasi fungsi yang menerjemahkan fungsi dari yang mengambil banyak argumen sekaligus, menjadi fungsi yang mengambil satu argumen dan mengembalikan fungsi lain yang menerima argumen yang tersisa satu per satu sampai semua argumen telah diterapkan.
Bagaimana Currying Bekerja:
Alih-alih memanggil fungsi dengan semua argumen sekaligus:
f(a, b, c)
Dengan currying, Anda memanggil serangkaian fungsi:
f(a)(b)(c)
Contoh JavaScript:
“`javascript
function tambah(a, b) {
return a + b;
}
// Fungsi yang di-curry
function tambahCurried(a) {
return function(b) {
return a + b;
}
}
const tambahLima = tambahCurried(5);
console.log(tambahLima(3)); // Output: 8
console.log(tambahCurried(10)(2)); // Output: 12
“`
Dalam contoh ini, tambahCurried
menerima satu argumen (a
) dan mengembalikan fungsi lain yang menerima satu argumen (b
) dan mengembalikan jumlahnya. Kita dapat menggunakan tambahCurried(5)
untuk membuat fungsi baru (tambahLima
) yang selalu menambahkan 5 ke argumennya.
Contoh JavaScript (Menggunakan Arrow Function):
“`javascript
const tambahCurried = a => b => a + b;
const tambahLima = tambahCurried(5);
console.log(tambahLima(3)); // Output: 8
console.log(tambahCurried(10)(2)); // Output: 12
“`
Contoh TypeScript:
“`typescript
const tambahCurried = (a: number) => (b: number): number => a + b;
const tambahLima = tambahCurried(5);
console.log(tambahLima(3)); // Output: 8
console.log(tambahCurried(10)(2)); // Output: 12
“`
Manfaat:
- Fleksibilitas: Anda dapat menerapkan argumen secara bertahap, memungkinkan Anda untuk membuat fungsi yang lebih khusus.
- Reusable: Anda dapat menggunakan kembali fungsi yang di-curry dengan menerapkan argumen yang berbeda.
- Spesialisasi Bertahap: Memungkinkan Anda untuk membuat fungsi yang lebih khusus secara bertahap.
Kapan Menggunakan Currying:
- Saat Anda ingin membuat fungsi yang lebih khusus dari fungsi yang sudah ada.
- Saat Anda ingin menerapkan argumen secara bertahap.
- Saat Anda ingin membuat kode yang lebih fleksibel dan reusable.
4. Fungsi Higher-Order (Higher-Order Functions): Abstraksi dan Kontrol Aliran
Fungsi higher-order adalah fungsi yang menerima fungsi lain sebagai argumen atau mengembalikan fungsi sebagai hasilnya. Mereka adalah alat yang ampuh untuk abstraksi dan kontrol aliran.
Definisi: Fungsi higher-order adalah fungsi yang melakukan salah satu atau kedua hal berikut:
- Menerima satu atau lebih fungsi sebagai argumen.
- Mengembalikan fungsi sebagai hasilnya.
Contoh JavaScript:
“`javascript
function sapa(nama, formatSapaan) {
return formatSapaan(nama);
}
function sapaFormal(nama) {
return “Halo, ” + nama + “!”;
}
function sapaInformal(nama) {
return “Hai, ” + nama + “!”;
}
console.log(sapa(“Andi”, sapaFormal)); // Output: Halo, Andi!
console.log(sapa(“Budi”, sapaInformal)); // Output: Hai, Budi!
“`
Dalam contoh ini, fungsi sapa
adalah fungsi higher-order karena menerima fungsi (formatSapaan
) sebagai argumen.
Contoh JavaScript (map
, filter
, reduce
):
Metode array map
, filter
, dan reduce
adalah contoh klasik dari fungsi higher-order:
“`javascript
const angka = [1, 2, 3, 4, 5];
// Map: Mengubah setiap elemen dalam array
const angkaDikuadratkan = angka.map(angka => angka * angka);
console.log(angkaDikuadratkan); // Output: [1, 4, 9, 16, 25]
// Filter: Memfilter elemen berdasarkan kondisi
const angkaGenap = angka.filter(angka => angka % 2 === 0);
console.log(angkaGenap); // Output: [2, 4]
// Reduce: Menggabungkan elemen array menjadi satu nilai
const jumlah = angka.reduce((akumulator, angka) => akumulator + angka, 0);
console.log(jumlah); // Output: 15
“`
Contoh TypeScript:
“`typescript
function sapa(nama: string, formatSapaan: (nama: string) => string): string {
return formatSapaan(nama);
}
function sapaFormal(nama: string): string {
return “Halo, ” + nama + “!”;
}
function sapaInformal(nama: string): string {
return “Hai, ” + nama + “!”;
}
console.log(sapa(“Andi”, sapaFormal)); // Output: Halo, Andi!
console.log(sapa(“Budi”, sapaInformal)); // Output: Hai, Budi!
“`
Manfaat:
- Abstraksi: Memungkinkan Anda untuk mengabstraksikan logic yang kompleks dan membuat kode yang lebih reusable.
- Kontrol Aliran: Memungkinkan Anda untuk mengontrol aliran eksekusi dengan cara yang lebih fleksibel.
- Reusable: Memungkinkan Anda untuk menggunakan kembali fungsi dengan perilaku yang berbeda.
Kapan Menggunakan Fungsi Higher-Order:
- Saat Anda ingin mengabstraksikan logic yang kompleks.
- Saat Anda ingin mengontrol aliran eksekusi dengan cara yang lebih fleksibel.
- Saat Anda ingin membuat kode yang lebih reusable.
5. Immediately Invoked Function Expressions (IIFEs): Enkapsulasi dan Isolasi Scope
Immediately Invoked Function Expressions (IIFEs) adalah fungsi yang didefinisikan dan dieksekusi segera. Mereka digunakan untuk membuat scope privat dan mencegah polusi namespace global.
Definisi: IIFE adalah fungsi JavaScript yang didefinisikan dan dieksekusi segera setelah didefinisikan.
Mengapa Menggunakan IIFE:
- Enkapsulasi: Menyembunyikan variabel dan fungsi internal dari scope global.
- Isolasi Scope: Mencegah konflik nama dengan variabel dan fungsi di scope global.
Contoh JavaScript:
“`javascript
(function() {
let pesan = “Halo dari IIFE!”;
console.log(pesan); // Output: Halo dari IIFE!
})();
// console.log(pesan); // Error: pesan is not defined
“`
Dalam contoh ini, variabel pesan
didefinisikan di dalam IIFE dan tidak dapat diakses dari luar.
Contoh JavaScript (Dengan Argumen):
“`javascript
(function(nama) {
console.log(“Halo, ” + nama + “!”); // Output: Halo, Andi!
})(“Andi”);
“`
Contoh TypeScript:
“`typescript
(function() {
let pesan: string = “Halo dari IIFE!”;
console.log(pesan);
})();
“`
Manfaat:
- Mencegah Polusi Namespace Global: Meminimalkan risiko konflik nama dengan variabel dan fungsi lain.
- Enkapsulasi Kode: Menyembunyikan detail implementasi internal.
- Kontrol Scope: Memungkinkan Anda untuk mengontrol visibility variabel dan fungsi.
Kapan Menggunakan IIFE:
- Saat Anda ingin mencegah polusi namespace global.
- Saat Anda ingin mengenkapsulasi kode.
- Saat Anda ingin mengontrol scope variabel dan fungsi.
6. Fungsi Generator (Generator Functions): Iterasi yang Efisien dan Keadaan yang Dipertahankan
Fungsi generator adalah fungsi khusus yang dapat dihentikan di tengah eksekusi dan dilanjutkan nanti. Mereka menggunakan kata kunci yield
untuk menghasilkan nilai satu per satu.
Definisi: Fungsi generator adalah fungsi yang dapat menjeda eksekusi dan melanjutkan eksekusi nanti, mempertahankan state-nya.
Bagaimana Menggunakan yield
:
Kata kunci yield
digunakan untuk menghasilkan nilai dari fungsi generator. Setiap kali yield
dipanggil, fungsi menjeda eksekusi dan mengembalikan nilai yang diberikan. Eksekusi dilanjutkan saat metode next()
dari iterator dipanggil.
Contoh JavaScript:
“`javascript
function* hitungSampaiTiga() {
yield 1;
yield 2;
yield 3;
}
const iterator = hitungSampaiTiga();
console.log(iterator.next().value); // Output: 1
console.log(iterator.next().value); // Output: 2
console.log(iterator.next().value); // Output: 3
console.log(iterator.next().done); // Output: true
“`
Dalam contoh ini, fungsi hitungSampaiTiga
adalah fungsi generator yang menghasilkan angka 1, 2, dan 3 satu per satu. Setiap kali yield
dipanggil, fungsi menjeda eksekusi dan mengembalikan nilai. Eksekusi dilanjutkan saat metode next()
dari iterator dipanggil.
Contoh TypeScript:
“`typescript
function* hitungSampaiTiga(): Generator
yield 1;
yield 2;
yield 3;
}
const iterator = hitungSampaiTiga();
console.log(iterator.next().value); // Output: 1
console.log(iterator.next().value); // Output: 2
console.log(iterator.next().value); // Output: 3
console.log(iterator.next().done); // Output: true
“`
Manfaat:
- Iterasi yang Efisien: Menghasilkan nilai satu per satu sesuai permintaan, menghemat memori.
- Keadaan yang Dipertahankan: Mempertahankan state antara panggilan
yield
. - Asynchronous Programming yang Mudah Dibaca: Memungkinkan Anda untuk menulis kode asynchronous yang terlihat seperti kode synchronous (dengan menggunakan
async
/await
).
Kapan Menggunakan Fungsi Generator:
- Saat Anda ingin melakukan iterasi yang efisien atas kumpulan data yang besar.
- Saat Anda ingin mempertahankan state antara iterasi.
- Saat Anda ingin menulis kode asynchronous yang lebih mudah dibaca.
7. Fungsi Rekursif (Recursive Functions): Memecahkan Masalah dengan Mengulangi Diri Sendiri
Fungsi rekursif adalah fungsi yang memanggil dirinya sendiri untuk memecahkan masalah. Mereka sangat berguna untuk masalah yang dapat dipecah menjadi submasalah yang lebih kecil dari jenis yang sama.
Definisi: Fungsi rekursif adalah fungsi yang memanggil dirinya sendiri, baik secara langsung maupun tidak langsung.
Bagaimana Rekursi Bekerja:
- Kasus Dasar (Base Case): Kondisi yang menghentikan rekursi. Tanpa kasus dasar, fungsi akan memanggil dirinya sendiri tanpa henti, menyebabkan stack overflow.
- Langkah Rekursif (Recursive Step): Fungsi memanggil dirinya sendiri dengan input yang lebih kecil, mendekati kasus dasar.
Contoh JavaScript:
“`javascript
function faktorial(n) {
if (n === 0) {
return 1; // Kasus dasar
} else {
return n * faktorial(n – 1); // Langkah rekursif
}
}
console.log(faktorial(5)); // Output: 120
“`
Dalam contoh ini, fungsi faktorial
memanggil dirinya sendiri dengan input yang lebih kecil (n - 1
) sampai mencapai kasus dasar (n === 0
).
Contoh TypeScript:
“`typescript
function faktorial(n: number): number {
if (n === 0) {
return 1; // Kasus dasar
} else {
return n * faktorial(n – 1); // Langkah rekursif
}
}
console.log(faktorial(5)); // Output: 120
“`
Manfaat:
- Elegansi: Dapat memecahkan masalah yang kompleks dengan kode yang relatif pendek dan mudah dipahami.
- Memecahkan Masalah yang Kompleks: Memecah masalah menjadi submasalah yang lebih kecil dan mudah dikelola.
- Sesuai untuk Masalah yang Secara Alami Rekursif: Sangat cocok untuk masalah seperti traversal tree atau grafik.
Kapan Menggunakan Fungsi Rekursif:
- Saat Anda ingin memecahkan masalah yang dapat dipecah menjadi submasalah yang lebih kecil dari jenis yang sama.
- Saat Anda ingin menulis kode yang elegan dan mudah dipahami.
- Saat masalah tersebut secara alami rekursif (misalnya, traversal tree).
Kesimpulan: Menerapkan Bentuk Fungsi Terbaik dalam Praktik
Kita telah menjelajahi 7 bentuk fungsi yang dapat meningkatkan keterbacaan, kegunaan, dan kepercayaan pada kode JavaScript dan TypeScript Anda. Mari kita rangkum:
- Fungsi Murni: Predictability dan testability.
- Fungsi Komposisi: Building blocks untuk logic kompleks.
- Currying: Spesialisasi fungsi secara bertahap.
- Fungsi Higher-Order: Abstraksi dan kontrol aliran.
- IIFEs: Enkapsulasi dan isolasi scope.
- Fungsi Generator: Iterasi yang efisien dan keadaan yang dipertahankan.
- Fungsi Rekursif: Memecahkan masalah dengan mengulangi diri sendiri.
Tips untuk Menerapkan Bentuk Fungsi Terbaik:
- Pilihlah Bentuk yang Tepat: Pertimbangkan masalah yang Anda coba pecahkan dan pilih bentuk fungsi yang paling sesuai.
- Konsisten: Gunakan bentuk fungsi yang sama secara konsisten di seluruh codebase Anda.
- Dokumentasikan Kode Anda: Jelaskan mengapa Anda memilih bentuk fungsi tertentu.
- Latihan: Semakin banyak Anda berlatih menggunakan bentuk fungsi yang berbeda, semakin baik Anda dalam memilih yang terbaik untuk pekerjaan itu.
Ingatlah, tujuan utama adalah untuk menulis kode yang mudah dibaca, dipahami, dan dipelihara. Bereksperimenlah dengan bentuk fungsi yang berbeda dan temukan yang paling sesuai dengan gaya dan kebutuhan Anda. Selamat mencoba!
“`