Objek dan struktur data memainkan peran penting dalam pengembangan perangkat lunak, dan dengan mengikuti praktik kode yang bersih, kita dapat meningkatkan keterbacaan, pemeliharaan, dan fleksibilitas kode kita. Kami akan mendalami enkapsulasi, pengubah akses, metode pengambil dan penyetel, komposisi pewarisan, meminimalkan keadaan yang bisa berubah, dan Prinsip Tanggung Jawab Tunggal (SRP). Ada alasan mengapa kami merahasiakan variabel kami. Kami tidak ingin orang lain bergantung pada mereka. Kami ingin menjaga kebebasan untuk mengubah jenis atau penerapannya sesuai keinginan atau dorongan hati.

1. Mengenkapsulasi Data

Enkapsulasi mengacu pada menggabungkan data dan perilaku terkait bersama-sama dalam suatu kelas atau antarmuka. Ini memungkinkan kami mengontrol akses ke data dan menyembunyikan detail implementasi internal. Dengan merangkum data, kita dapat menyediakan antarmuka yang jelas untuk berinteraksi dengan objek.

class Car {
  private brand: string;
  private model: string;
  
  constructor(brand: string, model: string) {
    this.brand = brand;
    this.model = model;
  }
  
  public getBrand(): string {
    return this.brand;
  }
  
  public getModel(): string {
    return this.model;
  }
}

Dalam contoh ini, kami merangkum properti brand dan model dalam kelas Car. Kami menggunakan pengubah akses pribadi untuk membatasi akses langsung ke properti ini. Sebagai gantinya, kami menyediakan metode pengambil publik (getBrand() dan getModel()) untuk mengakses nilai. Enkapsulasi ini memastikan bahwa detail internal kelas Car disembunyikan, dan data diakses melalui antarmuka yang terkontrol.

2. Menghindari Metode Pengambil dan Penyetel

Metode pengambil dan penyetel tradisional digunakan untuk mengakses dan mengubah properti objek. Namun, hal tersebut dapat menyebabkan pelanggaran terhadap Hukum Demeter, yang mengakibatkan kode yang sangat erat kaitannya. Sebagai gantinya, kita dapat menggunakan properti, yang memberikan sintaksis yang lebih bersih dan meningkatkan keterbacaan.

class Rectangle {
  private width: number;
  private height: number;
  
  constructor(width: number, height: number) {
    this.width = width;
    this.height = height;
  }
  
  public get area(): number {
    return this.width * this.height;
  }
  
  public setDimensions(width: number, height: number): void {
    this.width = width;
    this.height = height;
  }
}

Dalam contoh ini, kita menggunakan properti area untuk menghitung luas persegi panjang. Daripada memanggil metode terpisah seperti calculateArea(), kita dapat mengakses area tersebut secara langsung seolah-olah itu adalah properti biasa. Selain itu, kami menyediakan metode setDimensions() untuk memperbarui dimensi persegi panjang, sehingga menghindari kebutuhan metode pengambil dan penyetel terpisah.

3. Mengutamakan Komposisi dibandingkan Warisan

Warisan memungkinkan kita membuat objek baru dengan mewarisi properti dan perilaku dari objek yang sudah ada. Namun, hal ini dapat menyebabkan keterkaitan antar kelas dan membuat kode menjadi kurang fleksibel. Komposisi, di sisi lain, mempromosikan basis kode yang lebih fleksibel dan mudah dipelihara dengan menggabungkan objek yang lebih sederhana untuk membangun objek yang kompleks.

class Engine {
  public start(): void {
    console.log('Engine started');
  }
}

class Car {
  private engine: Engine;
  
  constructor() {
    this.engine = new Engine();
  }
  
  public startEngine(): void {
    this.engine.start();
  }
}

Dalam contoh ini, kami lebih menyukai komposisi daripada warisan. Daripada membuat kelas Car yang memperluas kelas Engine, kita membuat kelas Engine terpisah dan memasukkannya sebagai properti dalam kelas Car. Pendekatan komposisi ini memungkinkan kita dengan mudah menukar implementasi mesin yang berbeda tanpa mempengaruhi kelas Car itu sendiri.

4. Meminimalkan Status yang Dapat Diubah

Status yang dapat diubah mengacu pada objek atau data yang dapat diubah setelah pembuatan. Meskipun mutabilitas terkadang diperlukan, meminimalkan keadaan yang bisa berubah dapat mengurangi kompleksitas dan meningkatkan kemampuan pemeliharaan kode. Mendukung kekekalan membuat kode lebih mudah untuk dipikirkan dan membantu mencegah efek samping yang tidak diinginkan.

function calculateTotalPrice(prices) {
  let totalPrice = 0;

  for (const price of prices) {
    totalPrice += price;
  }

  return totalPrice;
}

const prices = [10, 20, 30, 40];
const total = calculateTotalPrice(prices);

Dalam contoh JavaScript ini, kami menghitung harga total dengan menjumlahkan serangkaian harga. Variabel totalPrice dideklarasikan menggunakan kata kunci let untuk memungkinkan mutasi dalam loop. Namun, array prices tetap tidak dapat diubah. Dengan meminimalkan keadaan yang bisa berubah dan menghindari mutasi variabel yang tidak perlu, kami membuat kode yang lebih mudah diprediksi dan dipelihara.

5. Mengikuti Prinsip Tanggung Jawab Tunggal (SRP)

Prinsip Tanggung Jawab Tunggal (SRP) menyatakan bahwa suatu objek atau fungsi harus mempunyai tanggung jawab tunggal atau melakukan satu hal dengan baik. Dengan mengikuti SRP, kami membuat komponen yang lebih kecil dan fokus sehingga lebih mudah dipahami, diuji, dan dipelihara.

class Logger {
  public logError(message: string): void {
    // Log the error message to a file or console
  }
  
  public logMetric(metric: string, value: number): void {
    // Log the metric and its value to a monitoring system
  }
}

class PaymentProcessor {
  private logger: Logger;
  
  constructor(logger: Logger) {
    this.logger = logger;
  }
  
  public processPayment(amount: number): void {
    try {
      // Process the payment logic
    } catch (error) {
      this.logger.logError('Payment processing failed');
    }
  }
}

Dalam contoh ini, kami mendemonstrasikan SRP dengan memisahkan kekhawatiran menjadi dua kelas: Logger dan PaymentProcessor. Kelas Logger bertanggung jawab atas kesalahan dan metrik pencatatan, sedangkan kelas PaymentProcessor hanya berfokus pada pemrosesan pembayaran. Dengan mengisolasi tanggung jawab, setiap kelas menjadi lebih kohesif dan lebih mudah dipahami.

Kesimpulan

Objek dan struktur data merupakan landasan dasar pengembangan perangkat lunak. Dengan menerapkan prinsip kode bersih pada objek dan struktur data, kita dapat meningkatkan keterbacaan, pemeliharaan, dan fleksibilitas kode kita. Sepanjang bab ini, kita mengeksplorasi enkapsulasi data, menghindari metode pengambil dan penyetel, lebih mengutamakan komposisi daripada pewarisan, meminimalkan keadaan yang bisa berubah, dan mematuhi Prinsip Tanggung Jawab Tunggal (SRP). Dengan mengikuti prinsip-prinsip ini dan menyesuaikannya dengan kebutuhan spesifik proyek kami, kami dapat menulis kode yang lebih bersih dan kuat.