Pengelolaan kompleksitas

Menjaga aplikasi web tetap sederhana bisa menjadi sangat rumit. Dalam modul ini, Anda akan mempelajari cara kerja API web dengan threading dan cara menggunakannya untuk pola PWA umum seperti pengelolaan status.

Simpel dan kompleks

Dalam presentasinya yang berjudul Simple Made Easy, Rich Hickey membahas kualitas hal-hal sederhana versus hal yang rumit. Ia menjelaskan hal-hal sederhana seperti berfokus pada:

"Satu peran, satu tugas, satu konsep, atau satu dimensi."

Namun tekankan bahwa kesederhanaan bukan tentang:

"Memiliki satu instance atau melakukan satu operasi."

Apakah sesuatu itu sederhana atau tidak adalah tentang seberapa berhubungannya hal itu.

Kerumitan berasal dari mengikat, menenun, atau, menggunakan istilah Rich, merangkai banyak hal menjadi satu. Anda dapat menghitung kompleksitas dengan menghitung jumlah peran, tugas, konsep, atau dimensi yang dikelola oleh sesuatu.

Kesederhanaan sangat penting dalam pengembangan perangkat lunak karena kode yang sederhana lebih mudah dipahami dan dikelola. Kesederhanaan juga diperlukan untuk aplikasi web karena dapat membantu membuat aplikasi kita cepat dan dapat diakses dalam setiap konteks yang memungkinkan.

Mengelola kompleksitas PWA

Semua JavaScript yang kita tulis untuk web menyentuh thread utama pada satu titik. Namun, thread utama memiliki banyak kerumitan langsung yang tidak dapat Anda kendalikan, sebagai developer.

Thread utama adalah:

  • Bertanggung jawab untuk menggambar halaman, yang merupakan proses multi-langkah yang kompleks dan melibatkan penghitungan gaya, memperbarui dan menyusun lapisan, serta menggambar ke layar.
  • Bertanggung jawab untuk mendengarkan dan bereaksi terhadap peristiwa, termasuk peristiwa seperti menggulir.
  • Bertanggung jawab untuk memuat dan menghapus muatan halaman.
  • Mengelola media, keamanan, dan identitas. Itu saja sebelum kode yang Anda tulis bahkan dapat dieksekusi pada thread tersebut, seperti:
  • Memanipulasi DOM.
  • Mengakses API sensitif, misalnya, kemampuan perangkat, atau media/keamanan/identitas.

Seperti yang dikatakan Surma dalam bincang-bincang Chrome Dev Summit 2019, rangkaian pesan utamanya memiliki terlalu banyak kerja dan gaji yang kurang.

Namun, sebagian besar kode aplikasi juga berada di thread utama.

Semua kode tersebut menambah kompleksitas thread utama. Thread utama adalah satu-satunya yang dapat digunakan browser untuk menata letak dan merender konten di layar. Oleh karena itu, ketika kode Anda memerlukan semakin banyak daya pemrosesan untuk diselesaikan, kita perlu menjalankannya dengan cepat, karena setiap detik yang diperlukan untuk menjalankan logika aplikasi sama dengan satu detik saat browser tidak dapat merespons input pengguna atau menggambar ulang halaman.

Ketika interaksi tidak terhubung ke input, ketika frame turun, atau ketika terlalu lama menggunakan situs, pengguna akan frustrasi, mereka merasa aplikasi rusak, dan kepercayaan mereka terhadap aplikasi menurun.

Berita buruknya? Menambahkan kompleksitas ke thread utama adalah cara yang hampir pasti untuk mencapai tujuan ini menjadi sulit. Berita bagusnya? Karena yang perlu dilakukan thread utama sudah jelas: thread ini dapat digunakan sebagai panduan untuk membantu mengurangi ketergantungan pada thread utama untuk aplikasi Anda yang lain.

Pemisahan fokus

Ada berbagai jenis pekerjaan yang dilakukan aplikasi web, tetapi secara luas, Anda bisa memecahnya menjadi pekerjaan yang langsung menyentuh UI dan pekerjaan yang tidak. Pekerjaan UI adalah pekerjaan yang:

  • Langsung menyentuh DOM.
  • Menggunakan API yang menyentuh kemampuan perangkat, misalnya, notifikasi atau akses sistem file.
  • Menyentuh identitas, misalnya, penyimpanan sesi, lokal, atau cookie pengguna.
  • Mengelola media, misalnya, gambar, audio, atau video.
  • Memiliki implikasi keamanan yang memerlukan intervensi pengguna untuk disetujui, seperti API serial web.

Pekerjaan non-UI dapat mencakup hal-hal seperti:

  • Kalkulasi murni.
  • Akses data (fetch, IndexedDB, dll.).
  • Kripto.
  • Berkirim pesan.
  • Pembuatan blob atau streaming, atau manipulasi.

