Wednesday

18-06-2025 Vol 19

Paracetamol.ts💊| #36: Explica este código TypeScript

Paracetamol.ts 💊 #36: Membedah dan Memahami Kode TypeScript Kompleks

Selamat datang di bedah kode mendalam lainnya! Dalam edisi ke-36 ini, kita akan menyelami file paracetamol.ts. Nama yang terdengar sederhana, tapi jangan terkecoh—kode TypeScript ini menyimpan banyak lapisan kompleksitas dan pembelajaran berharga. Tujuan kita adalah untuk membongkar kode baris demi baris, menjelaskan logika di baliknya, dan memahami bagaimana setiap bagian berkontribusi pada keseluruhan fungsi.

Artikel ini ditujukan untuk pengembang TypeScript dengan tingkat menengah hingga mahir yang ingin mempertajam keterampilan mereka dalam membaca, memahami, dan memodifikasi kode yang kompleks. Bersiaplah untuk petualangan mendalam ke dalam dunia tipe, antarmuka, fungsi tingkat tinggi, dan pola desain yang cerdas!

Mengapa Mempelajari paracetamol.ts?

Anda mungkin bertanya, mengapa kita memilih kode dengan nama seperti ini? Alasannya sederhana: kode dengan nama yang tidak terduga seringkali menyembunyikan solusi yang cerdas dan desain yang menarik. Dengan menganalisis kode ini, kita akan:

  1. Meningkatkan Keterampilan Membaca Kode: Membiasakan diri dengan sintaks TypeScript yang kompleks dan pola desain.
  2. Memahami Pola Desain: Mengidentifikasi dan memahami penerapan pola desain umum dalam TypeScript.
  3. Mempelajari Teknik Tingkat Lanjut: Mengeksplorasi penggunaan tipe generik, tipe union, dan fitur TypeScript lainnya yang canggih.
  4. Meningkatkan Kemampuan Debugging: Belajar bagaimana melacak logika kode yang rumit dan mengidentifikasi potensi masalah.
  5. Mendapatkan Inspirasi: Menemukan cara baru untuk menulis kode TypeScript yang efisien, mudah dibaca, dan mudah dipelihara.

Kerangka Artikel: Membongkar paracetamol.ts Langkah Demi Langkah

Untuk memastikan pemahaman yang komprehensif, kita akan mengikuti kerangka terstruktur:

  1. Gambaran Umum Kode: Memulai dengan tinjauan tingkat tinggi dari keseluruhan file paracetamol.ts.
  2. Analisis Impor dan Ekspor: Memeriksa modul mana yang diimpor dan diekspor, dan bagaimana mereka berinteraksi.
  3. Definisi Tipe: Menyelami definisi tipe (antarmuka, tipe alias, dll.) dan memahami struktur data yang digunakan.
  4. Analisis Fungsi: Membongkar setiap fungsi, menjelaskan tujuannya, input, output, dan logika internalnya.
  5. Pola Desain: Mengidentifikasi pola desain apa pun yang digunakan (misalnya, Factory, Singleton, Observer).
  6. Penanganan Kesalahan: Menganalisis bagaimana kesalahan ditangani dan bagaimana kode bereaksi terhadap kondisi tak terduga.
  7. Pengujian (Jika Ada): Memeriksa pengujian unit apa pun yang tersedia untuk memahami bagaimana kode tersebut diuji dan divalidasi.
  8. Refactoring dan Peningkatan: Menjelajahi potensi area untuk refactoring dan peningkatan dalam kode.
  9. Kesimpulan: Merangkum poin-poin penting dan memberikan saran untuk pembelajaran lebih lanjut.

1. Gambaran Umum Kode paracetamol.ts

