2 min read

Magic

Magic
Photo by Artem Maltsev / Unsplash

Di sini tidak membahas mengenai satu varian kopi, bukan pula bahas sulap, "magic" di sini hanyalah istilah yang umum disebutkan pada keajaiban sebuah bahasa atau framework pemograman.

Kenapa disebut keajaiban karena dari usaha menulis sampai menjadi hasil memang terasa seperti magic, mari lihat kode dari Django + Django Rest Framework ini.

# serializer.py
class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = '__all__'
        
  # views
  class PostListCreate(ListCreateAPIView):
     serializer_class = PostSerializer
     queryset = Post.objects.all()
     
 class PostEdit(RetrieveUpdateDestroyAPIView):
    serializer_class = PostSerializer
    queryset = Post.objects.all()

Kode di atas lebih mirip konfigurasi bukan menulis sebuah kode pada umumnya, tapi dari konfigurasi di atas sudah menghasilkan hasil akhir

  • fungsi list semua Post
  • Insert sebuah Post
  • Detail sebuah Post
  • Update sebuah Post
  • Hapus sebuah Post
  • Validasi yang sudah tercatat di model

Sudah satu fungsi yang sepenuhnya kan? Lalu coba lihat kembali kode di atas, apakah di dalamnya secara eksplisit mengenai daftar yang sudah diselesaikan? Itulah yang biasa disebut "magic" sedikit menulis banyak hasilnya.

Keuntungan.

Seperti contoh di atas keuntungan menggunakan "magic" di sini adalah memangkas banyak waktu, satu fungsi dasar sebuah operasi CRUD bisa diselesaikan dalam beberapa baris kode saja, mengerjakan sebuah projek yang sangat memperhitungkan jumlah fitur dalam rentang waktu yang tidak terlalu lama akan sangat cocok menggunakan pola "magic".

Kekurangan.

Sebagaimana sebuah koin yang ada dua sisi menggunakan "magic" tentu datang dengan konsekuensinya yang tidak terasa di awal namun sangat menggangu di akhir. Dari kode di atas jika di waktu yang akan datang ada penambahan fitur seperti:

  • tambahkan pagination
  • tambahkan kustom validasi
  • tambahkan fungsi authorize atau hanya menampilkan post dari user yang login saja
  • tambahkan kustom response field

Di mana kah semua kebutuhan itu harus kita tulis? Dalam konteks django maka pertanyaan mengerucut kepada:

  • apakah ditambahkan di model?
  • apakah ditambahkan di serializer?
  • apakah ditambahkan di views?

Bagi pengguna django senior mungkin pertanyaan di atas cukup mudah dijawab tapi untuk pemula yang baru mengenal penggunaan "magic" dari generic views bisa sangat membingungkan, bisa dibilang penggunaan magic itu akan sangat cepat dalam proses pembuatan tapi akan melambat ketika seiring waktu ada penambahan fitur.

Eksplisit

Contoh "magic" di atas saya menggunakan GenericView pada DRF yang memang pada fungsinya untuk mengerjakan hal-hal yang seragam saja dan mungkin tidak butuh banyak kustom, tapi seperti yang saya sebut di atas proses akan lambat saat menambahkan fitur di tengah jalan, oleh karena itu saya lebih memilih menulis kode secara explisit.

Dalam django selain menggunakan ClassViews seperti contoh di atas kita bisa menggunakan menggunakan function based views, maka operasional crud di atas bisa diubah menjadi seperti ini

@api_view(['GET', 'POST'])
def list_and_create(request):
    if request.method == 'POST':
       # Validasi sebelum diproses 
       # Persiapkan data 
       # Insert ke database 
       # return 201 jika sukses
    else:
        # get data dari database
        # return 200 jika ada, return 200 tetap dilakukan jika data 0

@api_view(['GET', 'PUT', 'DELETE'])
def detail_update_delete(request, pk):
    if request.method == 'GET':
        # validasi
        # get data dari db berdasarkan PK
        # return 200 jika ada
        # return 404 jika tidak ada
    else if request.method == 'PUT':
        # validasi apakah ada data di db dengan id dari pk
        # return 404 tidak ditemukan
        # validasi input
        # save ke database
        # return 200 jika sukses
    else:
        # validasi apakah ada data di db dengan id dari pk
        # return 404 tidak ditemukan
        # validasi input
        # return 200 jika berhasil

Atau bagi penyuka class based bisa seperti ini

class PostView(APIView):

    def get(self, request):
        pass
    def post(self, request):
        pass
    def put(self, request, pk):
        pass
    def delete(self, request, pk):
        pass

Mau menggunakan yang manapun terlihat perbedaan, entah menggunakan yang function based maupun APIView keduanya memaksa kita untuk menulis kode sesuai kebutuhan, tapi dengan seperti ini walau akan berkurang kecepatan dalam menulis fitur awa tapi dapat benefit:

  • kode jelas perbarisnya untuk apa
  • menambahkan fungsionalitas akan menjadi jelas
  • berkurangnya abstraksi bagi developer baru.