Pekerjaan non-UI sering kali dipesan oleh pekerjaan UI: pengguna mengklik tombol yang memicu permintaan jaringan untuk API yang menampilkan hasil terurai yang kemudian digunakan untuk memperbarui DOM. Saat menulis kode, pengalaman end-to-end ini sering dipertimbangkan, tetapi tempat setiap bagian alur tersebut berada biasanya tidak. Batasan antara pekerjaan UI dan pekerjaan non-UI sama pentingnya untuk dipertimbangkan sebagai pengalaman menyeluruh, karena batas tersebut adalah tempat pertama Anda dapat mengurangi kompleksitas thread utama.

Fokus ke satu tugas

Salah satu cara paling mudah untuk menyederhanakan kode adalah memecah fungsi sehingga masing-masing berfokus pada satu tugas. Tugas dapat ditentukan berdasarkan batasan yang diidentifikasi dengan mengikuti pengalaman dari awal hingga akhir:

  • Pertama, tanggapi input pengguna. Ini adalah pekerjaan UI.
  • Selanjutnya, buat permintaan API. Ini adalah pekerjaan non-UI.
  • Berikutnya, uraikan permintaan API. Sekali lagi, ini adalah pekerjaan non-UI.
  • Selanjutnya, tentukan perubahan pada DOM. Ini bisa berupa pekerjaan UI, atau jika Anda menggunakan sesuatu seperti implementasi DOM virtual, itu mungkin bukan pekerjaan UI.
  • Terakhir, buat perubahan pada DOM. Ini adalah pekerjaan UI.

Batasan yang jelas pertama adalah antara pekerjaan UI dan pekerjaan non-UI. Kemudian, ada hal penilaian yang perlu dilakukan: apakah membuat dan mengurai permintaan API satu atau dua tugas? Jika perubahan DOM bukan pekerjaan UI, apakah perubahan tersebut dipaketkan bersama kerja API? Ada di rangkaian pesan yang sama? Di rangkaian pesan lain? Tingkat pemisahan yang tepat di sini adalah kunci untuk menyederhanakan codebase Anda dan berhasil memindahkan sebagian dari thread utama.

Komposisi

Untuk memecah alur kerja end-to-end yang besar menjadi bagian-bagian yang lebih kecil, Anda perlu memikirkan komposisi codebase Anda. Mengambil isyarat dari pemrograman fungsional, pertimbangkan:

  • Mengategorikan jenis pekerjaan yang dilakukan aplikasi Anda.
  • Membangun antarmuka input dan output yang umum untuk mereka.

Misalnya, semua tugas pengambilan API mengambil endpoint API dan menampilkan array objek standar, dan semua fungsi pemrosesan data mengambil dan menampilkan array objek standar.

JavaScript memiliki algoritma clone terstruktur yang ditujukan untuk menyalin objek JavaScript kompleks. Pekerja web menggunakannya saat mengirim pesan dan IndexedDB menggunakannya untuk menyimpan objek. Memilih antarmuka yang dapat Anda gunakan dengan algoritma kloning terstruktur akan membuatnya lebih fleksibel untuk dijalankan.

Dengan mempertimbangkan hal ini, Anda dapat membuat library fungsi composable dengan mengategorikan kode Anda dan membuat antarmuka I/O umum untuk kategori tersebut. Kode composable adalah ciri khas codebase sederhana: bagian yang dikaitkan secara longgar dan dapat dipertukarkan yang dapat "berdekatan" satu sama lain dan saling membangun satu sama lain, berbeda dengan kode kompleks yang sangat terhubung dan karenanya tidak dapat dipisahkan dengan mudah. Dan di web, kode composable dapat menunjukkan perbedaan antara mengerahkan thread utama atau tidak.

Dengan kode composable yang sudah ada, kini saatnya untuk menghapus sebagian dari thread utama.

Menggunakan web worker untuk mengurangi kompleksitas

Web worker, yang merupakan kemampuan web yang sering kali kurang dimanfaatkan, tetapi tersedia secara luas, memungkinkan Anda memindahkan pekerjaan dari thread utama.

Pekerja web mengizinkan PWA menjalankan (beberapa) JavaScript di luar thread utama.

Ada tiga jenis pekerja.

Pekerja khusus, hal yang paling umum dipikirkan saat mendeskripsikan pekerja web, dapat digunakan oleh satu skrip dalam satu instance PWA yang berjalan. Jika memungkinkan, pekerjaan yang tidak secara langsung berinteraksi dengan DOM harus dipindahkan ke pekerja web untuk meningkatkan performa.

Pekerja bersama mirip dengan pekerja khusus, kecuali beberapa skrip dapat membagikannya di beberapa jendela terbuka. Ini memberikan manfaat pekerja khusus, tetapi dengan status bersama dan konteks internal antara jendela dan skrip.

Pekerja bersama dapat, misalnya, mengelola akses dan transaksi untuk IndexedDB PWA dan hasil transaksi siaran di seluruh skrip panggilan agar mereka dapat bereaksi terhadap perubahan.

Pekerja web final adalah salah satu yang dibahas secara ekstensif dalam kursus ini: pekerja layanan, yang bertindak sebagai proxy untuk permintaan jaringan dan digunakan bersama di antara semua instance PWA.

Cobalah sendiri

Saatnya membuat kode. Buat PWA dari awal berdasarkan semua yang telah Anda pelajari dalam modul ini.

Referensi