Development, Continuous Integration
Refactoring & Design Pattern
Berikut merupakan Best Practice yang ada terkait dengan Refactoring & Design Pattern.
Design Pattern
Data Transfer Object (DTO) Pattern:
Digunakan untuk mentransfer data antara sistem, Tujuan utama dari DTO adalah untuk mengurangi jumlah panggilan
jaringan serta menyediakan kelas yang independen dari lapisan teknologi tertentu.
Dalam aplikasi kami, kami menggunakan Django REST Framework khususnya pada ‘GetUserProfileSerializer’,
untuk mentransformasi objek model Django (Profile) menjadi format yang sesuai untuk dikirimkan melalui API.
Berikut adalah contoh bagaimana ‘GetUserProfileSerializer’ dianggap sebagai DTO:
Dalam kode di atas, ‘GetUserProfileSerializer’ digunakan untuk mengubah objek model Django Profile menjadi
representasi yang sesuai untuk dikirimkan melalui API. Hal ini memungkinkan saya untuk mengontrol bagaimana
data dikirim dan diterima oleh klien.
Misalnya, jika saya memiliki model Profile dengan beberapa atribut seperti nama_lengkap, email, dan alamat, maka
saya dapat menggunakan ‘GetUserProfileSerializer’ untuk mengubahnya menjadi format JSON yang sesuai untuk
dapat dikirim melalui API seperti berikut:
{
"nama_lengkap": "Nama Lenkap",
"email": "nama.lengkap@contoh.com",
"alamat": "123 Jalan Jalan"
}
Service Layer:
Merupakan lapisan dalam aplikasi yang bertanggung jawab untuk menyediakan logika bisnis. Tujuannya adalah
untuk mengisolasi logika bisnis dari implementasi teknis seperti database.
Dalam kode saya ‘UserProfileService’ berfungsi sebagai service layer yang bertanggung jawab untuk menyediakan
logika bisnis terkait profil pengguna.
Saya membuat kelas ‘UserProfileEditService’ yang bertanggung jawab untuk menangani operasi penyuntingan
profil pengguna. Dengan memisahkan logika penyuntingan profil ke dalam kelas service terpisah, saya
mengisolasi tanggung jawab ini dan membuat ‘UserProfileService’ lebih fokus pada operasi lain terkait profil
pengguna.
Berikut adalah UserProfileEditService dalam UserProfileService:
Dengan begitu saya memisahkan logika penyuntingan profil ke dalam kelas service terpisah dan mempertahankan kelas UserProfileService untuk tanggung jawab lainnya terkait profil pengguna. Hal tersebut membantu menjaga kohesi dan memisahkan tanggung jawab antara berbagai bagian.
Melengkapi sekaligus perbaikan submisi sebelumnya:
- Refactor:
- Struktur Folder: Struktur folder ini membantu dalam mengatur kode dengan cara yang lebih modular yang dimana setiap folder memiliki tanggung jawab khusus.
- _components, Folder ini berisi komponen-komponen yang dapat digunakan kembali di berbagai bagian aplikasi yang bersifat presentasional atau UI, seperti tombol, formulir, modals, dll.
- _constants, Folder ini berisi konstanta yang digunakan pada aplikasi seperti constant value, URL API, atau configuration settings lainnya.
- _fonts, Folder ini berisi file font dan pengaturan font yang digunakan di aplikasi.
- _helper, Folder ini berisi helper functions yang dapat digunakan di berbagai bagian aplikasi untuk menjalankan specific tasks.
- _hooks, Folder ini berisi custom hooks yang dapat digunakan di berbagai bagian aplikasi untuk mengelola state atau side effects.
- Service Layer: Refactoring yang telah dilakukan dalam kode fetchProfile dan updateProfileData, menggunakan axios untuk Pengelolaan HTTP Request. Refactoring ini bertujuan untuk memisahkan logika pemanggilan API ke dalam service layer yang terpisah dari komponen React, sehingga meningkatkan keterbacaan, pemeliharaan, dan modularitas kode. Berikut merupakan contoh penerapannya:
Penjelasan:
- Pemisahan Logika Pemanggilan API ke Service Layer:
Function fetchProfile: Bertanggung jawab untuk mengambil data profil dari server.
Function updateProfileData: Bertanggung jawab untuk memperbarui data profil di server.
- Penggunaan async/await untuk Asynchronous Calls:
Menggunakan async/await untuk menangani operasi asinkron secara lebih bersih dan mudah dipahami dibandingkan dengan chaining .then().
- Penanganan Error yang Lebih Baik:
Memeriksa apakah respons dari server sukses (response.ok), Membuang error (throw new Error) jika respons gagal, serta juga catch dan mencetak error dengan try/catch block.
Dengan refactoring ini, kode menjadi lebih terstruktur dan mudah dikelola yang memungkinkan pengembangan lebih lanjut dan debugging yang lebih efisien.
Menggunakan axios untuk Pengelolaan HTTP Request:
Dengan menggunakan axios.create(), dapat membuat instance axios yang dapat digunakan di seluruh aplikasi yang akan mengurangi duplikasi kode dan memungkinkan mengatur konfigurasi seperti base URL secara sentral.
Penggunaan interceptors memungkinkan untuk menambahkan header otomatis ke setiap request sebelum request itu dikirim yang berguna dalam kasus seperti menambahkan authorization token ke tiap request.
Dengan memisahkan fungsi handleResponse dan handleError, maka dapat mengelola respon dan error dari request HTTP secara centralized yang akan berguna dalam mengurangi duplikasi kode dan memastikan konsistensi dalam penanganan response dan error.
- Custom Hook: Sebelum dilakukan refactoring, logic untuk mengambil data profil pengguna terintegrasi langsung pada komponen React yang dimana membuat komponen lebih kompleks dan sulit diuji. Setelah dilakukan refactoring menggunakan custom hook useProfile, bertujuan untuk memisahkan logika pengambilan data profil dari komponen React yang membuat kode lebih modular dan mudah dipelihara.
Logika pengambilan data profil pengguna dipisahkan dari komponen React dan ditempatkan dalam custom hook useProfile yang bertujuan untuk membuat komponen React lebih bersih dan fokus pada rendering UI, serta meningkatkan keterbacaan kode.
Menggunakan custom hook memungkinkan penggunaan kembali logika pengambilan data profil di beberapa komponen tanpa duplikasi kode sehingga dapat meningkatkan modularitas dan mengurangi duplikasi kode.
Pada useEffect digunakan untuk menjalankan efek samping (pengambilan data dari API) saat komponen di-mount atau url berubah, kemudian State isLoading digunakan untuk mengelola status loading saat data sedang diambil dari server. Lalu dengan menggunakan .catch untuk menangkap dan mencetak error jika terjadi kesalahan saat pengambilan data.
Sehingga dengan menggunakan custom hook useProfile dapat menciptakan solusi yang lebih modular, reusable, dan maintainable untuk mengelola pengambilan data profil pengguna dalam aplikasi React.
- Komponen Tambahan: Contohnya pada Carousel dan Footer. Refactoring pada Carousel.tsx, awalnya pada kode Carousel.tsx cukup kompleks dengan berbagai komponen dan logika terkait carousel dalam satu file. Kemudian implementasi Refactor-nya adalah terkait modularisasi komponen dengan memisahkan komponen seperti CarouselMainContainer, CarouselThumbsContainer, SliderMainItem, SliderThumbItem, CarouselIndicator, CarouselPrevious, dan CarouselNext ke dalam file terpisah yang bertujuan agar kode menjadi lebih terorganisir, mudah dibaca, dan dikelola sehingga setiap komponen memiliki tanggung jawab yang jelas.
Penggunaan CarouselContext untuk mengelola state dan fungsi terkait carousel sehingga memudahkan pengelolaan state global terkait carousel di seluruh komponen yang membutuhkan. Menggunakan useCallback untuk mengoptimalkan fungsi yang digunakan dalam event handlers sehingga mengurangi re-render yang tidak perlu serta meningkatkan performa aplikasi.
Refactoring pada Footer.tsx, awalnya kode Footer.tsx mencakup keseluruhan markup dan styling dalam satu file. Kemudian implementasi Refactor-nya adalah terkait Customized Components dengan memisahkan CustomLink menjadi komponen tersendiri agar terdapat Reusability dan konsistensi dalam penggunaan link di seluruh aplikasi. Kemudian Penggunaan Chakra UI dengan memanfaatkan komponen dari Chakra UI untuk membangun layout footer sehingga dapat mempercepat pengembangan UI dengan komponen yang sudah teruji, serta memudahkan penyesuaian styling dengan tema yang konsisten.
Comments
Post a Comment