Development - Nafhan Raissa Syandana

Pada Sprint 1 minggu 3 saya melanjutkan Fix Back End Edit Profil dengan mencoba melakukan adjustment karena untuk bagian Get profile telah diselesaikan oleh teman yang lain, sehingga perlu dilakukan beberapa perbaikan disini.

Implementasi kode di atas telah mencakup beberapa best practice dalam pemrograman meskipun masih ada beberapa hal yang dapat diperbaiki. Berikut adalah beberapa penerapan best practice dalam kode tersebut:


  • Single Responsibility Principle (SRP):

ProfileEditAPIView:

Kelas ini bertanggung jawab untuk menangani permintaan profil pengguna.

Metode get(self, request) digunakan untuk mengambil profil pengguna.

Metode put(self, request) digunakan untuk memperbarui profil pengguna.

Tanggung jawabnya adalah berinteraksi dengan permintaan HTTP yang masuk dengan mengambil atau memperbarui profil

pengguna, serta mengembalikan respons yang sesuai.



ProfileSerializer:

Kelas ini bertanggung jawab untuk mengubah objek profil pengguna menjadi representasi yang dapat diserialisasi misalnya adalah JSON dan sebaliknya.

Ini digunakan dalam kelas ‘ProfileEditAPIView’ untuk mengubah data yang diterima dari permintaan HTTP menjadi representasi objek Python yang dapat disimpan dalam database, dan sebaliknya.



Dengan memisahkan tanggung jawab ini, setiap kelas memiliki fokus yang jelas dan tidak bercampur aduk dengan logika lainnya. ProfileEditAPIView fokus pada interaksi dengan permintaan HTTP, sementara ProfileSerializer fokus pada transformasi objek profil menjadi format yang sesuai untuk ditampilkan atau disimpan. Ini adalah contoh penerapan prinsip Single Responsibility Principle (SRP) dalam software design.

  • Object-Oriented (OO) Principles:

Penggunaan Kelas dan Objek dalam Model Django:

Dalam Django, model-model seperti User dan Profile didefinisikan sebagai kelas-kelas Python yang mewakili entitas dalam basis data.

Penggunaan kelas memungkinkan kita untuk mendefinisikan atribut dan metode yang sesuai dengan entitas yang direpresentasikan.

Dalam kode yang diberikan, kelas Profile digunakan untuk merepresentasikan profil pengguna dengan atribut-atribut seperti nama, status, email, dan lain-lain.



Penggunaan Inheritance dalam ‘get_user_model()’:

Di Django, ‘get_user_model()’ digunakan untuk mendapatkan model pengguna yang saat ini aktif yang telah ditentukan

dalam pengaturan proyek.

Penggunaan inheritance di sini memungkinkan aplikasi untuk lebih fleksibel dalam hal penggunaan model pengguna. Jika

di masa depan kita ingin mengganti model pengguna bawaan Django (User) kita hanya perlu mengubah pengaturan proyek

tanpa harus memodifikasi banyak bagian kode aplikasi.

Hal ini juga memungkinkan aplikasi untuk mengikuti prinsip-prinsip desain seperti Polymorphism, di mana memperlakukan

objek User sesuai dengan kelas yang ditentukan oleh ‘get_user_model()’.



Dengan menggunakan konsep-konsep ini, saya dapat mengatur kode dengan lebih terstruktur dan mudah dimengerti. Ini

juga membuat kode lebih mudah untuk dipelihara dan diperluas di masa depan, karena prinsip-prinsip OO memungkinkan

pemisahan logika yang berbeda ke dalam unit-unit yang terpisah dan berinteraksi dengan cara yang jelas dan terorganisir.


  • Open/Closed Principle (OCP)

Terdapat lapisan abstraksi tambahan untuk serializer. Ini memungkinkan kita untuk memperluas fungsionalitas serializer

tanpa harus mengubah kelas dasarnya.



‘BaseProfileSerializer’ adalah kelas dasar yang memiliki implementasi dasar untuk serializer profil. Kemudian, jika kita

perlu memperluas fungsionalitas serializer, saya dapat membuat kelas turunan baru dari ‘BaseProfileSerializer’ dan menambahkan fungsionalitas tambahan yang diperlukan tanpa mengubah kelas dasar tersebut. Dengan cara ini, prinsip OCP diterapkan karena saya dapat memperluas fungsionalitas serializer tanpa mengubah kode yang sudah ada. Dalam hal ini saya menambahkan validasi tambahan untuk memeriksa domain email.



Update Tambahan untuk submisi pada kompetensi Development:

Pada chores dan fix, terdapat beberapa hal yang perlu diperbaiki terkait pada edit profil.

OOP Principle:

~ Abstraction:

