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:
- Meningkatkan Keterampilan Membaca Kode: Membiasakan diri dengan sintaks TypeScript yang kompleks dan pola desain.
- Memahami Pola Desain: Mengidentifikasi dan memahami penerapan pola desain umum dalam TypeScript.
- Mempelajari Teknik Tingkat Lanjut: Mengeksplorasi penggunaan tipe generik, tipe union, dan fitur TypeScript lainnya yang canggih.
- Meningkatkan Kemampuan Debugging: Belajar bagaimana melacak logika kode yang rumit dan mengidentifikasi potensi masalah.
- 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:
- Gambaran Umum Kode: Memulai dengan tinjauan tingkat tinggi dari keseluruhan file
paracetamol.ts
. - Analisis Impor dan Ekspor: Memeriksa modul mana yang diimpor dan diekspor, dan bagaimana mereka berinteraksi.
- Definisi Tipe: Menyelami definisi tipe (antarmuka, tipe alias, dll.) dan memahami struktur data yang digunakan.
- Analisis Fungsi: Membongkar setiap fungsi, menjelaskan tujuannya, input, output, dan logika internalnya.
- Pola Desain: Mengidentifikasi pola desain apa pun yang digunakan (misalnya, Factory, Singleton, Observer).
- Penanganan Kesalahan: Menganalisis bagaimana kesalahan ditangani dan bagaimana kode bereaksi terhadap kondisi tak terduga.
- Pengujian (Jika Ada): Memeriksa pengujian unit apa pun yang tersedia untuk memahami bagaimana kode tersebut diuji dan divalidasi.
- Refactoring dan Peningkatan: Menjelajahi potensi area untuk refactoring dan peningkatan dalam kode.
- 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
, danPrescription
. - 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:
import { DosageCalculator } from './dosage-calculator';
: Mengimpor kelasDosageCalculator
dari filedosage-calculator.ts
. Kelas ini kemungkinan berisi logika untuk menghitung dosis dasar.import { Patient } from './patient';
: Mengimpor kelasPatient
dari filepatient.ts
. Kelas ini kemungkinan mewakili pasien dan berisi informasi tentang kondisi mereka.import { Prescription } from './prescription';
: Mengimpor kelasPrescription
dari fileprescription.ts
. Kelas ini kemungkinan mewakili resep dan berisi informasi tentang obat, dosis, dan pasien.- Ekspor:
export interface ParacetamolOptions
: Mengekspor antarmukaParacetamolOptions
. Antarmuka ini digunakan untuk menentukan opsi yang diperlukan untuk menghitung dosis parasetamol.export class Paracetamol
: Mengekspor kelasParacetamol
. 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 (tipenumber
).age
: Usia pasien dalam tahun (tipenumber
).indication
: Indikasi medis untuk penggunaan parasetamol (tipestring
).
Definisi tipe yang jelas meningkatkan keterbacaan kode dan membantu mencegah kesalahan runtime.
4. Analisis Fungsi
Sekarang, mari kita bedah setiap fungsi dalam kelas Paracetamol
:
- Konstruktor:
calculateDosage
Function:- Menghitung dosis dasar menggunakan metode
calculateBaseDosage
dari kelasDosageCalculator
. - 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.
getIndicationFactor
Function:adjustDosageForPatient
Function:createPrescription
Function:
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.
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:
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.
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.
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 objekPatient
dalam konstruktornya. Ini adalah contoh Dependency Injection, di mana ketergantungan (dalam hal ini, objekPatient
) 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 objekPrescription
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
dalamadjustDosageForPatient
) 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.
```