Pertama-tama, kita perlu melihat kode itu sendiri. Asumsikan kita memiliki file paracetamol.ts dengan konten berikut (ini adalah contoh, kode sebenarnya mungkin berbeda):


    // paracetamol.ts

    /**
     * Deskripsi singkat dari modul ini.
     * Mungkin terkait dengan manajemen resep atau kalkulasi dosis.
     */

    import { DosageCalculator } from './dosage-calculator';
    import { Patient } from './patient';
    import { Prescription } from './prescription';

    export interface ParacetamolOptions {
      weight: number; // in kg
      age: number; // in years
      indication: string;
    }

    export class Paracetamol {
      private dosageCalculator: DosageCalculator;

      constructor(private patient: Patient) {
        this.dosageCalculator = new DosageCalculator();
      }

      calculateDosage(options: ParacetamolOptions): number {
        // Logika kompleks untuk menghitung dosis parasetamol
        // berdasarkan berat badan, usia, dan indikasi pasien.
        const baseDosage = this.dosageCalculator.calculateBaseDosage(options.weight, options.age);
        const indicationFactor = this.getIndicationFactor(options.indication);
        const finalDosage = baseDosage * indicationFactor;

        return this.adjustDosageForPatient(finalDosage, this.patient);
      }

      private getIndicationFactor(indication: string): number {
        switch (indication) {
          case 'fever':
            return 1.0;
          case 'pain':
            return 1.2;
          case 'inflammation':
            return 1.5;
          default:
            return 1.0;
        }
      }

      private adjustDosageForPatient(dosage: number, patient: Patient): number {
        // Logika tambahan untuk menyesuaikan dosis berdasarkan kondisi pasien
        if (patient.hasKidneyDisease()) {
          return dosage * 0.75; // Kurangi dosis untuk pasien dengan penyakit ginjal
        }
        return dosage;
      }

      static createPrescription(patient: Patient, dosage: number): Prescription {
        // Menghasilkan objek Prescription
        return new Prescription(patient, "Paracetamol", dosage);
      }
    }
  

Dari kode ini, kita dapat melihat:

  • Kode tersebut mungkin terkait dengan kalkulasi dosis parasetamol.
  • Kode tersebut bergantung pada modul lain seperti DosageCalculator, Patient, dan Prescription.
  • Kode tersebut mendefinisikan antarmuka ParacetamolOptions untuk mengkonfigurasi perhitungan dosis.
  • Kode tersebut memiliki kelas Paracetamol yang berisi logika utama.

2. Analisis Impor dan Ekspor

Mari kita periksa impor dan ekspor secara lebih rinci:

  • Impor:
    1. import { DosageCalculator } from './dosage-calculator';: Mengimpor kelas DosageCalculator dari file dosage-calculator.ts. Kelas ini kemungkinan berisi logika untuk menghitung dosis dasar.
    2. import { Patient } from './patient';: Mengimpor kelas Patient dari file patient.ts. Kelas ini kemungkinan mewakili pasien dan berisi informasi tentang kondisi mereka.
    3. import { Prescription } from './prescription';: Mengimpor kelas Prescription dari file prescription.ts. Kelas ini kemungkinan mewakili resep dan berisi informasi tentang obat, dosis, dan pasien.
  • Ekspor:
    1. export interface ParacetamolOptions: Mengekspor antarmuka ParacetamolOptions. Antarmuka ini digunakan untuk menentukan opsi yang diperlukan untuk menghitung dosis parasetamol.
    2. export class Paracetamol: Mengekspor kelas Paracetamol. Kelas ini berisi logika utama untuk menghitung dosis parasetamol dan membuat resep.

Memahami impor dan ekspor membantu kita memahami bagaimana modul ini berinteraksi dengan bagian lain dari aplikasi.

3. Definisi Tipe

TypeScript mengandalkan tipe untuk meningkatkan keamanan dan keterbacaan kode. Mari kita periksa definisi tipe dalam paracetamol.ts:

  • ParacetamolOptions Interface:
  • 
          export interface ParacetamolOptions {
            weight: number; // in kg
            age: number; // in years
            indication: string;
          }
        

    Antarmuka ini mendefinisikan tipe objek yang digunakan untuk mengkonfigurasi perhitungan dosis parasetamol. Ini mencakup:

    • weight: Berat badan pasien dalam kilogram (tipe number).
    • age: Usia pasien dalam tahun (tipe number).
    • indication: Indikasi medis untuk penggunaan parasetamol (tipe string).

