Software Environment & Architecture — Sprint 5 Blog Azahra

Azahra Andani
Energizer AAA
Published in
7 min readApr 30, 2019

Pada sprint 5 ini, kelompok kami akhirnya berhasil menyelesaikan sprint goal yang sudah kami tetapkan sejak sprint pertama, yaitu sampai pengguna bisa melakukan register, login, dan melihat profil.

Software Environment

Perkuliahan PPL menggunakan satu server yang sama untuk menjalankan aplikasi dari semua kelompok yang ada. Untuk memenuhi semua kebutuhan deployment, PPL menggunakan teknologi docker. Untuk proses pengembangan, kami juga menggunakan tiga environments yang berbeda, yaitu development, staging, dan production. Untuk membantu mempercepat proses pengembangan, kami menggunakan GitLab CI. Ketiga poin di atas akan saya jelaskan di bawah ini.

Docker

Docker adalah salah satu software yang menyediakan layanan teknologi container. Container adalah metode yang digunakan untuk membungkus aplikasi, dari mulai kode sumber dengan segala dependensinya, agar dapat berjalan dengan baik dari sebuah environment ke environment lainnya. Manfaat lain dari penggunaan container adalah memungkinkan berbagai aplikasi untuk berjalan di sebuah server yang sama tanpa mempengaruhi satu sama lain.

Sebelum ada container, pendekatan yang dilakukan adalah dengan menggunakan virtual machine. Setiap virtual machine berisi keseluruhan sistem operasi dan aplikasi yang akan dijalankannya, sehingga sifat isolasi yang ditawarkannya sama dengan container. Perbedaan dari kedua pendekatan tersebut terletak pada abstraksi yang disediakannya. Container melakukan abstraksi pada tingkat aplikasi di mana beberapa container dapat berjalan di sebuah mesin yang sama dengan kernel sistem operasi yang sama. Setiap container berjalan masing-masing sebagai proses yang terpisah. Sementara, virtual machine adalah abstraksi dari tingkat hardware sehingga seakan-akan membuat satu server menjadi beberapa server yang berbeda.

Perbedaan Docker dan Virtual Machine. Sumber: www.docker.com.

Container membutuhkan ruang yang lebih sedikit dari virtual machine di mana biasanya sebuah image container memiliki ukuran puluhan MB, sementara sebuah virtual machine berukuran puluhan GB. Kelebihan lain dari container adalah fleksibilitasnya yang tinggi. Virtual machine membutuhkan waktu lebih lama untuk boot up, layaknya sebuah PC. Container dapat dinyalakan dalam beberapa detik karena sistem operasinya sudah berjalan di server sehingga tidak perlu waktu boot up yang selama virtual machine. Hal ini membuat container dapat dinyalakan dan dimatikan dalam waktu yang cepat sesuai dengan kebutuhan.

Kelemahan yang dimiliki oleh teknologi container adalah masalah keamanan. Oleh karena beberapa container berbagi sistem operasi yang sama, jika ada sebuah masalah keamanan di sistem operasi tersebut maka semua container yang ada akan terpengaruh.

Environments: Development, Staging, Production

Hal penting yang harus diperhatikan dalam pengembangan perangkat lunak adalah ketersediaan servis. Jangan sampai perubahan yang dilakukan pada tahap pengembangan mempengaruhi ketersediaan servis yang sudah ada. Stabilitas environment menjadi sebuah isu yang dapat diatasi oleh separasi. Dalam PPL, kami membagi deployment environment kami menjadi tiga, yaitu:

  1. Development : environment di mana kami mengembangkan fitur di branch yang berbeda-beda. Setiap update dapat di-push langsung ke environment ini.
  2. Staging : environment untuk melakukan merge dari setiap branch yang sudah dites dengan unit test dan cukup stabil. Kegiatan sprint review dilakukan pada environment ini.
  3. Production : environment di mana semua fitur yang sebelumnya ada di staging memiliki behavior yang diharapkan dan disetujui oleh product owner kami. Versi yang di-deploy di environment ini sudah siap digunakan oleh user kami.

Continuous Integration

Dalam pengembangan perangkat lunak secara agile, prinsip pertama yang dimiliki adalah kepuasan pelanggan dengan pemberian produk sedini mungkin secara berkelanjutan. Untuk dapat melakukan hal tersebut, pengembang perlu mengintegrasikan kodenya dengan kode yang sudah ada di repository yang dibagikan dengan tim secara rutin walaupun update yang diberikan hanya sedikit. Integrasi dini ini bermanfaat untuk mengetahui lebih cepat apabila terdapat error.

Tools yang dapat memudahkan kami dalam melakukan hal ini adalah GitLab CI. GitLab CI melakukan automasi proses integrasi dari mulai build, test, dan deployment. Tahap build mengkombinasikan kode sumber dengan semua dependensi yang dibutuhkan. Tahap test melakukan validasi dari behavior kode yang sudah ditulis. Terakhir, deployment melakukan proses deploy ke environment yang sesuai.

CI/CD pipeline ConnectDot.
Tambahan build package backend pada pipeline

Di kelompok kami, Yudhis sudah merancang script untuk melakukan CI/CD pipeline seperti gambar di atas.

stages:
- Cache Cleanup
- Manual Build Dependencies
- Build Dependencies
- Unit Tests
- Build Package Backend
- Build Package Frontend
- Deploy

variables:
CACHE_HOST: yudhistira.erlandinata@kawung.cs.ui.ac.id
BUILD_HOST: ${GCLOUD_VM_HOST}
.......Frontend Build Dependencies Template: &frontend_build_dependencies
stage: Build Dependencies
image: yerlandinata/energizer-devops-alpine:node-ssh
before_script:
- source devops/setup_ssh.sh
script:
- sh devops/frontend/dependency_build.sh