Abstraction merupakan proses menyembunyikan detail implementasi dan menampilkan fungsionalitas utama yang dimana membantu mengurangi kompleksitas serta meningkatkan fokus pada business logic yang relevan. Berikut adalah contoh terkait abstraction pada kode yang saya miliki:

> Penggunaan APIView dari Django REST Framework:

APIView menyediakan abstraksi untuk menangani permintaan HTTP pada Django sehingga kita dapat berfokus pada logika spesifik aplikasi. Berikut adalah contoh penerapannya:


> Serializer:
Serializer menyediakan abstraksi untuk mengonversi antara tipe data Python (seperti objek model) serta format JSON yang digunakan pada API. Salah satu contohnya misalnya pada:
Yang dimana kita tidak perlu mengetahui secara detail bagaimana data dikonversi dari objek model menjadi JSON cukup dengan menggunakan serializer.

> Service Layer:
Kelas ProfileUserService dan UserProfileService menyembunyikan detail implementasi business logic yang kompleks seperti misalnya pengambilan dan pengeditan profil pengguna. Penggunaan service layer ini memungkinkan kita untuk mengabstraksi business logic dari layer APIView.


~ Inheritance:
Inheritance merupakan konsep pada OOP dimana sebuah class dapat mewarisi properti serta metode dari class lain sehingga memungkinkan reuse code dan mempermudah addition of new functionality. Berikut adalah contoh terkait Inheritance pada kode yang saya miliki:
> Inherit dari APIView:
Kelas ProfileUserGetAPIView meng-inherit dari APIView yang mana ProfileUserGetAPIView mendapat semua fitur serta metode dari APIView seperti misalnya metode get dan post, dan juga kemampuan untuk mengelola HTTP request. Sehingga saya kemudian hanya perlu menambahkan logika khusus untuk menangani permintaan GET:

> Use of Mixins for Inheritance:
Kelas MustAuthenticateAsAdminMixin, MustAuthenticateAsUserMixin, dan MustAuthenticateMixin menyediakan fungsionalitas tambahan yang dapat digunakan oleh kelas lain. Berikut merupakan contoh penerapannya:
Sehingga dengan menggunakan MustAuthenticateAsAdminMixin, kelas ProfileUserGetAPIView akan mewarisi semua metode serta properti yang didefinisikan pada MustAuthenticateAsAdminMixin, yang mana memberikan fungsionalitas tambahan seperti authentication yang dibutuhkan untuk kepentingan admin.

SOLID Principle:
~ Single Responsibility Principle (SRP):

Pada sebuah class hanya memiliki satu alasan untuk berubah yang dimana class tersebut bertanggung jawab pada satu tugas tertentu. Dalam kode yang saya miliki telah menerapkan SRP. Misalnya, dalam class UserProfileService di file services/user_profile_service.py, class ini bertanggung jawab atas dua tugas terpisah:

get_user_profile: Mengambil data profil pengguna dari basis data.

edit_user_profile: Mengedit data profil pengguna dalam basis data.

Dengan memisahkan fungsi-fungsi ini ke dalam class yang berbeda maka kode menjadi lebih mudah dipahami, dikelola, dan diuji karena setiap class memiliki tanggung jawab yang lebih terfokus.

~ Open/Closed Principle (OCP):

OCP menyatakan sebuah class harus open for extension namun closed for modification. Sehingga kita harus dapat menambahkan fungsionalitas baru tanpa mengubah kode yang telah ada.

Pada kode saya OCP telah diterapkan, misalnya pada class ProfileEditAPIView di file views.py. Meskipun kita menambahkan fitur baru seperti validasi inputan, kita tidak mengubah kode yang sudah ada dalam method put. Validasi inputan baru ditambahkan secara terpisah dalam method put, tanpa mengubah logika pengeditan profil yang sudah ada.

Dengan menerapkan OCP dapat menghindari dampak negatif dari perubahan dalam kode yang sudah ada dan memungkinkan untuk mengembangkan fitur baru dengan aman tanpa merusak fungsionalitas yang sudah ada.

~ Liskov Substitution Principle (LSP):

LSP menyatakan bahwa objek dari superclass dapat diganti dengan objek dari subclass tanpa mengganggu program behavior.

Pada kode saya, kelas Profile dan Pengguna dapat digunakan secara bergantian pada class UserProfileService tanpa mempengaruhi perilaku sistem secara signifikan.

Misalnya jika mengganti model pengguna dengan model pengguna yang baru seperti CustomUser, maka kita masih dapat menggunakan kelas UserProfileService tanpa melakukan perubahan signifikan.

Hal ini karena kelas UserProfileService hanya bergantung pada interface dari kelas Profile dan Pengguna, bukan pada implementasi spesifik dari kelas-kelas tersebut.

Comments