Definisi tipe yang jelas meningkatkan keterbacaan kode dan membantu mencegah kesalahan runtime.

4. Analisis Fungsi

Sekarang, mari kita bedah setiap fungsi dalam kelas Paracetamol:

  1. Konstruktor:
  2. 
          constructor(private patient: Patient) {
            this.dosageCalculator = new DosageCalculator();
          }
        

    Konstruktor menerima objek Patient sebagai argumen dan menginisialisasi properti dosageCalculator dengan instance baru dari kelas DosageCalculator. Penggunaan `private patient` adalah shorthand TypeScript untuk mendefinisikan properti instance dan menginisialisasinya dari argumen konstruktor.

  3. calculateDosage Function:
  4. 
          calculateDosage(options: ParacetamolOptions): number {
            // Logika kompleks untuk menghitung dosis parasetamol
            // berdasarkan berat badan, usia, dan indikasi pasien.
            const baseDosage = this.dosageCalculator.calculateBaseDosage(options.weight, options.age);
            const indicationFactor = this.getIndicationFactor(options.indication);
            const finalDosage = baseDosage * indicationFactor;
    
            return this.adjustDosageForPatient(finalDosage, this.patient);
          }
        

    Fungsi ini adalah jantung dari kelas Paracetamol. Fungsi ini menerima objek ParacetamolOptions sebagai argumen dan menghitung dosis parasetamol yang sesuai. Berikut adalah rincian langkah-langkahnya:

    • Menghitung dosis dasar menggunakan metode calculateBaseDosage dari kelas DosageCalculator.
    • Mendapatkan faktor indikasi menggunakan metode getIndicationFactor berdasarkan indikasi yang diberikan.
    • Mengalikan dosis dasar dengan faktor indikasi untuk mendapatkan dosis akhir.
    • Menyesuaikan dosis akhir berdasarkan kondisi pasien menggunakan metode adjustDosageForPatient.
    • Mengembalikan dosis akhir.
  5. getIndicationFactor Function:
  6. 
          private getIndicationFactor(indication: string): number {
            switch (indication) {
              case 'fever':
                return 1.0;
              case 'pain':
                return 1.2;
              case 'inflammation':
                return 1.5;
              default:
                return 1.0;
            }
          }
        

    Fungsi ini menerima indikasi sebagai argumen dan mengembalikan faktor yang sesuai. Faktor ini digunakan untuk menyesuaikan dosis berdasarkan indikasi medis. Penggunaan `switch` statement membuatnya mudah untuk menambahkan indikasi baru di masa mendatang.

  7. adjustDosageForPatient Function:
  8. 
          private adjustDosageForPatient(dosage: number, patient: Patient): number {
            // Logika tambahan untuk menyesuaikan dosis berdasarkan kondisi pasien
            if (patient.hasKidneyDisease()) {
              return dosage * 0.75; // Kurangi dosis untuk pasien dengan penyakit ginjal
            }
            return dosage;
          }
        

    Fungsi ini menerima dosis dan objek Patient sebagai argumen dan menyesuaikan dosis berdasarkan kondisi pasien. Dalam contoh ini, dosis dikurangi untuk pasien dengan penyakit ginjal. Ini menunjukkan bagaimana dosis dapat disesuaikan berdasarkan kondisi medis tertentu.

  9. createPrescription Function:
  10. 
          static createPrescription(patient: Patient, dosage: number): Prescription {
            // Menghasilkan objek Prescription
            return new Prescription(patient, "Paracetamol", dosage);
          }
        

    Fungsi statis ini membuat objek Prescription baru. Ini menerima objek Patient dan dosis sebagai argumen dan mengembalikan instance baru dari kelas Prescription. Fungsi statis digunakan untuk membuat metode pabrik yang tidak memerlukan instance kelas Paracetamol.

5. Pola Desain