Frontend Dependencies Build:
<<: *frontend_build_dependencies
only:
changes:
- frontend/yarn.lock

Frontend Dependencies Build Manual:
<<: *frontend_build_dependencies
when: manual
......

Stages yang ada pada pipeline kami adalah:

  1. Cache Cleanup : membersihkan cache dependensi yang terdapat di CACHE_HOST.
  2. Manual Build Dependencies : meng-install dependensi pada server kami secara manual, sehingga bersifat opsional. Dilakukan ketika cache cleanup baru dieksekusi untuk mem-build dependensi kembali.
  3. Build Dependencies : meng-install dependensi pada server kami. Stage ini tidak akan dieksekusi jika tidak terdapat perubahan dependensi di file requirements.txt dan yarn.lock.
  4. Unit Tests : melakukan unit test di frontend kemudian backend.
  5. Build Package Backend : melakukan build bagian backend dengan mengunduh dependensi nya terlebih dahulu dari cache.
  6. Build Package Frontend : melakukan build bagian frontend dengan mengunduh dependensi nya terlebih dahulu dari cache.
  7. Deploy : menaruh image yang sudah di-build di environment staging.

Contoh script yang saya sertakan di atas adalah build dependency pada bagian frontend. Nama stage yaitu Build Dependencies. Image adalah image docker yang dieksekusi oleh gitlab runner untuk dapat menjalankan script yang terdapat di gitlab-ci.yml. before_script adalah bagian script yang akan dijalankan sebelum script utama yang dispesifikasikan di script:. Tujuan dipisahkannya before_script dan script adalah agar template Build Dependencies dapat di-extend dengan menggunakan <<: * dan dapat meng-overwrite salah satu bagian before_script dan script. Yang dilakukan pada bagian before_script adalah set up environment variable, sementara bagian script adalah meng-install dependensi.

Frontend Dependencies Build meng-extend template di atasnya dan mengatur waktu eksekusinya hanya ketika terdapat perubahan pada file frontend/yarn.lock. Frontend Dependencies Build Manual juga melakukan hal yang sama dengan Frontend Dependencies Build, hanya saja dilakukan dengan manual ketika developer ingin melakukan hal tersebut.

Software Architecture

Software architecture menggambarkan sebuah sistem dengan komponen-komponen utamanya serta bagaimana semua komponen tersebut berinteraksi satu sama lain. Dalam kata lain, software architecture berperan sebagai blueprint dari sebuah sistem secara abstrak untuk mengatur kompleksitas sistem.

Untuk proyek ConnectDot, kami menggunakan arsitektur sebagai berikut:

Credits: Yudhistira Erlandinata, A3 (Medium: https://medium.com/@yerlandinata).

Dalam pembuatannya, terdapat design principle yang harus diperhatikan agar aspek scalability perangkat lunak dapat dipertahankan. Prinsip-prinsip tersebut di antaranya:

Separation of Concerns

Prinsip ini sudah kami terapkan dengan memisahkan komponen sesuai dengan fungsinya masing-masing:

  • Frontend App berfungsi sebagai komponen yang dijalankan oleh komputer client dan yang berinteraksi langsung oleh user. Komponen ini berkomunikasi dengan banyak komponen lainnya, kecuali database dan email verification service, agar dapat menampilkan data yang dibutuhkan kepada user.
  • Frontend Server berfungsi sebagai layer yang memberikan data HTML, CSS, dan JavaScript kepada frontend app agar kemudian dapat di-render.
  • Image Resizer berfungsi untuk menyediakan gambar yang sudah diatur ulang ukurannya.
  • Image Serving berfungsi sebagai tempat penyimpanan semua gambar dan asset.
  • REST API berfungsi sebagai layer yang menyediakan API untuk mengakses database ConnectDot.
  • JWT Auth Server berfungsi sebagai layer yang menyediakan layanan autentikasi. Sebagai koreksi, komponen ini berkomunikasi dengan Email Verification Service ketika username tidak ditemukan di Users DB.
  • Email Verification Service berfungsi sebagai tempat untuk melakukan verifikasi user dengan email.
  • ConnectDot DB berfungsi sebagai tempat penyimpanan semua data ConnectDot.
  • Users DB berfungsi sebagai tempat penyimpanan data user, yaitu username dan password.

Single Responsibility Principle

Prinsip ini terpenuhi ketika sebuah komponen hanya memiliki satu tanggung jawab. Dengan fungsi yang berbeda-beda yang dimiliki oleh setiap komponen seperti penjelasan di atas, prinsip ini sudah dicoba dipertahankan.

Principle of Least Knowledge (Law of Demeter)

Prinsip ini membatasi pengetahuan yang harus diketahui oleh sebuah komponen mengenai komponen lain. Di dalam ConnectDot, prinsip ini sudah diterapkan di mana setiap komponen hanya harus mengetahui endpoint komponen lain yang dibutuhkan untuk sebuah request.

Do Not Repeat Yourself (functionality)

Sebisa mungkin setiap komponen dalam arsitektur tidak memiliki fungsi yang saling tumpang tindih. Dalam arsitektur ConnectDot, kami mempertahankan agar setiap komponen memiliki fungsi yang berbeda-beda. Sebagai contoh, walaupun image resizer dan image serving sama-sama berurusan dengan gambar, fungsi kedua komponen tersebut berbeda. Image resizer berfungsi untuk menampilkan gambar yang sudah diatur ulang ukurannya dengan sebelumnya memanggil image serving terlebih dahulu. Sementara, image serving hanya berfungsi untuk menyediakan gambar yang tidak memerlukan pengaturan ulang ukuran.

Referensi:

--

--