Meskipun kode ini relatif sederhana, kita dapat mengidentifikasi beberapa pola desain yang potensial:

  • Dependency Injection: Kelas Paracetamol menerima objek Patient dalam konstruktornya. Ini adalah contoh Dependency Injection, di mana ketergantungan (dalam hal ini, objek Patient) diberikan kepada kelas daripada dibuat di dalam kelas. Ini meningkatkan fleksibilitas dan kemudahan pengujian.
  • Factory Method (Potensial): Fungsi `createPrescription` dapat dilihat sebagai implementasi sederhana dari Factory Method. Ini menyediakan cara untuk membuat objek `Prescription` tanpa harus secara langsung menggunakan konstruktor kelas `Prescription`. Ini memungkinkan kita untuk mengubah cara objek `Prescription` dibuat tanpa mempengaruhi kode yang menggunakan metode `createPrescription`.

6. Penanganan Kesalahan

Dalam kode contoh ini, penanganan kesalahan tidak eksplisit. Dalam aplikasi produksi, kita perlu mempertimbangkan hal-hal berikut:

  • Validasi Input: Memastikan bahwa nilai dalam ParacetamolOptions valid (misalnya, berat badan dan usia harus positif).
  • Penanganan Kasus Edge: Mempertimbangkan kasus edge seperti dosis yang terlalu tinggi atau terlalu rendah.
  • Penanganan Kesalahan Tingkat Lanjut: Menggunakan blok try...catch untuk menangkap kesalahan yang tidak terduga dan menanganinya dengan tepat (misalnya, mencatat kesalahan atau menampilkan pesan kesalahan kepada pengguna).

Contoh penanganan kesalahan:


    calculateDosage(options: ParacetamolOptions): number {
      try {
        if (options.weight <= 0 || options.age <= 0) {
          throw new Error("Berat badan dan usia harus positif.");
        }

        const baseDosage = this.dosageCalculator.calculateBaseDosage(options.weight, options.age);
        const indicationFactor = this.getIndicationFactor(options.indication);
        const finalDosage = baseDosage * indicationFactor;

        return this.adjustDosageForPatient(finalDosage, this.patient);

      } catch (error) {
        console.error("Error menghitung dosis:", error);
        return -1; // Atau lempar kembali kesalahan, tergantung pada kebutuhan.
      }
    }
  

7. Pengujian (Jika Ada)

Pengujian unit sangat penting untuk memastikan bahwa kode berfungsi dengan benar. Meskipun kita tidak memiliki pengujian unit spesifik untuk kode ini, berikut adalah beberapa contoh pengujian yang mungkin:

  • Pengujian calculateDosage: Menguji dengan berbagai kombinasi berat badan, usia, dan indikasi untuk memastikan bahwa dosis yang dihitung benar.
  • Pengujian getIndicationFactor: Memastikan bahwa faktor indikasi yang benar dikembalikan untuk setiap indikasi.
  • Pengujian adjustDosageForPatient: Memastikan bahwa dosis disesuaikan dengan benar untuk pasien dengan kondisi medis tertentu.
  • Pengujian createPrescription: Memastikan bahwa objek Prescription dibuat dengan benar.

Contoh pengujian menggunakan Jest:


    // paracetamol.test.ts

    import { Paracetamol, ParacetamolOptions } from './paracetamol';
    import { Patient } from './patient'; // Anggap ada file patient.ts

    describe('Paracetamol', () => {
      let patient: Patient;
      let paracetamol: Paracetamol;

      beforeEach(() => {
        patient = new Patient("John Doe", 30, false); // Anggap konstruktor Patient ada
        paracetamol = new Paracetamol(patient);
      });

      it('should calculate the correct dosage for fever', () => {
        const options: ParacetamolOptions = {
          weight: 70,
          age: 30,
          indication: 'fever',
        };
        const dosage = paracetamol.calculateDosage(options);
        // Asumsikan dosageCalculator.calculateBaseDosage(70, 30) mengembalikan 500
        expect(dosage).toBeCloseTo(500); // Menggunakan toBeCloseTo untuk menghindari masalah floating point
      });

      it('should adjust dosage for patients with kidney disease', () => {
          patient = new Patient("Jane Doe", 40, true); //  Jane Doe memiliki penyakit ginjal
          paracetamol = new Paracetamol(patient);

          const options: ParacetamolOptions = {
              weight: 60,
              age: 40,
              indication: 'pain'
          };
          const dosage = paracetamol.calculateDosage(options);
          // Asumsikan dosageCalculator.calculateBaseDosage(60, 40) mengembalikan 400 dan indication factor adalah 1.2
          // Maka 400 * 1.2 * 0.75 = 360
          expect(dosage).toBeCloseTo(360);
      });

      it('should throw an error if weight or age is negative', () => {
        const options: ParacetamolOptions = {
          weight: -10,
          age: 30,
          indication: 'fever',
        };
        expect(() => paracetamol.calculateDosage(options)).toThrowError("Berat badan dan usia harus positif.");
      });
    });
  

8. Refactoring dan Peningkatan

Berikut adalah beberapa potensi area untuk refactoring dan peningkatan:

  • Ekstraksi Konstanta: Mengganti angka-angka ajaib (seperti 0.75 dalam adjustDosageForPatient) dengan konstanta bernama untuk meningkatkan keterbacaan.
  • Penggunaan Enum: Mengganti string literal untuk indikasi dengan enum untuk meningkatkan keamanan tipe dan mencegah kesalahan ketik.
  • Ekstraksi Logika: Memindahkan logika kompleks dari calculateDosage ke fungsi terpisah untuk meningkatkan modularitas.
  • Validasi Input yang Lebih Kuat: Menambahkan validasi input yang lebih komprehensif untuk memastikan bahwa data yang diterima valid.
  • Penggunaan Tipe Data yang Lebih Spesifik: Menggunakan tipe data yang lebih spesifik untuk representasi data (misalnya, menggunakan tipe khusus untuk berat badan dan usia).

Contoh penggunaan Enum:


    export enum Indication {
      Fever = 'fever',
      Pain = 'pain',
      Inflammation = 'inflammation',
    }

    export interface ParacetamolOptions {
      weight: number;
      age: number;
      indication: Indication; // Perhatikan perubahan tipe di sini
    }

    // ...di dalam kelas Paracetamol...

    private getIndicationFactor(indication: Indication): number {
      switch (indication) {
        case Indication.Fever:
          return 1.0;
        case Indication.Pain:
          return 1.2;
        case Indication.Inflammation:
          return 1.5;
        default:
          return 1.0;
      }
    }
  

9. Kesimpulan

Dalam artikel ini, kita telah membedah kode TypeScript paracetamol.ts. Kita telah memeriksa impor dan ekspor, definisi tipe, fungsi, pola desain potensial, penanganan kesalahan, dan pengujian. Kita juga telah mengidentifikasi area untuk refactoring dan peningkatan.

Pembelajaran utama meliputi:

  • Pentingnya definisi tipe yang jelas dalam TypeScript.
  • Bagaimana memecah logika yang kompleks menjadi fungsi yang lebih kecil dan mudah dikelola.
  • Bagaimana menggunakan pola desain untuk meningkatkan fleksibilitas dan kemudahan pengujian.
  • Pentingnya penanganan kesalahan dan pengujian unit.

Untuk pembelajaran lebih lanjut, pertimbangkan hal-hal berikut:

  • Mempelajari lebih lanjut tentang pola desain dan penerapannya dalam TypeScript.
  • Mempelajari tentang teknik penanganan kesalahan yang lebih canggih.
  • Berlatih menulis pengujian unit untuk berbagai jenis kode.
  • Membaca dan menganalisis kode sumber proyek open source untuk mempelajari praktik terbaik dari pengembang berpengalaman.

Semoga artikel ini bermanfaat! Teruslah berlatih dan tingkatkan keterampilan TypeScript Anda.

```

omcoding

Leave a Reply

Your email address will not be published. Required fields are marked *